Skip to content
Guides7 min read

लूप को बंद करना: एजेंट की गलतियों और जज की असहमतियों को वापस इंसानों तक पहुँचाना

एजेंट मूल्यांकन में मानवीय समीक्षा का समय सबसे दुर्लभ संसाधन है। Potato 2.6 एक सिग्नल-आधारित ट्राएज कतार को जज-मानव संरेखण के साथ जोड़ता है, ताकि सबसे खराब ट्रेस पहले लोगों तक पहुँचें और आपका LLM जज लगातार बेहतर होता रहे।

Potato Team

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

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

यह पोस्ट दोनों हिस्सों को और यह कि वे कैसे जुड़ते हैं, दोनों को कवर करती है।

एनोटेशन के दौरान एक प्राथमिकता बैज जो बताता है कि किसी आइटम को समीक्षा के लिए क्यों चिह्नित किया गयाPotato में ट्राएज कतार बैज

ट्राएज वाला हिस्सा: सबसे खराब पहले, न कि पहले-आए-पहले-गए

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

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

yaml
triage:
  enabled: true
  order: desc            # high priority first (default)
  show_badge: true       # banner during annotation explaining the priority
  rules:                 # evaluated in order; highest matching priority wins
    - name: "Agent errored"
      priority: 100
      when:
        field: status
        equals: error
    - name: "Negative feedback"
      priority: 80
      when:
        field: feedback
        in: [thumbs_down, negative]
    - name: "Low quality score"
      priority: 60
      when:
        field: score
        lt: 0.5
 
assignment_strategy: priority

नियमों का मूल्यांकन ऊपर से नीचे होता है और सबसे ऊँची मेल खाने वाली प्राथमिकता जीतती है, इसलिए एक एरर वाला ट्रेस जिसमें नकारात्मक फ़ीडबैक भी हो, फिर भी 100 पर ही उतरता है। यदि आप rules को पूरी तरह छोड़ देते हैं, तो Potato एक समझदार डिफ़ॉल्ट सेट पर वापस लौट आता है (एरर स्थिति पर 100, नकारात्मक फ़ीडबैक पर 80, 0.5 से कम स्कोर पर 60), इसलिए कुछ भी ट्यून करने से पहले ही टर्नकी व्यवहार उचित होता है।

शर्त ऑपरेटर उन तुलनाओं को कवर करते हैं जिनकी आपको वास्तव में ज़रूरत होती है:

Operatorअर्थ
equalsसटीक मिलान (स्ट्रिंग्स केस-असंवेदनशील होती हैं)
inमान किसी सूची में से एक है
containsसूची में शामिल है, या सबस्ट्रिंग मिलान
lt / lte / gt / gteसंख्यात्मक तुलना
existsफ़ील्ड मौजूद है या अनुपस्थित

जब सिग्नल पहले से ही एक संख्या हो, तो नियम लिखने के बजाय आप उसे सीधे फ़ील्ड से पढ़ सकते हैं:

yaml
triage:
  enabled: true
  signal_field: quality_score
  invert_signal: true           # lower score => higher priority

यह लाइव ट्रैफ़िक पर भी काम करता है

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

संरेखण वाला हिस्सा: जज पर कितना भरोसा करें

ट्राएज तय करता है कि इंसान क्या देखें। संरेखण तय करता है कि बाकी का कितना हिस्सा आप बिना निगरानी के जज को सौंप सकते हैं, और समय के साथ यह जज को कसता जाता है।

जज संरेखण उन इंस्टेंस पर एक विन्यास-योग्य LLM जज चलाता है जिन्हें आपके एनोटेटर पहले ही लेबल कर चुके हैं, फिर मानव गोल्ड के सामने Cohen's κ (कोहेन का कप्पा, सहमति का एक माप), एक कन्फ़्यूज़न मैट्रिक्स, और एक असहमति सूची रिपोर्ट करता है। मानक अभ्यास (एक जज को लगभग 100–200 गोल्ड लेबल से संरेखित करना, जाँचना कि वह कहाँ असहमत होता है, rubric को फिर से लिखना, और दोबारा चलाना) ही वह लूप है जिसके चारों ओर यह बनाया गया है।

yaml
ai_support:
  enabled: true
  endpoint_type: "ollama"
  ai_config:
    model: "llama3.2"
    temperature: 0.0
 
judge_alignment:
  enabled: true
  schemas:
    correctness:
      rubric: >
        Label 'correct' only if the agent's answer is factually right and fully
        satisfies the request; otherwise 'incorrect'.
  inline:
    enabled: true                # show the judge verdict beside the human label
    schemas: [correctness]

आप जज को एडमिन API से चलाते हैं, और भविष्यवाणियाँ प्रति प्रॉम्प्ट संस्करण कैश की जाती हैं, इसलिए दोबारा चलाना सस्ता रहता है:

bash
curl -X POST localhost:8000/admin/api/judge-alignment/run \
  -H "X-API-Key: <admin-key>" \
  -H "Content-Type: application/json" \
  -d '{"max_per_schema": 200}'

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

bash
curl -X POST localhost:8000/admin/api/judge-alignment/run \
  -H "X-API-Key: <admin-key>" -H "Content-Type: application/json" \
  -d '{"rubrics": {"correctness": "Stricter rubric text..."}}'

यह रिपोर्ट, जो JSON के रूप में या /admin/judge-alignment पर एक रेंडर किए गए पृष्ठ के रूप में उपलब्ध है, Landis–Koch व्याख्या के साथ κ, कन्फ़्यूज़न मैट्रिक्स, जज के तर्क के साथ एक असहमति तालिका, और एक प्रॉम्प्ट-संस्करण इतिहास दिखाती है, जिससे कैलिब्रेशन की प्रगति राउंड-दर-राउंड दिखाई देती है।

इनलाइन मोड इसे एनोटेटर के सामने रखता है

inline.enabled के साथ, प्रत्येक एनोटेशन पृष्ठ मानव लेबल के बगल में जज का कैश किया गया फ़ैसला (उसका चयन, आत्मविश्वास, और विस्तार-योग्य तर्क) दिखाता है, साथ ही कार्य के लिए एक चालू κ। "स्वीकार करें" मेल खाने वाले विकल्प को भर देता है। हर मानवीय सेव एक मानव↔जज तुलना दर्ज करता है जो चालू सहमति में फ़ीड होती है, इसलिए जिस κ की ओर आप ट्यून कर रहे हैं वह लोगों के काम करते-करते अपडेट होती रहती है।

दोनों को एक साथ रखना

इन सुविधाओं को एक ही लूप में संयोजित होने के लिए डिज़ाइन किया गया है:

प्रोडक्शन सिग्नल एक प्राथमिकता कतार को फ़ीड करते हैं; इंसान शीर्ष आइटम की समीक्षा करते हैं; उनके लेबल जज का kappa मापते हैं; एक परिष्कृत rubric वापस फ़ीड होता हैसक्रिय मूल्यांकन लूप: ट्राएज, मानवीय समीक्षा, जज संरेखण, rubric परिष्करण

  1. ट्राएज एरर वाले और कम-आत्मविश्वास वाले ट्रेस को मानव कतार के आगे धकेलता है।
  2. इंसान समीक्षा करते हैं उन उच्च-मूल्य आइटम की, और ठीक वहीं ताज़े गोल्ड लेबल बनाते हैं जहाँ सिस्टम सबसे कम आश्वस्त होता है।
  3. संरेखण उस गोल्ड के सामने जज को स्कोर करता है, और असहमति सूची ठीक-ठीक दिखाती है कि जज और इंसान कहाँ अलग होते हैं।
  4. आप rubric को परिष्कृत करते हैं, दोबारा चलाते हैं, और κ को हिलते देखते हैं, फिर बेहतर कैलिब्रेट किए गए जज को अधिक आसान मात्रा सोखने देते हैं ताकि मानवीय समय कठिन मामलों की ओर बहता रहे।

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

दोनों सुविधाएँ Potato 2.6 में आती हैं। पूर्ण संदर्भ के लिए ट्राएज कतार दस्तावेज़ और जज संरेखण दस्तावेज़ देखें, और प्राथमिकता वाले ट्रेसों को जल्दी पढ़ने के लिए eval_trace डिस्प्ले देखें।