LLMs तुमच्या कोडमध्ये शिरत नाहीत – ते तुम्हाला फक्त एक विनंती (request) देतात आणि तुम्ही ती फंक्शन रन करता. ही साधी गोष्ट "मॉडेल जादूने माझे Python रूटीन कॉल करते" या भ्रमाला छेद देते आणि डेव्हलपर्सना डीबगिंग आणि सुरक्षा (security) बद्दल पुन्हा विचार करण्यास भाग पाडते.

डिस्पॅच लूप (dispatch loop), टप्प्याटप्प्याने

जेव्हा लँग्वेज मॉडेलला (LLM) एखाद्या टूलची गरज असते, तेव्हा ते एका निश्चित क्रमाने (deterministic sequence) काम करते:

  1. Planning (नियोजन) – मॉडेल ठरवते की एखाद्या कृतीची आवश्यकता आहे (उदा. "पेमेंट रिफंड करणे").
  2. Generating a request (विनंती तयार करणे) – ते स्ट्रक्चर्ड टेक्स्ट—सहसा JSON—आउटपुट करते, ज्यामध्ये टूलचे नाव आणि आवश्यक आर्ग्युमेंट्स (arguments) असतात.
  3. Parsing (पार्शिंग) – तुमचे ॲप किंवा एखादे सपोर्टिंग फ्रेमवर्क ते टेक्स्ट वाचते.
  4. Matching (जुळवणी) – फ्रेमवर्क तुम्ही उपलब्ध करून दिलेल्या रिअल फंक्शन्सच्या रजिस्ट्रीमध्ये त्या नावाचा शोध घेते.
  5. Validating (पडताळणी) – ते तपासते की आर्ग्युमेंट्स फंक्शनच्या स्कीमाशी (schema) जुळतात का आणि विनंती करणारा वापरकर्ता अधिकृत (authorized) आहे का.
  6. Executing (अंमलबजावणी) – जुळलेले फंक्शन तुमच्या एनव्हायर्नमेंटमध्ये रन होते आणि काम पूर्ण करते.
  7. Returning (परत पाठवणे) – रिझल्ट पॅकेज केला जातो आणि पुढील विचार प्रक्रियेसाठी (reasoning) मॉडेलकडे परत पाठवला जातो.

LLM ला एक 'प्लॅनर' (planner), फ्रेमवर्कला 'डिस्पॅचर' (dispatcher) आणि फंक्शनला प्रत्यक्ष डेटा किंवा पैसे हलवणारा 'वर्कर' (worker) समजा.

"जादू"चा भ्रम का टिकून आहे?

बहुतेक डेव्हलपर्स मॉडेलच्या आउटपुटमधील एक ओळ पाहतात जी फंक्शन कॉलसारखी दिसते आणि असे मानतात की मॉडेलने स्वतःच ती क्रिया केली आहे. प्रोव्हायडर डॉक्युमेंटेशनमधील "tool calling" हा शब्द वाचल्यावर असे वाटते की मॉडेल थेट कोड कॉल करत आहे.

प्रत्यक्षात, मॉडेल फक्त असे टेक्स्ट तयार करते जे कॉलचे वर्णन करते. तुमचे प्रोसेस (process) खरे काम करते—जसे की लूकअप (lookup), टाईप चेकिंग (type checking), परमिशन एनफोर्समेंट (permission enforcement) आणि एरर हँडलिंग (error handling).

प्लंबिंग लपवणारे फ्रेमवर्क्स (Frameworks)

PydanticAI आणि LangChain सारखी लायब्ररीज या लूपला ॲबस्ट्रॅक्ट (abstract) करतात जेणेकरून तुम्ही बिझनेस लॉजिकवर लक्ष केंद्रित करू शकाल. ते आपोआप खालील गोष्टी करतात:

  • Validate arguments – स्कीमाच्या (उदा. Pydantic model) आधारे आर्ग्युमेंट्सची पडताळणी करतात.
  • Enforce permissions – वापरकर्त्याला टूल वापरण्याची परवानगी आहे की नाही याची खात्री करतात.
  • Retry on failure – टूलकडून एरर आल्यास पुन्हा मॉडेलकडे विनंती पाठवतात.
  • Guard against runaway loops – सलग टूल कॉल्सवर मर्यादा आणून अनियंत्रित लूपपासून वाचवतात.
  • Maintain conversation state – संभाषणाचा संदर्भ (state) कायम ठेवतात आणि टूलचे रिझल्ट्स संवादात समाविष्ट करतात.

या सहाय्यकांमुळेही (helpers) पॅटर्न तोच राहतो: मॉडेल कधीही कोड एक्झिक्युट करत नाही.

प्रोव्हायडर्सकडून मिळणारे नेटिव्ह टूल-कॉलिंग सपोर्ट (Native tool-calling support)

काही प्रोव्हायडर्स "नेटिव्ह" टूल-कॉलिंग इंटरफेस देतात जो टूल डेफिनिशन्स आणि रिक्वेस्ट फॉरमॅट्स प्रमाणित (standardize) करतो. यामुळे इंटिग्रेशन सोपे होते, पण डिस्पॅच स्टेप (dispatch step) निघून जात नाही. विनंती केलेली क्रिया प्रत्यक्षात रन करण्यासाठी तुम्हाला कोड लिहावाच लागतो (किंवा इम्पोर्ट करावा लागतो).

समस्येला नवीन नाव दिल्यास डीबगिंग सोपे होते

"Confused agent" ला दोष देण्याऐवजी, "मॉडेलच्या प्रतिसादात कोणतेही टूल कॉल्स नव्हते" असे म्हणा. हा फरक महत्त्वाचा आहे:

  • No tool call – मॉडेलने थेट उत्तर दिले किंवा योग्य फॉरमॅटमध्ये विनंती तयार करण्यात अपयश आले.
  • Malformed request – JSON सिंटॅक्सनुसार चुकीचे आहे किंवा आवश्यक फील्ड्स गहाळ आहेत, त्यामुळे डिस्पॅचर ते नाकारतो.
  • Validation failure – आर्ग्युमेंट्स स्कीमाशी जुळत नाहीत, ज्यामुळे एक्झिक्यूशनपूर्वीच एरर येतो.

त्रुटींचे वर्गीकरण केल्यामुळे तुम्हाला लूपच्या प्रत्येक टप्प्याचा लॉग (log) ठेवता येतो आणि नेमकी चूक कुठे झाली हे शोधता येते.

विश्वसनीय पाइपलाइनसाठी व्यावहारिक टिप्स (Practical tips)

  • मॉडेलच्या आउटपुटला 'अविश्वासार्ह इनपुट' (untrusted input) समजा. कोणताही साइड-इफेक्ट निर्माण करणारा कोड रन करण्यापूर्वी प्रत्येक विनंतीची निश्चित पडताळणी (deterministic validation) करा.
  • Raw request आणि प्रत्येक व्हॅलिडेशन स्टेपचा रिझल्ट लॉग करा. यामुळे काही चुकल्यास पुन्हा तपासण्यासाठी एक ट्रेल (trail) तयार होतो.
  • सलग टूल कॉल्सवर स्पष्ट मर्यादा (explicit limits) ठेवा; अनियंत्रित लूपमुळे रिसोर्सेस संपू शकतात किंवा रेट लिमिट्स (rate limits) लागू होऊ शकतात.
  • प्रत्येक फंक्शनला try/except ब्लॉक मध्ये गुंडाळा (wrap), जे मॉडेलला समजेल असा स्ट्रक्चर्ड एरर ऑब्जेक्ट परत करेल, ज्यामुळे मॉडेलला पुन्हा प्रयत्न करण्यास किंवा सुरक्षित पर्याय (graceful fallback) निवडण्यास मदत होईल.
  • परमिशन चेक्स आणि बिझनेस लॉजिक वेगळे ठेवा. फंक्शन रन होण्यापूर्वी विनंती करणाऱ्याचे अधिकार तपासा, विशेषतः "delete user" सारख्या महत्त्वाच्या कृतींसाठी.
  • Schema-driven डेफिनिशन्स वापरा (उदा. Pydantic models), जेणेकरून फ्रेमवर्क मॉडेलने पाळायचा JSON स्कीमा आपोआप तयार करू शकेल.

पुढे काय पाहावे?

जसे प्रोव्हायडर्स नेटिव्ह टूल-कॉलिंग APIs अधिक प्रगत करतील, तसे रिक्वेस्ट फॉरमॅट्स आणि अधिक माहितीपूर्ण एरर कोड्सची अपेक्षा ठेवा. या बदलांमुळे व्हॅलिडेशन सोपे होईल आणि डेव्हलपर्स अधिक कडक सुरक्षा यंत्रणा (security fences) तयार करू शकतील. लायब्ररी अपडेट्सवर लक्ष ठेवा—अनेक लायब्ररीज नवीन प्रोव्हायडर फीचर्ससाठी इन-बिल्ट सपोर्ट जोडून घेत आहेत.

सारांश (Takeaway)

LLM हा एक प्रगत मजकूर जनरेटर आहे, अंमलबजावणी करणारा (executor) नाही. कृती पार पाडण्याचा एकमेव अधिकार तुमच्या कोडकडेच असतो आणि तुम्ही तयार केलेला (किंवा आयात केलेला) डिस्पॅचर (dispatcher) हा गेटकीपर म्हणून काम करतो, जो त्या कृतींची पडताळणी, अधिकृतता आणि अंमलबजावणी करतो. वर्कफ्लोची ही पुनर्रचना केल्यामुळे "जादू" असा भ्रम दूर होतो, डीबगिंग अधिक अचूक होते आणि प्रत्येक प्रोडक्शन सिस्टमला आवश्यक असलेली सुरक्षा शिस्त लागू होते.