Skip to content
This page has been auto-translated and may contain errors.View in English

एजेंट्स

docs.scrimba.com

एक एजेंट एक मॉडल है जो एक लूप में चलता है, अगले टूल को कॉल करने का चयन करता है जब तक कि कार्य पूरा न हो जाए। इस अध्याय का बाकी हिस्सा यह है कि इसका मतलब क्या है, यह कहां काम आता है, और यह कहां चुपचाप खर्च करता है।

एजेंट लूप

टूल उपयोग में मॉडल ने एक फ़ंक्शन को कॉल किया और आपने परिणाम वापस भेजा। लेकिन कुछ कार्यों में कई चरण होते हैं, और आप पहले से चरणों को नहीं जानते हैं। "सबसे सस्ती उड़ान खोजें और इसे बुक करें" का मतलब खोजना, तुलना करना, कैलेंडर जांचना, फिर बुक करना हो सकता है, और मॉडल को यह क्रम जैसे-जैसे बढ़ता है वैसे ही काम करना पड़ता है।

तो एक एकल टूल कॉल को संभालने की जगह, आप पूरी चीज़ को एक लूप में रखते हैं। यह दोहराया जाने वाला चक्र एजेंट लूप है, एक बार बार-बार तब तक जब तक कार्य पूरा न हो जाए:

  1. कॉनवर्सेशन और उपलब्ध टूल्स को मॉडल को भेजें।
  2. मॉडल या तो एक टूल को कॉल करता है या एक अंतिम उत्तर देता है।
  3. अगर इसने एक टूल को कॉल किया, तो इसे चलाएं, परिणाम को कॉनवर्सेशन में जोड़ें, और चरण 1 पर वापस जाएं।
  4. अगर इसने एक अंतिम उत्तर दिया, तो रुकें।

प्रत्येक बार मॉडल सब कुछ देखता है जो अब तक हुआ है, पिछले टूल परिणामों सहित, और अगला कदम तय करता है। यह टूल उपयोग से पूरी तरह अलग है: आप तब तक लूप करते रहते हैं जब तक मॉडल को संतुष्टि न हो कि वह पूरा हो गया है।

असली बदलाव यह है कि कौन स्टीयर कर रहा है। अब तक के हर अध्याय में, आपका कोड कंट्रोल फ्लो तय करता था: आपने चुना कि मॉडल को कब कॉल करें, कब टूल चलाएं, अगला क्या हो। एक एजेंट वह निर्णय मॉडल को सौंप देता है। लूप बार-बार पूछता है "अगला क्या होना चाहिए?" और मॉडल की भविष्यवाणी हर बार उत्तर है। आप नियंत्रण को लचीलेपन के लिए व्यापार करते हैं, और यह व्यापार पहुंच और जोखिम दोनों का स्रोत है।

नीचे, कुछ नया नहीं हो रहा है। यह बढ़ते संदर्भ पर समान भविष्यवाणी है, टूल-उपयोग राउंड-ट्रिप दोहरी। मॉडल एक योजना तैयार नहीं करता है और इसका पालन नहीं करता है। प्रत्येक बार यह अगला एकल सर्वोत्तम कदम की भविष्यवाणी करता है जो वह अभी देख सकता है, फिर लूप फिर से चलता है।

जब यह काम करता है, तो यह एक लक्ष्य की ओर तर्क करने जैसा लगता है। जब यह नहीं होता है, तो एजेंट अपने आप पर लूप करता है या एक डेड एंड पर भटकता है, क्योंकि सिस्टम का कोई हिस्सा भी समग्र योजना को नहीं रखता है।

Junoएजेंट लूप एक एजेंट लूप-रिपीट किया गया टूल-उपयोग लूप है: कॉनवर्सेशन और टूल्स भेजें, मॉडल एक टूल को कॉल करता है या एक अंतिम उत्तर देता है, आप किसी भी टूल को चलाते हैं और परिणाम वापस खिलाते हैं, और आप फिर से तब तक जाते हैं जब तक यह उत्तर न दे। प्रत्येक बार मॉडल सभी पूर्व परिणामों को देखता है और अगला कदम चुनता है। सादे टूल उपयोग पर केवल नया विचार लूप करना है, न कि एकल कॉल को संभालना।

टूल उपयोग में आपने एक कॉल को संभाला और परिणाम लौटाया। एक एजेंट वह राउंड-ट्रिप है जो एक लूप में लपेटा गया है, तब तक चलाया जाता है जब तक मॉडल तय न करे कि यह किया जा चुका है। वह लूप एजेंट लूप है। यहाँ कदम है: चरणों के अनुक्रम को हार्डकोड करना बंद करें और मॉडल को प्रत्येक बार अगला चुनने दें।

चक्र चार चरण है:

  1. कॉनवर्सेशन प्लस टूल सूची को मॉडल को भेजें।
  2. मॉडल या तो टूल कॉल या एक अंतिम टेक्स्ट उत्तर के साथ प्रतिक्रिया करता है।
  3. अगर इसने टूल्स मांगे, तो उन्हें चलाएं, प्रत्येक परिणाम को कॉनवर्सेशन में जोड़ें, और लूप करें।
  4. अगर इसने उत्तर दिया, तो रुकें और लौटें।

तंत्र जो इसे काम करता है वह यह है कि मॉडल प्रत्येक बार पूरी बढ़ती हुई कॉनवर्सेशन देखता है: आपका मूल अनुरोध, हर टूल कॉल जो इसने किया, और हर परिणाम जो वापस आया। यह संचित संदर्भ एजेंट की एकमात्र मेमोरी है। प्रत्येक भविष्यवाणी अब तक के पूरे इतिहास पर शर्त रखी गई है, जिसका अर्थ है कि यह चरणों को जोड़ सकता है जो पहले परिणामों पर निर्भर हैं।

एक विवरण जो जल्दी नाम देने योग्य है: चरण 2 एक नहीं, बल्कि एक बार में कई टूल कॉल वापस कर सकता है। जब कॉल एक दूसरे पर निर्भर नहीं होते हैं, जैसे तीन शहरों में मौसम की जांच करना, मॉडल एक एकल मोड़ पर सभी तीन का अनुरोध कर सकता है और आप उन्हें एक साथ चला सकते हैं। जब कोई कॉल पिछले एक के परिणाम की आवश्यकता होती है, तो मॉडल को अगले मांगने से पहले उस परिणाम के लिए इंतजार करना पड़ता है, इसलिए ये अलग-अलग बार पर आते हैं। लूप दोनों को संभालता है: इस बार जो भी कॉल आए, उन सभी परिणामों को खिलाएं, और फिर से भविष्यवाणी करें।

कहीं भी इसके अंदर कोई वैश्विक योजना नहीं है। मॉडल पूरे कार्य के नक्शे से नहीं, बल्कि वह सर्वोत्तम अगला कदम की भविष्यवाणी करता है जो वह अभी देख सकता है। यह एक एजेंट और निश्चित पाइपलाइनों के बीच का अंतर है जो आपने पहले लिखे हैं, और यह है कि क्यों एक ही लूप जो अनुसंधान चरणों को जोड़ सकता है अपनी पूंछ का पीछा भी कर सकता है।

Junoएजेंट लूप एक एजेंट लूप में टूल-उपयोग राउंड-ट्रिप है: कॉनवर्सेशन प्लस टूल्स भेजें, मॉडल टूल्स को कॉल करता है या उत्तर देता है, आप टूल्स को चलाते हैं और परिणाम वापस खिलाते हैं, दोहराएं जब तक यह उत्तर न दे। बढ़ती कॉनवर्सेशन एजेंट की एकमात्र मेमोरी है, इसलिए प्रत्येक कदम इससे पहले के हर परिणाम पर शर्त रखा गया है। एक बार कई स्वतंत्र टूल कॉल एक बार में वापस कर सकता है, या एक समय में जब प्रत्येक अंतिम पर निर्भर हो। कहीं कोई वैश्विक योजना नहीं रहती है: हर कदम एक ताज़ा अगला-कदम अनुमान है।

एक एजेंट टूल-उपयोग राउंड-ट्रिप है जो एक लूप में रखा गया है और पहिया सौंपा गया है, एजेंट लूप: मॉडल प्रत्येक बार अगला टूल चुनता है, आप इसे निष्पादित करते हैं, आप परिणाम वापस खिलाते हैं, और आप फिर से तब तक जाते हैं जब तक यह एक कॉल की जगह एक अंतिम उत्तर उत्सर्जित करता है। लूप चार चरण है और यह दिलचस्प हिस्सा नहीं है। दिलचस्प हिस्सा यह है कि आर्किटेक्चर क्या देता है और नहीं देता है।

चक्र:

  1. चलती हुई कॉनवर्सेशन प्लस टूल स्कीमा भेजें।
  2. मॉडल टूल कॉल या एक अंतिम उत्तर लौटाता है।
  3. किसी भी कॉल को चलाएं, परिणाम जोड़ें, लूप करें।
  4. एक अंतिम उत्तर पर, लौटें।

एक एकल बार कई टूल कॉल वापस कर सकता है। मॉडल समानांतर कॉल उत्सर्जित करता है जब यह उन्हें स्वतंत्र मानता है (तीन लुकअप उनके बीच कोई डेटा निर्भरता के साथ), और क्रमबद्ध कॉल पार बारों पर जब एक को दूसरे के आउटपुट की जरूरत होती है। आप इसे बाहर से बाध्य नहीं कर सकते: क्या काम समानांतर है यह मॉडल का कॉल है जो यह कार्य मानता है, इसलिए एक कार्य आप समानांतर सोचते हैं क्रमबद्ध वापस आ सकता है और धीमा हो सकता है, और जो आप अनुक्रमिक सोचते हैं एक बैच के रूप में वापस आ सकता है आपको एक साथ चलाने के लिए तैयार होना चाहिए।

यहाँ लोड-असर करने वाली तथ्य, वह जो हर विफलता मोड को वापस आता है। कोई वैश्विक योजना नहीं है। मॉडल कार्य का नक्शा नहीं रखता है और उसके विरुद्ध निष्पादित नहीं करता है। प्रत्येक बार यह वर्तमान कॉनवर्सेशन से अगला कदम की भविष्यवाणी करता है, और वह कॉनवर्सेशन सिस्टम की संपूर्ण स्थिति है, आपका प्रॉम्प्ट प्लस हर कॉल और परिणाम अब तक, संचित।

हर कदम पिछले कदम पर विश्वास करता है, कुछ भी पूरे को जांच नहीं करता। यही है कि क्यों एक एजेंट जो एक लक्ष्य की ओर तर्क करता है दिखता है वास्तव में स्थानीय रूप से प्रशंसनीय अनुमानों का एक अनुक्रम ले रहा है जो, जब यह काम करता है, जोड़ता है।

परिणाम को आंतरीकरण करने के लिए अब: क्योंकि स्थिति केवल बढ़ती प्रतिलिपि है और हर कदम इस पर शर्त रखा गया है, एक प्रारंभिक गलत टूल परिणाम को ठीक नहीं किया जाता है, इसे बनाया जाता है। त्रुटि आगे की ओर फैलती है और मिश्रित होती है, और लूप का कोई हिस्सा नोटिस करने के लिए स्थित नहीं है। एजेंट पर विश्वसनीयता काम ज्यादातर उस एक संपत्ति के विरुद्ध लड़ रहा है।

Junoएजेंट लूप एक एजेंट लूप में टूल-उपयोग राउंड-ट्रिप है मॉडल स्टीयरिंग के साथ: यह अगला टूल चुनता है, आप इसे चलाते हैं, आप परिणाम वापस खिलाते हैं, दोहराएं जब तक यह उत्तर न दे। पूरी स्थिति बढ़ती प्रतिलिपि है, और कहीं भी कोई वैश्विक योजना नहीं है, केवल अगला-कदम अनुमानों की एक श्रृंखला प्रत्येक अंतिम पर शर्त रखी गई है। एक बार समानांतर कॉल लौटा सकता है जब मॉडल उन्हें स्वतंत्र मानता है या अनुक्रमिक जब वे एक दूसरे पर निर्भर करते हैं, और आप नियंत्रण नहीं करते कि कौन सा। एक चीज़ पकड़ें: हर कदम पिछले कदम पर विश्वास करता है, इसलिए एक प्रारंभिक गलत परिणाम आगे की ओर मिश्रित होता है कुछ भी पूरे को जांचते हुए।

न्यूनतम एजेंट

यहाँ लूप कोड में है। यह टूल उपयोग से टूल परिभाषाओं और कार्यान्वयनों को पुनः उपयोग करता है और एक लूप में लपेटता है जो तब तक चलता है जब तक मॉडल टूल्स मांगना बंद नहीं करता।

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # कोई टूल नहीं चाहता: यह अंतिम उत्तर है

        # हर अनुरोधित टूल को चलाएं और परिणाम वापस खिलाएं
        for call in calls:
            args = json.loads(call.function.arguments)
            result = tool_impls[call.function.name](args)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "रुक गया: एजेंट अपनी कदम सीमा तक पहुंच गया।"  # सुरक्षा जाल

इसे ऊपर से नीचे पढ़ें: मॉडल को कॉल करें, इसके संदेश को कॉनवर्सेशन में धकेलें, और अगर इसने टूल्स मांगे, तो उन सभी को चलाएं और परिणाम जोड़ें, फिर फिर से लूप करें। जब मॉडल एक टूल कॉल की जगह टेक्स्ट लौटाता है, तो वह टेक्स्ट अंतिम उत्तर है और आप इसे लौटाते हैं।

max_steps मान एक कदम सीमा सेट करता है, सुरक्षा जाल जो लूप को दूर नहीं दौड़ने देता है, जो अगला अनुभाग है। यहाँ आकार एक प्रदाता के SDK से मेल खाता है; फ़ील्ड नाम प्रदाताओं में भिन्न होते हैं, लेकिन लूप हर जगह एक जैसा है।

Junoन्यूनतम एजेंट एक न्यूनतम एजेंट एक मॉडल कॉल के चारों ओर एक लूप है: मॉडल को चलाएं, यह जो टूल्स चाहता है उन्हें चलाएं, परिणाम वापस खिलाएं, दोहराएं। जब मॉडल एक टूल कॉल की जगह टेक्स्ट लौटाता है, तो वह टेक्स्ट अंतिम उत्तर है। कदम सीमा एक आवश्यक सुरक्षा जाल है, न कि एक अतिरिक्त जो आप बाद में जोड़ते हैं।

यहाँ लूप कोड में है, टूल उपयोग से टूल परिभाषाओं और कार्यान्वयनों को पुनः उपयोग करते हुए। यह तब तक चलता है जब तक मॉडल टूल्स मांगना बंद नहीं करता या कदम कैप से टकराता है।

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # अंतिम उत्तर

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # विफलता को सामने लाएं, क्रैश न करें
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "रुक गया: एजेंट अपनी कदम सीमा तक पहुंच गया।"

आकार एक प्रदाता का SDK है और फ़ील्ड नाम अलग-अलग हैं, लेकिन हर लूप में ये हिस्से हैं: मॉडल का संदेश जोड़ें, शाखा करें कि क्या इसने टूल्स मांगे, अनुरोधित लोगों को चलाएं, हर परिणाम को एक tool संदेश के रूप में वापस खिलाएं इसके कॉल आईडी के लिए कुंजी।

सादे संस्करण पर बनाने लायक एक बदलाव टूल के चारों ओर try/except है। जब कोई टूल विफल हो, तो अपवाद को लूप को नहीं मारने दें। इसे पकड़ें और त्रुटि को मॉडल को टूल परिणाम के रूप में वापस खिलाएं। मॉडल फिर अपने अगले मोड़ पर "वह लुकअप विफल हुआ" को पढ़ सकता है और अनुकूल हो सकता है: अलग तर्कों के साथ फिर से प्रयास करें, दूसरे टूल को आजमाएं, या उपयोगकर्ता को बताएं कि यह कार्य पूरा नहीं कर सका। क्रैश मॉडल को ठीक होने का कोई मौका नहीं देता है; यह त्रुटि-परिणाम पैटर्न इसे लूप में अभिनय करने के लिए जानकारी के साथ रखता है।

दो चीज़ें इस रूप में ट्रैक करने के लिए जैसे यह चलता है। सबसे पहले, कॉनवर्सेशन केवल बढ़ता है। हर बार मॉडल का संदेश और हर टूल परिणाम जोड़ता है, इसलिए चरण पाँच तक मॉडल चरण एक से चार सब कुछ फिर से पढ़ रहा है। यह एजेंट की मेमोरी है और यह भी इसका बिल है: प्रत्येक कदम पूरी संचित संदर्भ को फिर से भेजता है, इसलिए कार्य के साथ-साथ कदम प्रति टोकन लागत बढ़ती है। एक दस-कदम एजेंट दस सस्ते कॉल नहीं है, यह एक बढ़ती हुई प्रतिलिपि पर दस कॉल है।

दूसरा, वह वृद्धि ही है क्यों max_steps अनंत लूप को रोकने से परे महत्वपूर्ण है। इसे कार्य के विरुद्ध चुनें। एक मौसम सवाल को दो या तीन कदम चाहिए; एक अनुसंधान कार्य दस चाहता है। कैप को एक स्वस्थ रन में थोड़ा ऊपर सेट करें, इसलिए एक वास्तविक रूप से लंबा कार्य समाप्त कर सकता है लेकिन एक फंसा हुआ सब कुछ अभी भी आपके बजट को नष्ट करने से पहले काट दिया जाता है।

Junoन्यूनतम एजेंट लूप है: मॉडल का संदेश जोड़ें, शाखा करें कि क्या इसने टूल्स मांगे, उन्हें चलाएं, हर परिणाम को एक tool संदेश के रूप में वापस खिलाएं। टूल कॉल को try/except में लपेटें और क्रैश की जगह त्रुटियों को वापस खिलाएं, इसलिए मॉडल फिर से प्रयास कर सकता है या ठीक हो सकता है। देखें कि कॉनवर्सेशन केवल बढ़ता है: हर कदम पूरी प्रतिलिपि को फिर से भेजता है, इसलिए कार्य चलता है क्योंकि कदम प्रति टोकन लागत बढ़ती है। max_steps को कार्य के विरुद्ध सेट करें, एक स्वस्थ रन से थोड़ा ऊपर।

लूप, टूल उपयोग से टूल परत को पुनः उपयोग करता है। एक प्रदाता के SDK आकार, फ़ील्ड नाम अलग-अलग, संरचना नहीं।

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # मॉडल इसे पढ़ता है और अगले बार अनुकूल हो सकता है
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "रुक गया: एजेंट अपनी कदम सीमा तक पहुंच गया।"

सादा लूप सही है और अशिप्य है, और दोनों के बीच का अंतर जहाँ यह अनुभाग रहता है। इस कोड के तीन गुण उत्पादन में काटते हैं।

त्रुटियों को सामने लाएं, कभी क्रैश न करें। try/except एक विफल टूल को मॉडल को परिणाम के रूप में खिलाता है जो वह पढ़ सकता है। यह सही है, लेकिन समझें कि आप क्या कर रहे हैं: आप मॉडल को एक त्रुटि स्ट्रिंग सौंप रहे हैं और विश्वास कर रहे हैं कि यह समझदारी से ठीक हो जाएगा। यह एक ही गलत कॉल को फिर से आजमा सकता है, या एक अलग दृष्टिकोण बना सकता है, या माफी माँग सकता है और बंद कर सकता है।

त्रुटियों को वापस खिलाना एजेंट को जीवित रखता है; यह पुनरुद्धार को विश्वसनीय नहीं बनाता है। किसी भी लोड-असर के लिए, प्रति टूल पुनः प्रयास कैप करें और दोहराई गई विफलता को एक टर्मिनल स्थिति के रूप में मानें जो आप संभालते हैं, न कि एक लूप जो मॉडल को अनुभव से हल करता है।

प्रतिलिपि केवल बढ़ती है, और वह दो मिश्रित लागत हैं। टोकन लागत प्रति कदम बढ़ता है क्योंकि हर कॉल पूरी संचित इतिहास को पुनः भेजता है, इसलिए लंबा रन एक सपाट नहीं, हर बार एक उठता हुआ बिल देता है। और प्रतिलिपि जितनी लंबी है, मॉडल अगले कदम को तय करने के लिए पुरानी टूल आउटपुट को पढ़ रहा है, जो ठीक है जहाँ संदर्भ विंडो अध्याय का मध्य में खोया प्रभाव काटने शुरू करता है, जहाँ एक मॉडल लंबे संदर्भ के बीच में दफन की गई जानकारी को कम करता है: प्रारंभिक निर्देश जो एजेंट को बाधा देना चाहिए, संचित परिणामों के तहत डूब जाते हैं और कम किए जाते हैं। लंबे एजेंट जोर से विफल नहीं होते हैं, वे बहते हैं।

max_steps एक बजट है, एक बग गार्ड नहीं है। यह मौजूद है क्योंकि मॉडल रुकना तय करता है और गलत तय कर सकता है: एक कदम पर लूप करें, दो टूल्स के बीच पिंग-पॉन्ग करें, एक डेड एंड का पीछा करें।

संख्या एक असली लागत छत है। सबसे बुरी स्थिति खर्च मोटे तौर पर max_steps गुणा एक पूर्ण-संदर्भ कॉल की लागत रन के अंत के पास है, इसलिए एक संदर्भ-भारी कार्य पर एक उदार कैप एक उदार बिल है। सबसे लंबे वैध रन प्लस मार्जिन से सेट करें, अलर्ट करें जब रन नियमित रूप से इसे हिट करते हैं (यह एक संकेत है कि एजेंट फंसा है, सीमा बहुत कम नहीं है), और एक एजेंट को पेपर के ऊपर करने के लिए इसे उठाने का विरोध करें जो पूरा नहीं कर सकता।

Junoन्यूनतम एजेंट सादा लूप सही है और अशिप्य है। टूल त्रुटियों को वापस खिलाएं इसलिए मॉडल अनुकूल हो सकता है, लेकिन पुनः प्रयास को कैप करें और दोहराई गई विफलता को टर्मिनल के रूप में मानें, क्योंकि त्रुटि को सामने लाना पुनरुद्धार को विश्वसनीय नहीं बनाता है। प्रतिलिपि केवल बढ़ती है, इसलिए प्रति-कदम टोकन लागत बढ़ता है और आपके प्रारंभिक निर्देश पुरानी परिणामों के नीचे दफन हो जाते हैं जब तक एजेंट बहता है। max_steps एक लागत छत है, बग गार्ड नहीं: इसे सबसे लंबे असली रन प्लस मार्जिन के लिए आकार दें, और जब रन इसे नियमित रूप से हिट करते हैं, एजेंट फंसा है, तो संख्या को सामान्य रूप से न बढ़ाएं।

रुकना और सुरक्षा उपाय

एक लूप जो मॉडल को रुकना तय करता है विफल हो सकता है। यह उपकरणों को हमेशा के लिए कॉल कर सकता है, अपने आप को दोहरा सकता है, या एक डेड एंड का पीछा कर सकता है। क्योंकि हर कदम एक मॉडल कॉल है जो टोकन द्वारा बिल किया जाता है, एक भागते हुए एजेंट पैसे और समय को तेज़ी से जलाते हैं।

तो सुरक्षा उपाय, जो लूप के चारों ओर सीमाएँ होती हैं, डिज़ाइन का हिस्सा हैं, न कि एक पॉलिश चरण जो आप अंत में जोड़ते हैं:

  • एक कदम सीमा। लूप की संख्या को कैप करें, max_steps तरीका। जब यह हिट हो, रुकें और लौटें।
  • टूल इनपुट को सत्यापित करें। मॉडल तर्क चुनता है, इसलिए असली परिणाम वाली किसी भी चीज़ को चलाने से पहले उन्हें जांचें।
  • सीमा करें कि उपकरण क्या कर सकते हैं। एजेंट को सबसे कम शक्ति दें जिसे उसे चाहिए। एक टूल जो पढ़ता है वह एक जैसा है जो हटाता है।
  • लागत देखें। कई मॉडल कॉल प्रति कार्य तेज़ी से गुणा करते हैं, इसलिए टोकन को ट्रैक करें और एक बजट सेट करें।

इन्हें जोड़ने वाला धागा: मॉडल पथ को तुरुप कर रहा है, इसलिए आप सीमाएँ रखते हैं जो यह नहीं होगा। मान लें कि एजेंट कम से कम एक बार गलत काम करेगा, और वह जीवित रहेगा।

Junoरुकना और सुरक्षा उपाय एक एजेंट अपने रुकने के बिंदु को तय करता है, इसलिए यह हमेशा के लिए लूप कर सकता है, और हर लूप लागत टोकन। हमेशा एक कदम सीमा सेट करें, मॉडल जो तर्क चुनता है उन्हें सत्यापित करें, और उपकरणों को सबसे कम शक्ति दें जिसे उन्हें चाहिए। लागत को ट्रैक करें, क्योंकि कई मॉडल कॉल प्रति कार्य तेज़ी से जोड़ते हैं।

एक लूप जहाँ मॉडल रुकना तय करता है विफल हो सकता है, और क्योंकि हर कदम एक टोकन-बिल मॉडल कॉल है, एक फंसा एजेंट बजट को तेज़ी से जलाता है। सुरक्षा उपाय डिज़ाइन का हिस्सा हैं। तार करने के लिए चार:

  • एक कदम सीमा। max_steps के साथ लूप को कैप करें और हिट होने पर स्वच्छता से लौटें। यह आपकी भागते हुए लूप के विरुद्ध कठोर बंद है।
  • टूल इनपुट को सत्यापित करें। मॉडल तर्क चुनता है, और यह गलत चुन सकता है या गलत तरीके से निर्देशित हो सकता है। किसी भी टूल को असली परिणाम के साथ चलाने से पहले उन्हें जांचें: आईडी के बिना हटाना, ऋणात्मक राशि के साथ स्थानांतरण, अनुमत निर्देशिका के बाहर पथ।
  • सबसे कम शक्ति। हर टूल को सबसे संकीर्ण क्षमता दें जो कार्य को चाहिए। पढ़ने-लेखन पर पढ़ें-केवल जीतें, कच्चे डेटाबेस एक्सेस पर एक स्कोप्ड प्रश्न, मनमाना भेजने पर प्राप्तकर्ताओं की एक निश्चित सूची।
  • लागत छत। पूरे रन में टोकन को ट्रैक करें, प्रति कॉल नहीं, और जब कोई रन बजट को पार करता है तो रुकें।

इन्हें जोड़ने वाली बात यह है कि आपके उपकरणों के तर्क मॉडल से आते हैं, जिसका मतलब है कि वे अप्रत्यक्ष रूप से किसी भी टेक्स्ट से आते हैं जो मॉडल ने पढ़ी है। यदि कोई टूल एक वेब पेज लाया था और वह पेज निर्देश ले रहा था, तो वे निर्देश अब मॉडल के संदर्भ में हैं और अगली टूल कॉल को निर्देशित कर सकते हैं। यह प्रॉम्प्ट इंजेक्शन है: संदर्भ में अविश्वसनीय टेक्स्ट जो एजेंट को क्या करता है। सुरक्षा प्रॉम्प्ट में नहीं है। यह हर टूल इनपुट को सत्यापित करने और हर टूल की शक्ति को स्कोप करने में है ताकि भले ही एक पूरी तरह से अपहृत तर्क असली नुकसान नहीं कर सकता है।

Junoरुकना और सुरक्षा उपाय चार सुरक्षा उपाय, डिज़ाइन द्वारा पॉलिश नहीं: एक max_steps कठोर बंद, हर महत्वपूर्ण टूल पर इनपुट सत्यापन, सबसे कम शक्ति टूल स्कोपिंग, और पूरे रन में एक टोकन बजट। कारण इनपुट सत्यापन महत्वपूर्ण है: टूल तर्क मॉडल से आते हैं, जिसका मतलब है कि यह जो कुछ टेक्स्ट पढ़ता है, इसलिए एक लाया हुआ पेज निर्देश ले जाना प्रॉम्प्ट इंजेक्शन है जो अगली कॉल को निर्देशित कर सकता है। इनपुट को सत्यापित करें और शक्ति को स्कोप करें ताकि एक अपहृत तर्क अभी भी नुकसान नहीं कर सकता है।

एक लूप जहाँ मॉडल रुकना तय करता है विफल हो सकता है, और हर कदम एक टोकन-बिल कॉल है, इसलिए विफलता मोड डिफ़ॉल्ट रूप से महंगा है। चार सुरक्षा उपाय (कदम सीमा, इनपुट सत्यापन, सबसे कम शक्ति, लागत छत) सारणी दांव हैं। इनपुट सत्यापन पर ध्यान देने का हिस्सा यह है कि यह एक सुरक्षा नियंत्रण है, न कि एक स्पष्टता जांच।

टूल तर्क मॉडल आउटपुट हैं, और मॉडल आउटपुट सब कुछ पर शर्त रखा गया है संदर्भ में, टेक्स्ट सहित एजेंट बाहर से लाया। जिस क्षण एक एजेंट एक वेब पेज, एक दस्तावेज़, एक ईमेल, या एक टूल परिणाम पढ़ता है जो आप नियंत्रण नहीं करते हैं, अविश्वसनीय टेक्स्ट इसके संदर्भ में है और निर्देश ले जा सकता है। यह प्रॉम्प्ट इंजेक्शन है: इनपुट में प्रतिकूल सामग्री मॉडल को आपके इरादे से अलग कार्यों में निर्देशित करती है। एकल-शॉट प्रॉम्प्ट में यह एक उपद्रव है। एक एजेंट में यह एक जीवंत शोषण है, क्योंकि मॉडल का अगला कदम एक वास्तविक-विश्व प्रभाव वाला टूल कॉल है, और इंजेक्ट किया गया टेक्स्ट उस कॉल को प्रभावित करता है।

इसे प्रतिकूल के रूप में डिज़ाइन करें, क्योंकि यह है। तीन नियम पकड़ात हैं:

  • एक अनुमति सूची के विरुद्ध हर टूल तर्क को सत्यापित करें, एक ब्लॉकलिस्ट नहीं। परिभाषित करें कि एक वैध तर्क कैसा दिखता है (यह आईडी प्रारूप, यह प्राप्तकर्ता सेट, यह निर्देशिका) और बाकी सब कुछ अस्वीकार करें। आप प्रत्येक बुरे इनपुट की गणना नहीं कर सकते हैं जो एक हमलावर तैयार करेगा; आप अच्छे लोगों की गणना कर सकते हैं।
  • अनुमति दें कि एक पूरी तरह से अपहृत कॉल जीवित रहेगी। मान लें कि तर्क हमलावर-नियंत्रित है और पूछें कि टूल तब क्या कर सकता है। अगर असली उत्तर "किसी को भी ईमेल करें" या "किसी भी पंक्ति को हटाएं" है, तो टूल बहुत व्यापक है चाहे प्रॉम्प्ट कितना भी सावधान हो। सबसे कम शक्ति नियंत्रण है जो मॉडल समझदारी से काम करता है, और प्रॉम्प्ट कोई नियंत्रण नहीं है।
  • अपरिवर्तनीय क्रियाओं पर मानव को लूप में डालें। पैसे भेजना, डेटा हटाना, ग्राहकों को ईमेल करना: इन्हें पुष्टि पर गेट करें। एजेंट प्रस्तावित है, एक व्यक्ति या कठोर जांच निपटती है।

गहरा कारण यह कि कोई भी यह प्रॉम्प्ट में नहीं रहता है: सिस्टम प्रॉम्प्ट में निर्देश और प्राप्त सामग्री में इंजेक्ट किए गए निर्देश संदर्भ में टेक्स्ट के समान तरीके के रूप में आते हैं, और मॉडल के पास एक के ऊपर दूसरे को विश्वसनीय रूप से रैंक करने का कोई तरीका नहीं है। तो आप सुरक्षा के लिए प्रॉम्प्ट नहीं कर सकते। सीमा जो मॉडल के बाहर रहती है: सत्यापित इनपुट और स्कोप किए गए टूल्स। यह सुरक्षा और सीमा में व्यापक उपचार से जुड़ता है।

Junoरुकना और सुरक्षा उपाय चार सुरक्षा उपाय सारणी दांव हैं; वह जो विचार अर्जित करता है इनपुट सत्यापन है, क्योंकि यह एक सुरक्षा नियंत्रण है। टूल तर्क मॉडल आउटपुट पर शर्त रखे गए हैं सब कुछ यह पढ़ता है, इसलिए कोई भी लाया गया पेज या ईमेल इंजेक्ट किए गए निर्देश ले जा सकता है जो अगली कॉल को निर्देशित करते हैं, और एक एजेंट में वह कॉल वास्तविक-विश्व प्रभाव है। एक अनुमति सूची के विरुद्ध सत्यापित करें, हर टूल को स्कोप करें इसलिए एक अपहृत तर्क अभी भी जीवित रहेगा, और अपरिवर्तनीय पर गेट करें। आप सुरक्षा के लिए प्रॉम्प्ट नहीं कर सकते: इंजेक्ट किए गए और सिस्टम निर्देश मॉडल के लिए टेक्स्ट के समान तरीके हैं, इसलिए सीमा इसके बाहर रहती है।

जब वर्कफ़्लो एजेंट को हराता है

एजेंट्स रोमांचक हैं, जो इसे लुभावना बनाता है जब आपको एक की आवश्यकता नहीं है। सादा नियम: अगर आप पहले से ही चरणों को जानते हैं, तो एजेंट का उपयोग न करें। उन्हें सादे कोड के रूप में लिखें, एक वर्कफ़्लो, जहाँ हर कदम एक निश्चित क्रम में चलता है।

एक वर्कफ़्लो अधिक विश्वसनीय, सस्ता, और डिबग करना बहुत आसान है, क्योंकि आप पथ को नियंत्रित करते हैं, इसके बजाय कि मॉडल इसे खोजता है। खुले सिरे वाले कार्यों के लिए एजेंट्स बचाएं जहाँ चरण उस पर निर्भर करते हैं जो आविष्कार किया गया है।

कई सुविधाएँ जो एजेंट की तरह दिखती हैं वास्तव में एक संरचित आउटपुट कॉल या एक RAG लुकअप हाथ से जुड़ी हुई हैं। एजेंट के लिए पहुंचें केवल जब आप चरणों को आगे से लिख न सकें।

Junoजब वर्कफ़्लो एजेंट को हराता है यदि आप पहले से ही चरणों को जानते हैं, तो उन्हें एजेंट के बजाय एक वर्कफ़्लो के रूप में कोडित करें: यह सस्ता, अधिक विश्वसनीय, और डिबग करना आसान है। खुले सिरे वाले कार्यों के लिए एजेंट्स बचाएं जहाँ चरण उस पर निर्भर करते हैं जो मिला। कई "एजेंट" सुविधाएँ वास्तव में एक संरचित-आउटपुट या RAG कॉल हाथ से जुड़ी हुई हैं।

एजेंट्स रोमांचक उपकरण हैं, जो ठीक है क्यों वे गलत होने पर पहुंचे जाते हैं। निर्णय नियम एक सवाल है: क्या आप चरणों को आगे से लिख सकते हैं? यदि हाँ, तो आप एक वर्कफ़्लो चाहते हैं, चरण सादे कोड में एक निश्चित क्रम में, एजेंट नहीं।

एक वर्कफ़्लो हर चीज़ पर जीतता है एक एजेंट संघर्ष करता है। यह सस्ता है, क्योंकि आप एक लूप की जगह एक या दो मॉडल कॉल करते हैं। यह अधिक विश्वसनीय है, क्योंकि पथ निश्चित है, हर बार पुनः तय नहीं किया गया। और डिबग करना बहुत आसान है, क्योंकि विफलता एक ज्ञात कदम पर होती है जो आप निरीक्षण कर सकते हैं, न कि मॉडल द्वारा चुने गए चालों की श्रृंखला में कहीं।

यहाँ परीक्षण व्यावहारिक है। "इस सहायता टिकट को सारांशित करें, इसकी तात्कालिकता को वर्गीकृत करें, और इसे एक कतार में निर्देशित करें" ज्ञात चरण एक ज्ञात क्रम में है, इसलिए यह एक वर्कफ़्लो है: एक संरचित आउटपुट कॉल सारांश, श्रेणी, और तात्कालिकता प्राप्त करने के लिए, फिर परिणाम पर निर्देशित करने के लिए सादा कोड। "जांच करें कि क्यों इस ग्राहक की आखिरी तीन ऑर्डर विफल हुई" ज्ञात चरण नहीं है, पथ उस पर निर्भर करता है जो हर लुकअप प्रकट करता है, इसलिए यह एक एजेंट है।

जाल यह है कि बहुत सी सुविधाएँ खुले सिरे वाली लगती हैं और हैं नहीं। एक दस्तावेज़ से खेत खींचना, आपके दस्तावेज़ से जवाब देना, आने वाली मेल को छाँटना: ये एजेंट काम पढ़ते हैं लेकिन एक संरचित आउटपुट कॉल या एक RAG लुकअप के लिए समाधान देता है इसके चारों ओर कोड। वर्कफ़्लो को चूक करें और कार्य को एजेंट अर्जित करता है अनुमानित होने के द्वारा ऐसा करें जो आप स्क्रिप्ट नहीं कर सकते।

Junoजब वर्कफ़्लो एजेंट को हराता है निर्णय एक सवाल है: क्या आप चरणों को आगे से लिख सकते हैं? यदि हाँ, तो एक वर्कफ़्लो बनाएं, चरण सादे कोड में, क्योंकि यह सस्ता, अधिक विश्वसनीय, और एक ज्ञात बिंदु पर डिबग करने योग्य है। "टिकट को सारांशित करें, वर्गीकृत करें, निर्देशित करें" एक वर्कफ़्लो है: एक संरचित-आउटपुट कॉल प्लस निर्देशित कोड। "जांच करें कि यह ऑर्डर विफल क्यों हुई" एक एजेंट है, क्योंकि पथ उस पर निर्भर करता है जो प्रत्येक कदम ढूँढता है। वर्कफ़्लो में चूक करें और कार्य को एजेंट अर्जित करने दें।

एजेंट रणनीतिक उपकरण है, जो यह है क्यों वह उपयोग किया जाता है जहाँ वह नहीं है। निर्णय नियम छोटा है: यदि आप चरणों को पहले से लिख सकते हैं, उन्हें लिखें। यह एक वर्कफ़्लो है, चरण कोड में एक निश्चित क्रम में, और यह किसी भी कार्य को हराता है जिसका आकार आप जानते हैं लागत, विश्वसनीयता, और डिबग करने योग्यता पर।

कारण सीधा आर्किटेक्चर पर है। एक एजेंट के पास कोई वैश्विक योजना नहीं है और त्रुटियों को आगे की ओर मिश्रित करता है, इसलिए इसकी विश्वसनीयता हर कदम को अधिकार के साथ गुणा करने का उत्पाद है कुछ भी पूरे को जांचते हुए। एक वर्कफ़्लो आपने लिखा है एक योजना है, परिभाषा के द्वारा, और आप निरीक्षण, परीक्षण, और सत्यापित कर सकते हैं हर कदम अलगाव में। जब कुछ एक वर्कफ़्लो में टूटता है, यह एक लाइन पर टूटता है। जब कुछ एक एजेंट में टूटता है, यह प्रतिलिपि में मॉडल के द्वारा चुने गए चालों में कहीं टूटता है, और आप ट्रेस से यह पुनर्निर्माण करते हैं कि यह क्या सोच रहा था।

अब कठिन केस, क्योंकि "क्या मुझे चरणों को जानते हैं" सीधा आधा है। एक एजेंट गलत टूल हो सकता है भले ही कार्य खुला हुआ हो, जब गलत कदम की लागत बहुत अधिक हो एक अगला-कदम अनुमान लेने के लिए। एक एजेंट जो यात्रा बुक करता है, पैसे चलाता है, या उत्पादन डेटा को संशोधित करता है खुला है और भी जहाँ आप एक अनुपरिवर्तनीय, इंजेक्शन योग्य, त्रुटि-मिश्रित लूप नियंत्रण नहीं चाहते हैं। सही डिज़ाइन अक्सर एक संकर है: मॉडल योजना या प्रस्ताव, लेकिन एक निश्चित वर्कफ़्लो और मानव फाटक निष्पादित करते हैं, इसलिए अनुपूर्वनिर्णय वाला हिस्सा कभी अपरिवर्तनीय हिस्से को सीधे नहीं छूता है।

तो सवाल दो सवाल हैं। क्या आप चरणों को जानते हैं, और गलत कदम की लागत क्या है?

ज्ञात चरण एक वर्कफ़्लो जाते हैं। अज्ञात चरण सस्ते, अपरिवर्तनीय क्रियाओं के साथ हैं जहाँ एक एजेंट अपनी जगह अर्जित करता है। अज्ञात चरण महंगे, अपरिवर्तनीय क्रियाओं के साथ एक बाधित डिज़ाइन चाहते हैं, एक मुक्त-रन लूप नहीं।

एक एजेंट सस्ते, अपरिवर्तनीय कदम के साथ खुले-सिरे काम में फिट है, और और कुछ नहीं। "एजेंट" सुविधाओं का एक आश्चर्यजनक शेयर एक संरचित आउटपुट कॉल या एक RAG लुकअप उनके चारों ओर कोड के साथ हैं, और वे बेहतर तरीके से उस तरीके से रहते हैं।

Junoजब वर्कफ़्लो एजेंट को हराता है दो सवाल, एक नहीं: क्या आप चरणों को जानते हैं, और गलत कदम की लागत क्या है? ज्ञात चरण एक वर्कफ़्लो पर जाते हैं, जो एक एजेंट को लागत, विश्वसनीयता, और डिबग करने पर हराता है क्योंकि इसके पास एक योजना है और एजेंट के पास कभी नहीं। अज्ञात चरण सस्ते अपरिवर्तनीय क्रियाओं के साथ हैं जहाँ एक एजेंट अपनी जगह अर्जित करता है। अज्ञात चरण महंगे अपरिवर्तनीय क्रियाओं के साथ एक संकर चाहते हैं: मॉडल प्रस्ताव, एक निश्चित वर्कफ़्लो और मानव फाटक निष्पादित करते हैं, इसलिए त्रुटि-मिश्रण लूप कभी भी एक हिस्से को नहीं छूता है जो आप पूर्ववत नहीं कर सकते।

व्यावहारिक में

ऊपर run_agent फ़ंक्शन पूरी चीज़ है। इसे एक सवाल, एक सेट उपकरण, और उनकी कार्यान्वयन दें, और यह तब तक लूप करता है जब तक किया या कदम सीमा तक पहुँचता है। एक छोटा कार्य लूप अर्जन को दिखाता है:

python
answer = run_agent(
    "Oslo में मौसम क्या है और क्या मुझे छाता लाना चाहिए?",
    tools,        # टूल-उपयोग अध्याय से get_weather शामिल है
    tool_impls,   # {"get_weather": ...}
)
# एजेंट get_weather को कॉल करता है, "बादल" पढ़ता है, फिर एक अंतिम बार में उत्तर देता है:
# "यह Oslo में बादल भरा है 18 डिग्री पर है, इसलिए छाता एक विवेकपूर्ण विचार है।"

एक टूल, एक लूप, एक उत्तर। एक ही संरचना कई उपकरणों और कई कदम तक बिना बदलाव के पैमाने।

एक बार जब आप इतनी क्षमता की चीज़ें बनाने में सक्षम हो जाते हैं, तो अगला सवाल यह है कि आप कैसे जानते हैं कि वे वास्तव में काम करते हैं, जो evals के बारे में है।

Junoव्यावहारिक मेंrun_agent लूप पूरी पैटर्न है: इसे एक सवाल, उपकरण, और उनकी कार्यान्वयन दें, और यह तब तक लूप करता है जब तक मॉडल टूल्स मांगना बंद नहीं करता या कैप से टकराता है। एक उपकरण और एक लूप बिना बदलाव के कई तक पैमाने। अगला सवाल यह है कि आप कैसे जानते हैं कि यह वास्तव में काम करता है, जो evals है।

run_agent फ़ंक्शन पूरी पैटर्न है। इसे एक सवाल, उपकरण, और उनकी कार्यान्वयन दें, और यह तब तक लूप करता है जब तक मॉडल मांगना बंद न करता है या सीमा से टकराता है।

python
answer = run_agent(
    "Delhi में मौसम क्या है और क्या मुझे छाता लाना चाहिए?",
    tools,        # टूल-उपयोग अध्याय से get_weather शामिल है
    tool_impls,   # {"get_weather": ...}
)
# एजेंट get_weather को कॉल करता है, "बादल" पढ़ता है, फिर एक अंतिम बार में उत्तर देता है।

एक उपकरण, एक लूप, एक उत्तर, और एक ही आकार कई उपकरणों और कई कदम तक पैमाने पर। आपके विश्वास में क्या पैमाना नहीं है कि यह काम करता है। एक वर्कफ़्लो आप कदम-से-कदम परीक्षण कर सकते हैं; एक एजेंट अलग इनपुट पर अलग पथ लेता है, इसलिए एक रन जो कल काम किया वह कल विफल रन के बारे में बहुत कम बताता है।

यही वह है कि एजेंट के साथ बनाने के लिए अगली चीज़ क्यों है यह मापने का एक तरीका है: प्रतिनिधि कार्यों का एक सेट भर में चलाएं और परिणाम जांचें, एक अच्छे डेमो पर विश्वास के बजाय। "यह काम किया जब मैंने इसे आजमाया" को एक संख्या में बदलना जो आप ट्रैक कर सकते हैं ठीक है जो evals को कवर करता है।

Junoव्यावहारिक मेंrun_agent लूप पूरी पैटर्न है, और एक उपकरण और एक लूप बिना बदलाव के कई तक पैमाने। पकड़ यह है विश्वास: एक एजेंट इनपुट प्रति अलग पथ लेता है, इसलिए प्रति-इनपुट परीक्षण कम बताता है और एक अच्छा डेमो अगले रन के बारे में कम प्रमाण देता है। प्रतिनिधि कार्यों भर में मापने का एक तरीका बनाएं, जो evals के लिए है।

run_agent फ़ंक्शन पूरी पैटर्न है, और नीचे का उदाहरण नग्न न्यूनतम है: एक उपकरण, एक लूप, एक उत्तर।

python
answer = run_agent(
    "Delhi में मौसम क्या है और क्या मुझे छाता लाना चाहिए?",
    tools,        # टूल-उपयोग अध्याय से get_weather शामिल है
    tool_impls,   # {"get_weather": ...}
)
# get_weather "बादल" लौटाता है, मॉडल एक अंतिम बार में उत्तर देता है।

आकार बिना बदलाव के कई उपकरणों और कई कदम तक पैमाने, और यह जाल है, क्योंकि विफलता मोड इसके साथ पैमाने हैं जबकि कोड स्थिर रहता है। एक एजेंट पथ-निर्भर है: अलग इनपुट मॉडल-चुने गए कदमों के अलग अनुक्रम ड्राइव करते हैं, इसलिए प्रति-इनपुट परीक्षण आपको लगभग कुछ नहीं बताता है और एक अच्छा डेमो वह समान चीज़ साबित करता है। संदर्भ विंडो का मतलब भी गैर-नियतकरण, तो भी एक ही इनपुट दो बार अलग पथ ले सकता है।

तो अगली चीज़ जो आप एजेंट के साथ बनाते हैं वह मापन है, और यह एक अलग तरह का मापन है वर्कफ़्लो की आवश्यकता है। आप एक अपेक्षित आउटपुट का दावा नहीं कर रहे हैं; आप प्रतिनिधि कार्यों का नमूना ले रहे हैं और परिणामों का वितरण पढ़ रहे हैं: कितनी बार यह बजट में समाप्त होता है, कितनी बार यह सही उत्तर तक पहुँचता है, जहाँ यह लूप करता है, यह क्या लागत है पूंछ। यह एजेंट के आकार का evals है, और यह एकमात्र तरीका है विश्वसनीयता, लागत, और सुरक्षा चिंताएँ ऊपर के अनुभागों से संख्याओं में बदलती हैं जो आप एक डेमो रक्षा कर सकते हैं आपको भाग्यशाली हुई।

Junoव्यावहारिक मेंrun_agent पूरी पैटर्न है और यह आकार में पैमाने जबकि विफलता मोड इसके साथ पैमाने। एक एजेंट पथ-निर्भर है और नमूना गैर-नियतकरण जोड़ता है, इसलिए प्रति-इनपुट परीक्षण कम बताता है और एक अच्छा डेमो कम साबित करता है। इसे एजेंट तरीके से मापें: प्रतिनिधि कार्यों को नमूना और वितरण पढ़ें, कितनी बार यह बजट में समाप्त होता है, जहाँ यह लूप करता है, पूंछ लागत। यह है evals, और यह है कि विश्वसनीयता और लागत चिंताएँ संख्याओं में बदलती हैं।