Skip to content

Solo Mode

Potato में पूरी annotation pipeline अकेले चलाइए, जहाँ एक expert और एक LLM phases की एक state machine से गुज़रते हैं, जिसमें prompt लिखना, parallel annotation, disagreement resolution और final validation शामिल हैं।

v2.3.0 में नया

पारंपरिक annotation projects में कई annotators, inter-annotator agreement की गणना, adjudication rounds और काफ़ी coordination overhead लगता है। कई research teams के लिए यही सबसे बड़ी रुकावट है। रुकावट annotation interface नहीं, बल्कि एक team को hire, train और manage करने की logistics है।

Solo Mode multi-annotator paradigm की जगह एक अकेले human expert को LLM के साथ काम करने देता है। Human एक छोटे, सोच-समझकर चुने गए subset पर high-quality labels देता है। LLM उन labels से सीखता है, बाकी के लिए labels propose करता है, और human केवल उन cases की समीक्षा करता है जहाँ LLM अनिश्चित है या शायद गलत है। यह सब phases की एक state machine संचालित करती है, जो आपके तय किए thresholds पर आगे बढ़ती है और जब भी पता चलता है कि गड़बड़ी prompt में ही है, तब prompt पर लौट आती है।

Internal benchmarks में, Solo Mode ने पूर्ण multi-annotator pipelines के साथ 95%+ agreement हासिल किया, जबकि कुल human labels का केवल 10-15% ही लगा।

Workflow

Solo Mode एक state machine है। SoloPhaseController यह track करता है कि project किस phase में है और आगे किन phases में जा सकता है, इसलिए रास्ता सीधी रेखा नहीं है। जब prompt पर अभी और काम बाकी हो, तो कई phases पीछे लौट सकते हैं।

Setup

Task का विवरण और data। Generate prompt एक revision model (revision_models) से कहता है कि वह विवरण और annotation schemes से पहला prompt लिखे। Revision model न हो, या वह कुछ न लौटाए, तो विवरण ही पहला prompt बन जाता है और prompt history में यह दर्ज होता है। Setup से केवल prompt review में जाया जा सकता है।

Prompt review

Potato task के विवरण से एक prompt तैयार करता है और आप उसे edit करते हैं। जब पता चलता है कि समस्या prompt में है, तो बाद के कई phases यहीं लौटते हैं। इसलिए यह phase एक बार का step नहीं, बल्कि पूरे workflow का केंद्र है।

यहाँ से project या तो edge-case loop से गुज़रता है या सीधे parallel annotation में जाता है।

Edge case synthesis, फिर edge case labeling

LLM सीमा पर पड़ने वाले examples बनाता है और आप उन्हें label करते हैं। अगर examples दिखाते हैं कि prompt गलत है, तो labeling वापस prompt review में जा सकती है।

Prompt validation

Edge cases पर आपके labels की तुलना prompt के output से की जाती है। यहाँ से project या तो parallel annotation में आगे बढ़ता है या prompt review में लौटता है।

Parallel annotation

आप और LLM एक ही data को एक ही समय पर annotate करते हैं। यही वह phase है जो agreement का वह आँकड़ा देता है जिस पर बाकी सब कुछ निर्भर करता है।

Disagreement resolution

जहाँ आप और LLM अलग राय रखते हैं, वहाँ फ़ैसला आप करते हैं। Project parallel annotation में लौटता है, या prompt review में, जब disagreements अलग-अलग items की बजाय prompt की ओर इशारा करते हैं।

Active annotation

मुख्य annotation phase, जिसमें instances instance_selection के weighted pools से चुने जाते हैं। यहाँ से Potato periodic review, rule review या autonomous labeling में जा सकता है।

Periodic review

कम confidence वाले LLM labels, जो हर thresholds.periodic_review_interval items पर सामने लाए जाते हैं। Project active annotation में लौटता है, rule review में जाता है, या वापस prompt review पर आ जाता है।

Rule review

आपकी labeling से Potato ने जो edge case rules निकाले हैं, वे approval के लिए दिखाए जाते हैं। Project active annotation या prompt review में लौटता है।

Autonomous labeling

LLM बचा हुआ data label करता है। इसका एकमात्र निकास final validation है।

Final validation

आप केवल LLM द्वारा दिए गए labels का एक sample जाँचते हैं। thresholds.end_human_annotation_agreement पार होने पर project पूरा हो जाता है। पार न होने पर project active annotation में लौट जाता है।

Completed

अंतिम state।


कॉन्फ़िगरेशन

Quick Start

एक न्यूनतम Solo Mode configuration:

yaml
annotation_task_name: "Sentiment Classification"
task_dir: "."
 
data_files:
  - "data/reviews.jsonl"
 
item_properties:
  id_key: id
  text_key: text
 
solo_mode:
  enabled: true
 
  # The models that label. A list: the first is used, the rest are fallbacks.
  labeling_models:
    - endpoint_type: openai
      model: "gpt-4o"
      api_key: ${OPENAI_API_KEY}
      temperature: 0.1
      max_tokens: 1024
 
  # When the project may stop asking the human
  thresholds:
    end_human_annotation_agreement: 0.92
    minimum_validation_sample: 50
    confidence_low: 0.5
 
  state_dir: "solo_state_sentiment"
 
annotation_schemes:
  - annotation_type: radio
    name: sentiment
    description: "What is the sentiment of this text?"
    labels:
      - Positive
      - Neutral
      - Negative
 
output_annotation_dir: "output/"
export_annotation_format: "jsonl"

पूर्ण Configuration Reference

yaml
solo_mode:
  enabled: true
 
  # Models that label, and models that revise. Both are lists; revision_models
  # defaults to labeling_models when omitted.
  labeling_models:
    - endpoint_type: openai       # openai, anthropic, ollama, vllm, ...
      model: "gpt-4o"
      api_key: ${OPENAI_API_KEY}
      temperature: 0.1
      max_tokens: 1024
  revision_models:
    - endpoint_type: anthropic
      model: "claude-sonnet-4-20250514"
      api_key: ${ANTHROPIC_API_KEY}
      max_tokens: 1024
 
  # Sentence embeddings, used for diversity and neighbour lookups
  embedding:
    model_name: "all-MiniLM-L6-v2"
 
  # How the LLM's uncertainty is measured
  uncertainty:
    strategy: direct_confidence
    sampling_diversity:
      num_samples: 5
      temperature: 1.0
 
  # When the human can stop, and what counts as agreement per scheme type
  thresholds:
    end_human_annotation_agreement: 0.90
    minimum_validation_sample: 50
    confidence_low: 0.5
    confidence_high: 0.8
    periodic_review_interval: 100
    likert_tolerance: 1
    multiselect_jaccard_threshold: 0.5
    textbox_embedding_threshold: 0.7
    span_overlap_threshold: 0.5
 
  # Weights for the pools that choose what the human sees next
  instance_selection:
    low_confidence_weight: 0.3
    disagreement_weight: 0.1
    diversity_weight: 0.2
    llm_predicted_weight: 0.3
    random_weight: 0.1
    cartography_weight: 0.0
    edge_case_rule_weight: 0.0
 
  batches:
    llm_labeling_batch: 50
    max_parallel_labels: 200
 
  labeling_functions:
    enabled: true
    auto_extract: true
    max_functions: 50
    min_confidence: 0.85
    min_coverage: 3               # instances, not a fraction
    vote_threshold: 0.5
 
  edge_case_rules:
    enabled: true
    auto_extract_on_labeling: true
    confidence_threshold: 0.75
    min_rules_for_clustering: 10
    target_cluster_size: 15
    reannotation_enabled: true
    reannotation_confidence_threshold: 0.60
    max_reannotations_per_instance: 2
 
  confusion_analysis:
    enabled: true
    min_instances_for_pattern: 3
    max_patterns: 20
    auto_suggest_guidelines: false
 
  prompt_optimization:
    enabled: true
    find_smallest_model: true
    target_accuracy: 0.85
    optimization_interval_seconds: 300
    accuracy_weight: 0.7
    length_weight: 0.2
 
  # Send cheap cases to a small model and hard ones to a larger one
  confidence_routing:
    enabled: false
    tiers:
      - name: cheap
        confidence_threshold: 0.8
        model:
          endpoint_type: ollama
          model: "llama3.2"
 
  refinement_loop:
    enabled: true
    trigger_interval: 50
    min_improvement: 0.02
    max_cycles: 5
    patience: 2
 
  state_dir: "solo_state_sentiment"

प्रमुख क्षमताएँ

Confusion Analysis

हर labeling round के बाद, Potato human और LLM labels के बीच एक confusion matrix बनाता है। Admin dashboard दिखाता है:

  • LLM के नज़रिए से per-class precision, recall और F1
  • सबसे आम confusion pairs (जैसे, "neutral को positive के रूप में misclassify किया गया: 23 instances")
  • हर confusion pair के लिए example instances
  • Refinement rounds में सुधार दिखाने वाले trend charts

Solo Mode का कोई command-line interface नहीं है। यह server के अंदर चलता है और चल रहे instance के अपने pages से संचालित होता है, इसलिए analysis CLI से नहीं, dashboard से पढ़ा जाता है। यह जो report करता है, वह ऐसा दिखता है:

text
Confusion Analysis (Round 2)
============================
Overall Accuracy: 0.87 (target: 0.92)

Top Confusion Pairs:
  neutral -> positive:  23 instances (15.3%)
  negative -> neutral:  11 instances (7.3%)
  positive -> neutral:   5 instances (3.3%)

Per-Class Performance:
  Positive:  P=0.91  R=0.94  F1=0.92
  Neutral:   P=0.78  R=0.71  F1=0.74
  Negative:  P=0.93  R=0.88  F1=0.90

Automated Refinement Loop

Refinement loop बारी-बारी से LLM labeling, confusion analysis और guideline updates चलाता है। हर iteration में:

  1. LLM मौजूदा guidelines के साथ पूरे dataset को label करता है
  2. Potato उपलब्ध सभी human labels से तुलना करता है
  3. अगर accuracy threshold से नीचे है, तो confusion analysis चलता है
  4. LLM error patterns के आधार पर guideline edits propose करता है
  5. Human edits की समीक्षा करके उन्हें approve करता है
  6. Cycle दोहराई जाती है (max_cycles तक)
yaml
solo_mode:
  revision_models:
    - endpoint_type: anthropic
      model: "claude-sonnet-4-20250514"
      api_key: ${ANTHROPIC_API_KEY}
 
  refinement_loop:
    enabled: true
    trigger_interval: 50           # run a cycle every 50 new human labels
    min_improvement: 0.02          # stop if a cycle gains less than 2%
    max_cycles: 5
    patience: 2                    # cycles below min_improvement before stopping

Labeling Functions (ALCHEmist से प्रेरित)

Potato human annotations में दिखे patterns से हल्के labeling functions बनाता है। ये LLM calls नहीं हैं। ये तेज़, deterministic rules हैं।

Generated labeling functions के उदाहरण:

python
# Auto-generated labeling function 1
# Precision: 0.96, Coverage: 0.08
def lf_strong_positive_words(text):
    positive = {"excellent", "amazing", "fantastic", "outstanding", "perfect"}
    if any(w in text.lower() for w in positive):
        if not any(neg in text.lower() for neg in {"not", "never", "no"}):
            return "Positive"
    return None  # abstain
 
# Auto-generated labeling function 2
# Precision: 0.93, Coverage: 0.05
def lf_explicit_negative(text):
    negative = {"terrible", "awful", "horrible", "worst", "disgusting"}
    if any(w in text.lower() for w in negative):
        return "Negative"
    return None

Labeling function का व्यवहार configure करें:

yaml
solo_mode:
  labeling_functions:
    enabled: true
    auto_extract: true
    max_functions: 50
    min_confidence: 0.85
    min_coverage: 3          # minimum instances a function must cover
    vote_threshold: 0.5      # agreement needed when functions disagree

Disagreement Explorer

Disagreement explorer वे instances दिखाता है जहाँ अलग-अलग signals आपस में टकराते हैं। हर instance के लिए annotator देखता है:

  • LLM का predicted label और उसकी confidence
  • Labeling function votes (अगर हों)
  • Embedding space में सबसे नज़दीकी labeled neighbors
  • Raw text या content

यह सबसे ज़्यादा मूल्य वाली annotation गतिविधि है, क्योंकि हर label एक वास्तविक ambiguity सुलझाता है।

yaml
solo_mode:
  # Disagreement is a phase, not a configurable block. What you control is how
  # heavily disagreement weighs when Potato picks the next instance.
  instance_selection:
    disagreement_weight: 0.3
    low_confidence_weight: 0.3
    diversity_weight: 0.2
    llm_predicted_weight: 0.1
    random_weight: 0.1

Cascaded Confidence Escalation

जब dataset का अधिकांश हिस्सा LLM label कर चुका होता है, तब Potato LLM-labeled सभी instances को confidence के क्रम में रखता है और सबसे कम confidence वाले instances human को escalate करता है। यह batches में तब तक चलता है जब तक quality स्थिर न हो जाए।

yaml
solo_mode:
  thresholds:
    confidence_low: 0.5           # below this, the human sees it
    confidence_high: 0.8          # above this, the LLM's label stands
    periodic_review_interval: 100 # surface low-confidence labels this often
 
  batches:
    llm_labeling_batch: 50
    max_parallel_labels: 200

Decision Models

Potato 2.11 से Solo Mode में एक decision model भी label कर सकता है। Decision model किसी fixed-choice सवाल का जवाब एक ही forward pass में देता है और हर option की probability लौटाता है, इसलिए labeling में वह LLM से तेज़ और सस्ता है, पर वह prompts, rules या explanations नहीं लिख सकता। दो endpoint types इस तक पहुँचते हैं। laya Laya को Potato process के अंदर CPU पर चलाता है और इसके लिए pip install 'potato-annotation[decision]' चाहिए, और systemone /v1/systemone API वाले किसी भी server से बात करता है, जैसे hosted Jev या OpenJev।

Decision model की आम जगह confidence routing का पहला tier है, जहाँ वह सब कुछ label करता है और केवल वे items LLM तक जाते हैं जिन पर वह अनिश्चित है:

yaml
solo_mode:
  labeling_models:
    - endpoint_type: laya
      model: convaiinnovations/laya
  revision_models:                     # required: decision models cannot write text
    - endpoint_type: vllm
      model: google/gemma-4-12B-it-qat-w4a16-ct
      base_url: http://localhost:8001/v1
  confidence_routing:
    enabled: true
    tiers:
      - name: laya
        confidence_threshold: 0.9
        model:
          endpoint_type: laya
          model: convaiinnovations/laya
          device: cpu
      - name: llm
        confidence_threshold: 0.5
        model:
          endpoint_type: vllm
          model: google/gemma-4-12B-it-qat-w4a16-ct
          base_url: http://localhost:8001/v1

revision_models एक generative model होना चाहिए। इसका default labeling_models है, इसलिए जिस study का अकेला model कोई decision model है, उसे इसे set करना होगा। Decision models radio, select, likert और slider schemes label करते हैं, और अगर किसी को multiselect, span या free-text schemes label करने के लिए set किया जाए, तो Solo Mode शुरू होने से मना कर देता है। Rating scales पर Laya के scores मुश्किल से ही scale का पालन कर पाते हैं, इसलिए किसी likert या slider scheme को इसके ज़रिए route करने से पहले Try on 10 items से कुछ items जाँच लें। Confidence वह probability है जो model ने अपने चुने हुए option को दी, और इसका calibration domain के हिसाब से बदलता है, इसलिए tier threshold अपने data से तय करें। config-decision-model.yaml इसका चलने लायक version है।

Blind Suggestions

Default रूप से annotate page आपके जवाब देने से पहले LLM का label, उसकी confidence और एक Accept button दिखाता है। इससे काम तेज़ होता है, पर आपका जवाब सुझाव की ओर खिंचता भी है। जब LLM के साथ आपकी agreement end_human_annotation_agreement को पार कर जाती है, तब Solo Mode बाकी corpus LLM को सौंप देता है, इसलिए सुझाव देखने के बाद दिए गए labels पर मापी गई agreement आपके हिस्से का काम बहुत जल्दी खत्म कर सकती है। Potato 2.11 से solo_mode.suggestions तय करता है कि सुझाव कब दिखे:

yaml
solo_mode:
  suggestions:
    display: blind_sample      # before_label | after_label | blind_sample
    blind_rate: 0.2
    minimum_blind_sample: 20

blind_sample items के blind_rate हिस्से पर सुझाव छिपाता है, और after_label उसे कभी पहले नहीं दिखाता। minimum_blind_sample blind तुलनाएँ हो जाने के बाद handoff blind agreement की तुलना end_human_annotation_agreement से करता है। Dashboard का Blind Agreement card blind और shown agreement साथ-साथ दिखाता है, और बड़ा positive अंतर बताता है कि जब आप LLM का जवाब देख सकते हैं, तब आप उससे ज़्यादा बार सहमत होते हैं।

Potato 2.11 में Solo Mode labeling शुरू होने से पहले और हर batch से पहले project की spend cap (ai_budget.cap_usd) भी जाँचता है, और इसमें एक response cache (solo_mode.cache), prompt trials के साथ एक gold set (solo_mode.gold), एक prompt-sensitivity check, एक labeling jury (solo_mode.jury) और curriculum ordering (solo_mode.instance_selection.curriculum) भी जुड़ते हैं। Solo Mode Advanced Features हर एक का विवरण देता है। जब लेबलिंग इंजन चालू हो, तब Solo Mode अपने model predictions इंजन के store में भी लिखता है, ताकि इंजन उन्हें calibrate और certify कर सके।

Multi-Signal Instance Prioritization

जिन phases में human labeling होती है, उन सभी में Potato सबसे informative instances चुनने के लिए weighted pool system इस्तेमाल करता है। सात pools एक साझा priority queue में जाते हैं:

yaml
solo_mode:
  instance_selection:
    low_confidence_weight: 0.3
    diversity_weight: 0.2
    llm_predicted_weight: 0.3
    disagreement_weight: 0.1
    random_weight: 0.1
    cartography_weight: 0.0
    edge_case_rule_weight: 0.0
  • low_confidence: LLM की confidence thresholds.confidence_low से नीचे चली जाती है
  • diversity: embedding space में उससे दूर, जो आप पहले ही label कर चुके हैं
  • llm_predicted: LLM के पास एक label है जिसे अभी जाँचा नहीं गया
  • disagreement: instance के लिए उपलब्ध signals आपस में सहमत नहीं हैं
  • random: एक छोटा random draw, ताकि अनुमान ईमानदार रहे और blind spots पकड़े जा सकें
  • cartography: training-dynamics signal, default रूप से बंद
  • edge_case_rule: आपकी पिछली labeling से निकाले गए किसी rule से मेल खाता है, default रूप से बंद

Edge Case Synthesis

Potato LLM से ऐसे synthetic examples बनवाता है जो ज्ञात कमज़ोरियों को निशाना बनाते हैं:

yaml
solo_mode:
  edge_case_rules:
    enabled: true
    auto_extract_on_labeling: true   # derive rules as you label
    confidence_threshold: 0.75
    min_rules_for_clustering: 10
    target_cluster_size: 15
    reannotation_enabled: true       # revisit items a new rule contradicts
    reannotation_confidence_threshold: 0.60
    max_reannotations_per_instance: 2

LLM ऐसे examples बनाता है जो बताए गए label pairs के बीच ambiguous हों। Human उन्हें label करता है, और ये labels आगे के LLM labeling rounds के few-shot context में जोड़ दिए जाते हैं।

Prompt Optimization (DSPy से प्रेरित)

Potato LLM के लिए सबसे अच्छा instruction format खोजने के लिए automated prompt optimization चलाता है, और वह सबसे छोटा model ढूँढता है जो फिर भी target accuracy बनाए रखे:

yaml
solo_mode:
  prompt_optimization:
    enabled: true
    find_smallest_model: true          # prefer the cheapest model that holds up
    target_accuracy: 0.85
    optimization_interval_seconds: 300
    accuracy_weight: 0.7               # how the candidates are scored
    length_weight: 0.2

Progress की निगरानी

Admin dashboard Solo Mode की progress real time में दिखाता है:

  • मौजूदा phase और हर phase के भीतर progress
  • पूरे हो चुके human labels बनाम कुल budget
  • समय के साथ LLM accuracy (हर round के लिए)
  • Labeling function coverage और precision
  • Confidence distribution histogram
  • पूरा होने का अनुमानित समय

न कोई potato.solo module है और न कोई Solo Mode CLI। पूरा workflow server के अपने routes के पीछे चलता है, इसलिए progress dashboard से पढ़ी जाती है। यह report करता है:

text
Solo Mode Status
================
Current Phase: 6 (Active Labeling) - Batch 3/10
Human Labels: 142 / ~300 estimated total
LLM Accuracy: 0.89 (target: 0.92)
LF Coverage: 0.23 (labeling functions cover 23% of data)
Dataset Size: 10,000 instances
  - Human labeled: 142
  - LF labeled: 2,300
  - LLM labeled: 7,558
  - Unlabeled: 0

Solo Mode vs. Traditional Multi-Annotator कब उपयोग करें

Solo Mode का उपयोग करें जब:

  • आपके पास एक domain expert हो जो high-quality labels दे सकता है
  • Budget या logistics कई annotators hire करने से रोकते हैं
  • Task में स्पष्ट, well-defined categories हैं
  • आपको एक बड़ा dataset (1,000+ instances) label करना है
  • Speed inter-annotator agreement मापने से ज़्यादा मायने रखती है

Traditional multi-annotator का उपयोग करें जब:

  • आपको publication के लिए inter-annotator agreement statistics चाहिए
  • Task बहुत subjective है (जैसे, offensiveness, humor)
  • आपको annotator disagreement patterns का अध्ययन करना है
  • Regulatory requirements कई independent annotators अनिवार्य करते हैं
  • Label space complex है या बदल रहा है (annotation guidelines अभी विकसित हो रही हैं)

Hybrid approach: शुरुआती bulk labeling के लिए Solo Mode का उपयोग करें, फिर agreement statistics निकालने के लिए एक second annotator को random 10-20% sample assign करें। इससे Solo Mode की efficiency के साथ multi-annotator verification का quality assurance भी मिलता है।

Solo Mode का अपना कोई verification block नहीं है। Second annotator को export किए गए labels पर एक सामान्य Potato pass की तरह चलाइए, और उनके labels और Solo Mode के labels के बीच agreement वैसे ही निकालिए जैसे किन्हीं भी दो annotators के लिए निकालते हैं। (icl_labeling में एक verification block है, लेकिन वह in-context labeling का हिस्सा है, Solo Mode का नहीं।)


आगे पढ़ें

कार्यान्वयन विवरण के लिए, स्रोत दस्तावेज़ देखें।