डेवलपर्स अब मरम्मत के प्रयासों को दो तक सीमित करके लार्ज लैंग्वेज मॉडल्स (LLMs) से मिलने वाले malformed JSON को ठीक करने की लागत को नियंत्रण में रख सकते हैं, जैसा कि एक सरल पायथन लूप दिखाता है। यह पैटर्न—जनरेट करना, पार्स करना, वैलिडेट करना, फिर से प्रयास करना, और फिर स्वीकार करना या विफल होना—"शायद-वैलिड JSON" को एक मापने योग्य सफलता दर में बदल देता है और अनियंत्रित टोकन उपयोग को रोकता है।
मरम्मत लूप (repair loop) क्यों महत्वपूर्ण है
LLMs को अक्सर "JSON रिटर्न करें" का निर्देश दिया जाता है, फिर भी आउटपुट में अक्सर सिंटैक्स त्रुटियां, गायब कीज़ (keys), या ऐसे मान (values) होते हैं जो बिजनेस रूल्स को तोड़ देते हैं। एक डाउनस्ट्रीम सिस्टम जो सख्त पेलोड (strict payload) की अपेक्षा करता है, वह ऐसे आउटपुट मिलने पर क्रैश हो सकता है या गलत परिणाम दे सकता है। इन समस्याओं को पकड़ने और सुधारने के व्यवस्थित तरीके के बिना, टीमें या तो उच्च विफलता दर को स्वीकार करती हैं या मॉडल को तब तक बार-बार प्रॉम्प्ट करती रहती हैं जब तक कि वह सही न कर दे, जिससे पैसा बर्बाद होता है।
सत्यापन के तीन स्तर (The three validation layers)
एक विश्वसनीय लूप सत्यापन को इन भागों में विभाजित करता है:
- Syntax – क्या स्ट्रिंग बिल्कुल JSON के रूप में पार्स होती है?
- Shape – क्या टॉप-लेवल ऑब्जेक्ट में ठीक वही अपेक्षित कीज़ (keys) हैं?
- Semantic – क्या वैल्यूज़ डोमेन बाधाओं (domain constraints) का पालन करती हैं (उदाहरण के लिए, एक "category" को पूर्व-निर्धारित सेट से संबंधित होना चाहिए)?
पहले विफल होने वाले स्तर पर ही रुककर, लूप मॉडल को एक सटीक त्रुटि संदेश दे सकता है, जिससे अगले प्रयास में सही सुधार की संभावना नाटकीय रूप से बढ़ जाती है।
न्यूनतम पायथन उदाहरण
निम्नलिखित कोड केवल स्टैंडर्ड लाइब्रेरी का उपयोग करता है। यह एक छोटा स्कीमा (एक डिक्शनरी जिसमें category और summary कीज़ हैं) और अनुमत श्रेणियों की एक निश्चित सूची को परिभाषित करता है।
import json
CATEGORIES = {"bug", "feature", "question"}
def validate(raw: str):
try:
value = json.loads(raw)
except json.JSONDecodeError as exc:
return None, f"syntax: {exc.msg}"
if not isinstance(value, dict):
return None, "shape: root must be an object"
if set(value) != {"category", "summary"}:
return None, "shape: expected category and summary"
if value["category"] not in CATEGORIES:
return None, "semantic: invalid category"
if not isinstance(value["summary"], str) or not value["summary"].strip():
return None, "semantic: summary must be text"
return value, None
मरम्मत लूप स्वयं प्रयासों पर एक सख्त सीमा लगाता है:
MAX_ATTEMPTS = 2
raw = model_response # initial LLM output
for attempt in range(MAX_ATTEMPTS + 1):
value, error = validate(raw)
if error is None:
break
if attempt == MAX_ATTEMPTS:
raise RuntimeError(f"failed after {MAX_ATTEMPTS} retries: {error}")
# Send the error and schema back to the model for a fix
raw = ask_model_to_repair(raw, error)
यदि JSON पहले प्रयास में ही सत्यापन पास कर लेता है, तो लूप तुरंत समाप्त हो जाता है। अन्यथा यह फिर से प्रयास करता है, मॉडल को एक संक्षिप्त पेलोड देता है: मूल आउटपुट, सटीक त्रुटि स्ट्रिंग, और अपेक्षित स्कीमा। दो असफल प्रयासों के बाद प्रक्रिया एक स्पष्ट अपवाद (exception) के साथ रुक जाती है।
लागत प्रभावी मरम्मत के लिए दो नियम
मरम्मत प्रॉम्प्ट्स को संक्षिप्त रखें – इसमें केवल रॉ JSON, त्रुटि संदेश और स्कीमा शामिल करें। एक लंबा चैट इतिहास जोड़ने से टोकन का उपयोग बढ़ जाता है और यह मॉडल को भ्रमित कर सकता है, जिससे सटीकता में सुधार किए बिना प्रति प्रयास लागत बढ़ जाती है।
सत्यापन को फैक्ट-चेकिंग से अलग रखें – पार्सर संरचनात्मक समस्याओं का पता लगा सकता है, लेकिन यह सत्यापित नहीं कर सकता कि "summary" कथन सत्य है या नहीं। फैक्ट-चेकिंग बाद के चरण में होनी चाहिए; किसी गलत दावे को "मरम्मत" करने का प्रयास केवल झूठ को अधिक साफ-सुथरा बनाता है।
सफलता को मापना
प्रत्येक प्रयास के त्रुटि प्रकार (syntax, shape, semantic) और लूप सफल हुआ या नहीं, इसका लॉग रखना एक ठोस मेट्रिक प्रदान करता है: सीमित प्रयासों के भीतर उपयोगी बनने वाले LLM रिस्पॉन्स का अनुपात। टीमें समय के साथ इसे ट्रैक कर सकती हैं, प्रॉम्प्ट शैलियों की तुलना कर सकती हैं, या विभिन्न स्कीमा परिभाषाओं के साथ प्रयोग कर सकती हैं।
संभावित नुकसान
लूप को सीमित करने का मतलब है कि सीमा तक पहुँचने के बाद कुछ malformed आउटपुट को हटा दिया जाएगा, जिससे कुल विफलता दर बढ़ सकती है यदि मॉडल की मूल गुणवत्ता कम है। ऐसे वातावरण में जहाँ हर रिस्पॉन्स महत्वपूर्ण है, डेवलपर्स अतिरिक्त टोकन की कीमत पर उच्च रिट्राय सीमा (retry ceiling) पसंद कर सकते हैं। ट्रेड-ऑफ स्पष्ट है: उच्च कवरेज के लिए अधिक लागत, या एक अनुमानित सीमा के साथ सख्त बजट।
आगे क्या देखें
- मरम्मत के लिए प्रॉम्प्ट इंजीनियरिंग – त्रुटि संदेश के प्रारूप को बेहतर बनाने से आवश्यक रिट्राइज़ की संख्या कम हो सकती है।
- वैकल्पिक पार्सर्स – कुछ लाइब्रेरीज़ टॉलरेंट पार्सिंग प्रदान करती हैं जो छोटी समस्याओं को ऑटो-करेक्ट कर सकती हैं; एक सीमित लूप बनाम उनकी लागत की तुलना करना सार्थक है।
- मॉडल अपडेट्स – नए LLM वर्ज़न डिफ़ॉल्ट रूप से अधिक साफ JSON बना सकते हैं, जिससे संभावित रूप से रिट्राय सीमा को और कम किया जा सकता है।
एक सीमित JSON मरम्मत लूप डेवलपर्स को अनियंत्रित लागत के बिना धुंधले LLM आउटपुट को विश्वसनीय डेटा में बदलने के लिए एक व्यावहारिक टूल देता है। सत्यापन को एक प्राथमिक चरण के रूप में मानकर और रिट्राइज़ को सीमित करके, टीमें बजट और डाउनस्ट्रीम सिस्टम दोनों को खुश रख सकती हैं।
