LLMs आपके कोड के अंदर नहीं पहुँचते – वे आपको एक अनुरोध देते हैं, और आप फंक्शन चलाते हैं। यह सरल तथ्य इस मिथक को बदल देता है कि "मॉडल जादुई रूप से मेरे Python रूटीन को कॉल करता है" और डेवलपर्स को डिबगिंग और सुरक्षा के बारे में फिर से सोचने के लिए मजबूर करता है।
डिस्पैच लूप (dispatch loop), चरण दर चरण
जब किसी लैंग्वेज मॉडल (LLM) को किसी टूल की आवश्यकता होती है, तो वह एक नियतात्मक (deterministic) क्रम का पालन करता है:
- Planning (योजना बनाना) – मॉडल तय करता है कि किसी कार्रवाई की आवश्यकता है (जैसे, "भुगतान वापस करना")।
- Generating a request (अनुरोध उत्पन्न करना) – यह स्ट्रक्चर्ड टेक्स्ट—आमतौर पर JSON—आउटपुट करता है, जो टूल का नाम बताता है और आर्गुमेंट्स (arguments) प्रदान करता है।
- Parsing (पार्सिंग) – आपका ऐप या कोई सहायक फ्रेमवर्क उस टेक्स्ट को पढ़ता है।
- Matching (मिलान करना) – फ्रेमवर्क आपके द्वारा एक्सपोज़ किए गए वास्तविक फंक्शन्स की रजिस्ट्री में उस नाम को खोजता है।
- Validating (सत्यापन करना) – यह जाँचता है कि आर्गुमेंट्स फंक्शन के स्कीमा (schema) से मेल खाते हैं या नहीं और क्या कॉलर (caller) अधिकृत है।
- Executing (निष्पादन करना) – मैच किया गया फंक्शन आपके एनवायरनमेंट में चलता है और काम पूरा करता है।
- Returning (वापस भेजना) – परिणाम को पैक किया जाता है और आगे के तर्क (reasoning) के लिए मॉडल को वापस भेज दिया जाता है।
LLM को एक प्लानर, फ्रेमवर्क को एक डिस्पैचर और फंक्शन को उस वर्कर के रूप में समझें जो वास्तव में डेटा या पैसा स्थानांतरित करता है।
"जादू" वाला मिथक क्यों बना रहता है
अधिकांश डेवलपर्स मॉडल आउटपुट की एक सिंगल लाइन देखते हैं जो फंक्शन कॉल जैसी दिखती है और मान लेते हैं कि मॉडल ने स्वयं ऑपरेशन किया है। प्रोवाइडर डॉक्यूमेंटेशन में "tool calling" शब्द ऐसा लगता है जैसे मॉडल सीधे कोड को इनवोक (invoke) कर रहा हो।
वास्तव में, मॉडल केवल ऐसा टेक्स्ट तैयार करता है जो कॉल का वर्णन करता है। आपका प्रोसेस सारा भारी काम करता है—लुकअप, टाइप चेकिंग, परमिशन लागू करना और एरर हैंडलिंग।
फ्रेमवर्क्स जो प्लंबिंग (plumbing) को छिपा देते हैं
PydanticAI और LangChain जैसी लाइब्रेरीज़ इस लूप को एब्स्ट्रैक्ट (abstract) कर देती हैं ताकि आप बिजनेस लॉजिक पर ध्यान केंद्रित कर सकें। वे स्वचालित रूप से:
- Validate arguments (आर्गुमेंट्स का सत्यापन) एक स्कीमा (जैसे, Pydantic मॉडल) के विरुद्ध करते हैं।
- Enforce permissions (अनुमतियों को लागू करना), यह सुनिश्चित करते हुए कि उपयोगकर्ता टूल को ट्रिगर कर सकता है।
- Retry on failure (विफलता पर पुनः प्रयास), जब कोई टूल एरर देता है तो मॉडल के पास वापस लूप करते हैं।
- Guard against runaway loops (अनियंत्रित लूप से बचाव), लगातार होने वाले टूल कॉल्स की संख्या सीमित करते हैं।
- Maintain conversation state (बातचीत की स्थिति बनाए रखना), टूल के परिणामों को संवाद में जोड़ते हैं।
इन सहायकों के बावजूद, पैटर्न वही रहता है: मॉडल कभी भी कोड निष्पादित (execute) नहीं करता है।
प्रोवाइडर्स से नेटिव टूल-कॉलिंग सपोर्ट
कुछ प्रोवाइडर्स एक "नेटिव" टूल-कॉलिंग इंटरफ़ेस देते हैं जो टूल डेफिनिशन और रिक्वेस्ट फॉर्मेट को मानकीकृत (standardize) करता है। यह इंटीग्रेशन को आसान बनाता है लेकिन डिस्पैच स्टेप को हटाता नहीं है। आपको अभी भी वह कोड लिखना (या इम्पोर्ट करना) पड़ता है जो वास्तव में अनुरोधित ऑपरेशन को चलाता है।
समस्या का नाम बदलने से डिबगिंग आसान हो जाती है
"कन्फ्यूज्ड एजेंट" को दोष देने के बजाय, यह कहें कि समस्या यह है कि "मॉडल रिस्पॉन्स में कोई टूल कॉल नहीं था।" यह अंतर महत्वपूर्ण है:
- No tool call – मॉडल ने सीधे उत्तर दिया या सही फॉर्मेट में अनुरोध उत्पन्न करने में विफल रहा।
- Malformed request – JSON सिंटैक्स के हिसाब से गलत है या आवश्यक फ़ील्ड्स गायब हैं, इसलिए डिस्पैचर इसे अस्वीकार कर देता है।
- Validation failure – आर्गुमेंट्स स्कीमा से मेल नहीं खाते, जिससे निष्पादन से पहले एरर आ जाता है।
विफलताओं को वर्गीकृत करने से आप लूप के प्रत्येक चरण को लॉग कर सकते हैं और सटीक रूप से पता लगा सकते हैं कि चीजें कहाँ पटरी से उतरीं।
एक विश्वसनीय पाइपलाइन के लिए व्यावहारिक सुझाव
- मॉडल आउटपुट को अविश्वसनीय इनपुट मानें। किसी भी साइड-इफेक्ट पैदा करने वाले कोड को कॉल करने से पहले हर अनुरोध को नियतात्मक (deterministic) सत्यापन के माध्यम से चलाएं।
- Raw request को लॉग करें और प्रत्येक सत्यापन चरण के परिणाम को भी। इससे कुछ गलत होने पर एक दोबारा चलाने योग्य (replayable) ट्रेल बन जाती है।
- लगातार होने वाले टूल कॉल्स पर स्पष्ट सीमाएं निर्धारित करें; एक अनियंत्रित लूप संसाधनों को समाप्त कर सकता है या रेट लिमिट को पार कर सकता है।
- प्रत्येक फंक्शन को try/except ब्लॉक में लपेटें जो एक स्ट्रक्चर्ड एरर ऑब्जेक्ट लौटाता है जिसे मॉडल समझ सके, जिससे पुनः प्रयास या ग्रेसफुल फॉलबैक (graceful fallback) को बढ़ावा मिले।
- परमिशन चेक को बिजनेस लॉजिक से अलग रखें। फंक्शन चलने से पहले कॉलर के अधिकारों को सत्यापित करें, विशेष रूप से "delete user" जैसे विशेषाधिकार प्राप्त कार्यों के लिए।
- स्कीमा-संचालित डेफिनिशन का उपयोग करें (जैसे, Pydantic मॉडल) ताकि फ्रेमवर्क उस JSON स्कीमा को ऑटो-जेनरेट कर सके जिसका मॉडल को पालन करना चाहिए।
आगे क्या देखें
जैसे-जैसे प्रोवाइडर्स नेटिव टूल-कॉलिंग APIs को बेहतर बना रहे हैं, रिक्वेस्ट फॉर्मेट के आसपास सख्त कॉन्ट्रैक्ट्स और बेहतर एरर कोड्स की उम्मीद करें। ये बदलाव सत्यापन को आसान बनाएंगे और डेवलपर्स को सख्त सुरक्षा घेरे बनाने की अनुमति देंगे। लाइब्रेरी अपडेट पर नज़र रखें—कई लाइब्रेरीज़ नवीनतम प्रोवाइडर फीचर्स के लिए इन-बिल्ट सपोर्ट जोड़ रही हैं।
निष्कर्ष (Takeaway)
LLM एक परिष्कृत टेक्स्ट जनरेटर है, न कि एक निष्पादक। आपका कोड ही एकमात्र अधिकार बना रहता है जो कार्यों को निष्पादित करता है, और आपके द्वारा बनाया गया (या इम्पोर्ट किया गया) डिस्पैचर वह गेटकीपर है जो उन कार्यों को सत्यापित, अधिकृत और रन करता है। वर्कफ़्लो को फिर से परिभाषित करने से "जादू" का भ्रम दूर हो जाता है, डिबगिंग अधिक सटीक हो जाती है, और वह सुरक्षा अनुशासन लागू होता है जिसकी हर प्रोडक्शन सिस्टम को आवश्यकता होती है।
