الوضع الفردي
شغّل خط تعليق توضيحي كاملًا بمفردك في Potato، حيث يعمل خبير واحد ونموذج لغوي كبير عبر آلة حالات من المراحل تغطي صياغة الموجّه والتعليق التوضيحي المتوازي وحل الخلافات والتحقق النهائي.
جديد في الإصدار v2.3.0
تتطلب مشاريع التعليق التوضيحي التقليدية معلّقين متعددين وحساب الاتفاق بين المعلّقين وجولات تحكيم وعبئًا كبيرًا من التنسيق. بالنسبة لكثير من فرق البحث، يكون هذا هو العائق الرئيسي. ليست المشكلة في واجهة التعليق التوضيحي، بل في الجوانب اللوجستية لتوظيف فريق وتدريبه وإدارته.
يستبدل الوضع الفردي نموذج المعلّقين المتعددين بخبير بشري واحد يتعاون مع نموذج لغوي كبير (LLM). يقدم الإنسان تصنيفات عالية الجودة على مجموعة فرعية صغيرة مختارة بعناية. يتعلم النموذج من تلك التصنيفات ويقترح تصنيفات للباقي، ولا يراجع الإنسان إلا الحالات التي يكون فيها النموذج غير متأكد أو يُرجَّح أنه مخطئ. تتولى آلة حالات من المراحل تنظيم ذلك، فتتقدم وفق العتبات التي تحددها وتعود إلى الموجّه كلما تبيّن أن الموجّه نفسه هو مصدر الخطأ.
في الاختبارات المعيارية الداخلية، حقق الوضع الفردي اتفاقًا يزيد على 95% مع خطوط المعالجة الكاملة متعددة المعلّقين، مع الحاجة إلى 10-15% فقط من إجمالي التصنيفات البشرية.
سير العمل
الوضع الفردي آلة حالات. يتتبع SoloPhaseController المرحلة التي يوجد فيها المشروع والمراحل التي يُسمح له بالانتقال إليها بعدها، لذا فالمسار ليس خطًا مستقيمًا. يمكن لعدة مراحل أن تعود إلى الوراء عندما يظل الموجّه بحاجة إلى عمل.
الإعداد
وصف المهمة والبيانات. يطلب Generate prompt من نموذج مراجعة (revision_models) أن يكتب الموجّه الأول انطلاقًا من الوصف ومخططات التعليق التوضيحي. وإن لم يوجد نموذج مراجعة، أو لم يُعِد شيئًا، يصير الوصف نفسه الموجّه الأول ويذكر سجل الموجّهات ذلك. والمرحلة الوحيدة التي يمكن الانتقال إليها من الإعداد هي مراجعة الموجّه.
مراجعة الموجّه
يصوغ Potato موجّهًا انطلاقًا من وصف المهمة وتقوم أنت بتحريره. تعود عدة مراحل لاحقة إلى هنا عندما يتبيّن أن الموجّه هو المشكلة، مما يجعل هذه المرحلة محور سير العمل كله وليست خطوة تُنفَّذ مرة واحدة.
من هنا إما أن يمر المشروع بحلقة الحالات الحدية أو ينتقل مباشرة إلى التعليق التوضيحي المتوازي.
توليد الحالات الحدية، ثم تصنيف الحالات الحدية
يولّد النموذج أمثلة حدية وتقوم أنت بتصنيفها. يمكن أن يعود التصنيف إلى مراجعة الموجّه إذا أظهرت الأمثلة أن الموجّه خاطئ.
التحقق من الموجّه
تُقارَن تصنيفاتك للحالات الحدية بما ينتجه الموجّه. إما أن يتقدم المشروع إلى التعليق التوضيحي المتوازي أو يعود إلى مراجعة الموجّه.
التعليق التوضيحي المتوازي
تعلّق أنت والنموذج على البيانات نفسها في الوقت نفسه. هذه هي المرحلة التي تنتج رقم الاتفاق الذي يعتمد عليه كل ما بعده.
حل الخلافات
حيث تختلف أنت والنموذج، تحسم أنت الأمر. يعود المشروع إلى التعليق التوضيحي المتوازي، أو إلى مراجعة الموجّه عندما تشير الخلافات إلى الموجّه لا إلى عناصر بعينها.
التعليق التوضيحي النشط
مرحلة التعليق التوضيحي الرئيسية، وتُختار فيها العناصر من خلال المجمّعات الموزونة في instance_selection. من هنا يمكن أن ينتقل Potato إلى المراجعة الدورية أو مراجعة القواعد أو إلى التصنيف الذاتي.
المراجعة الدورية
تصنيفات النموذج منخفضة الثقة، تُعرض كل thresholds.periodic_review_interval عنصرًا. يعود المشروع إلى التعليق التوضيحي النشط، أو ينتقل إلى مراجعة القواعد، أو يرجع إلى مراجعة الموجّه.
مراجعة القواعد
قواعد الحالات الحدية التي استخرجها Potato من تصنيفك، معروضة للموافقة عليها. يعود المشروع إلى التعليق التوضيحي النشط أو إلى مراجعة الموجّه.
التصنيف الذاتي
يصنّف النموذج ما تبقى. مخرجه الوحيد هو التحقق النهائي.
التحقق النهائي
تفحص عينة من التصنيفات التي وضعها النموذج وحده. تجاوز thresholds.end_human_annotation_agreement يُكمل المشروع، والإخفاق فيه يعيده إلى التعليق التوضيحي النشط.
مكتمل
حالة نهائية.
الإعداد
البدء السريع
إعداد أدنى للوضع الفردي:
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"مرجع الإعداد الكامل
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"القدرات الرئيسية
تحليل الالتباس
بعد كل جولة تصنيف، يبني Potato مصفوفة التباس بين تصنيفات الإنسان وتصنيفات النموذج. تعرض لوحة تحكم المسؤول:
- الدقة والاستدعاء ومقياس F1 لكل فئة من منظور النموذج
- أكثر أزواج الالتباس شيوعًا (مثل: "neutral مصنف خطأً على أنه positive: 23 عنصرًا")
- أمثلة على العناصر لكل زوج التباس
- مخططات اتجاه تُظهر التحسن عبر جولات التحسين
لا يملك الوضع الفردي واجهة سطر أوامر. فهو يعمل داخل الخادم ويُدار من صفحاته الخاصة ضمن النسخة قيد التشغيل، لذا يُقرأ التحليل من لوحة التحكم لا من CLI. هذا مثال على ما يعرضه:
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
حلقة التحسين الآلية
تتنقل حلقة التحسين بين تصنيف النموذج وتحليل الالتباس وتحديث الإرشادات. في كل تكرار:
- يصنّف النموذج مجموعة البيانات كاملة وفق الإرشادات الحالية
- يقارن Potato النتائج بجميع التصنيفات البشرية المتاحة
- إذا كانت الدقة دون العتبة، يُجرى تحليل الالتباس
- يقترح النموذج تعديلات على الإرشادات بناءً على أنماط الأخطاء
- يراجع الإنسان التعديلات ويوافق عليها
- تتكرر الدورة (حتى
max_cycles)
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دوال التصنيف (مستوحاة من ALCHEmist)
يولّد Potato دوال تصنيف خفيفة من الأنماط الملحوظة في التعليقات التوضيحية البشرية. هذه ليست استدعاءات للنموذج اللغوي، بل قواعد سريعة وحتمية.
أمثلة على دوال تصنيف مولَّدة:
# 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اضبط سلوك دوال التصنيف:
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مستكشف الخلافات
يعرض مستكشف الخلافات العناصر التي تتعارض فيها إشارات مختلفة. لكل عنصر، يرى المعلّق:
- التصنيف الذي تنبأ به النموذج ودرجة ثقته
- أصوات دوال التصنيف (إن وُجدت)
- أقرب الجيران المصنَّفين في فضاء التضمينات
- النص أو المحتوى الخام
هذا هو نشاط التعليق التوضيحي الأعلى قيمة، إذ يحسم كل تصنيف غموضًا حقيقيًا.
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التصعيد المتتالي حسب الثقة
بعد أن يصنّف النموذج الجزء الأكبر من مجموعة البيانات، يرتّب Potato جميع العناصر التي صنّفها النموذج حسب الثقة ويصعّد الأقل ثقة منها إلى الإنسان. يستمر ذلك على دفعات حتى تستقر الجودة.
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نماذج القرار
بدءًا من Potato 2.11، يمكن لنموذج قرار أن يصنّف في الوضع الفردي. يجيب نموذج القرار عن سؤال ذي اختيارات ثابتة في تمريرة أمامية واحدة ويعيد احتمالًا لكل خيار، مما يجعله أسرع وأرخص من النموذج اللغوي الكبير في التصنيف، لكنه لا يستطيع كتابة الموجّهات أو القواعد أو التفسيرات. ويصل إليه نوعان من نقاط النهاية. يشغّل laya نموذج Laya داخل عملية Potato على المعالج المركزي (CPU) ويحتاج إلى pip install 'potato-annotation[decision]'، ويتصل systemone بأي خادم يوفّر واجهة /v1/systemone، مثل Jev المستضاف أو OpenJev.
المكان المعتاد لنموذج القرار هو المستوى الأول من التوجيه حسب الثقة، حيث يصنّف كل شيء، ولا ينتقل إلى النموذج اللغوي الكبير إلا العناصر التي لا يكون متأكدًا منها:
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 نموذجًا توليديًا. وقيمته الافتراضية هي labeling_models، لذا يجب على الدراسة التي يكون نموذجها الوحيد نموذج قرار أن تضبطه. تصنّف نماذج القرار مخططات radio وselect وlikert وslider، ويرفض الوضع الفردي البدء إذا ضُبط أحدها لتصنيف مخططات multiselect أو الامتدادات النصية (span) أو النص الحر. وعلى مقاييس التقدير، بالكاد تتبع درجات Laya المقياس، فافحص بضعة عناصر باستخدام Try on 10 items قبل توجيه مخطط likert أو slider عبره. والثقة هي الاحتمال الذي أعطاه النموذج للخيار الذي اختاره، وتختلف معايرتها باختلاف المجال، لذا اضبط عتبة المستوى من بياناتك أنت. ويقدّم config-decision-model.yaml نسخة قابلة للتشغيل.
الاقتراحات العمياء
افتراضيًا تعرض صفحة التعليق التوضيحي تصنيف النموذج اللغوي الكبير وثقته وزر قبول قبل أن تجيب، وهذا سريع، لكنه يشدّ إجابتك نحو الاقتراح أيضًا. يسلّم الوضع الفردي بقية المدوّنة إلى النموذج اللغوي الكبير حين يتجاوز اتفاقك معه end_human_annotation_agreement، لذا فإن الاتفاق المقيس على تصنيفات أعطيتها بعد رؤية الاقتراح قد ينهي دورك في العمل قبل الأوان. وبدءًا من Potato 2.11، يتحكم solo_mode.suggestions في وقت ظهور الاقتراح:
solo_mode:
suggestions:
display: blind_sample # before_label | after_label | blind_sample
blind_rate: 0.2
minimum_blind_sample: 20يخفي blind_sample الاقتراح على نسبة blind_rate من العناصر، ولا يعرضه after_label أولًا أبدًا. وبمجرد وجود minimum_blind_sample من المقارنات العمياء، يقارن التسليم الاتفاق الأعمى بـ end_human_annotation_agreement. وتعرض بطاقة Blind Agreement في لوحة التحكم الاتفاق الأعمى والاتفاق مع العرض جنبًا إلى جنب، والفجوة الموجبة الكبيرة تعني أنك تتفق مع النموذج اللغوي الكبير أكثر حين تستطيع رؤية إجابته.
ويجعل Potato 2.11 أيضًا الوضع الفردي يفحص سقف الإنفاق الخاص بالمشروع (ai_budget.cap_usd) قبل بدء التصنيف وقبل كل دفعة، ويضيف ذاكرة تخزين مؤقت للردود (solo_mode.cache)، ومجموعة ذهبية مع تجارب للموجّهات (solo_mode.gold)، وفحصًا لحساسية الموجّه، ولجنة تحكيم للتصنيف (solo_mode.jury)، وترتيبًا وفق منهج متدرّج (solo_mode.instance_selection.curriculum). وتوثّق صفحة Solo Mode Advanced Features كلًا منها. وحين يكون محرّك الوسم مفعّلًا، يكتب الوضع الفردي أيضًا تنبؤات نماذجه في مخزن المحرّك، فيستطيع المحرّك معايرتها والإشهاد عليها.
ترتيب أولويات العناصر متعدد الإشارات
في جميع المراحل التي تتضمن تصنيفًا بشريًا، يستخدم Potato نظام مجمّعات موزونة لاختيار العناصر الأكثر إفادة. تغذي سبعة مجمّعات قائمة أولويات موحدة:
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: تنخفض ثقة النموذج عن
thresholds.confidence_low - diversity: بعيد، في فضاء التضمينات، عما صنّفته بالفعل
- llm_predicted: لدى النموذج تصنيف لم يُتحقق منه بعد
- disagreement: الإشارات المتاحة للعنصر لا تتفق
- random: سحب عشوائي صغير، لإبقاء التقدير نزيهًا واكتشاف النقاط العمياء
- cartography: إشارة من ديناميكيات التدريب، معطّلة افتراضيًا
- edge_case_rule: يطابق قاعدة مستخرجة من تصنيفك السابق، معطّل افتراضيًا
توليد الحالات الحدية
يستخدم Potato النموذج لتوليد أمثلة اصطناعية تستهدف نقاط ضعف معروفة:
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يولّد النموذج أمثلة ملتبسة بين أزواج التصنيفات المحددة. يصنّفها الإنسان، وتُضاف هذه التصنيفات إلى سياق الأمثلة القليلة (few-shot) في جولات تصنيف النموذج اللاحقة.
تحسين الموجّهات (مستوحى من DSPy)
يُجري Potato تحسينًا آليًا للموجّهات للعثور على أفضل صيغة تعليمات للنموذج، ويبحث عن أصغر نموذج يظل محافظًا على الدقة المستهدفة:
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متابعة التقدم
تعرض لوحة تحكم المسؤول تقدم الوضع الفردي في الوقت الفعلي:
- المرحلة الحالية والتقدم داخل كل مرحلة
- التصنيفات البشرية المكتملة مقابل الميزانية الإجمالية
- دقة النموذج بمرور الوقت (لكل جولة)
- تغطية دوال التصنيف ودقتها
- مدرج تكراري لتوزيع الثقة
- الوقت المقدّر حتى الاكتمال
لا توجد وحدة potato.solo ولا واجهة سطر أوامر للوضع الفردي. سير العمل كله يقع خلف مسارات الخادم نفسه، لذا يُقرأ التقدم من لوحة التحكم. وهي تعرض:
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
متى تستخدم الوضع الفردي مقابل التعليق التوضيحي التقليدي متعدد المعلّقين
استخدم الوضع الفردي عندما:
- لديك خبير في المجال يمكنه تقديم تصنيفات عالية الجودة
- الميزانية أو الجوانب اللوجستية تمنع توظيف معلّقين متعددين
- المهمة لها فئات واضحة ومحددة جيدًا
- تحتاج إلى تصنيف مجموعة بيانات كبيرة (1,000+ عنصر)
- السرعة أهم من قياس الاتفاق بين المعلّقين
استخدم التعليق التوضيحي التقليدي متعدد المعلّقين عندما:
- تحتاج إلى إحصائيات الاتفاق بين المعلّقين للنشر
- المهمة ذاتية للغاية (مثل الإساءة أو الفكاهة)
- تحتاج إلى دراسة أنماط الخلاف بين المعلّقين
- المتطلبات التنظيمية تفرض معلّقين مستقلين متعددين
- فضاء التصنيفات معقد أو متغير (إرشادات التعليق التوضيحي لا تزال قيد التطوير)
النهج الهجين: استخدم الوضع الفردي للتصنيف المبدئي بالجملة، ثم كلّف معلّقًا ثانيًا بعينة عشوائية نسبتها 10-20% لحساب إحصائيات الاتفاق. يجمع هذا بين كفاءة الوضع الفردي وضمان الجودة الذي يوفره التحقق متعدد المعلّقين.
ليس للوضع الفردي كتلة تحقق خاصة به. شغّل المعلّق الثاني كجولة عادية في Potato على التصنيفات المصدَّرة، واحسب الاتفاق بين تصنيفاته وتصنيفات الوضع الفردي كما تفعل مع أي معلّقَين اثنين. (يملك icl_labeling كتلة verification، لكنها تخص التصنيف داخل السياق، لا الوضع الفردي.)
قراءة إضافية
- دليل الوضع الفردي: تصنيف 10,000 مثال -- شرح تفصيلي خطوة بخطوة
- التعلم النشط -- نظام التعلم النشط الأساسي
- دعم الذكاء الاصطناعي -- إعداد تكامل النموذج اللغوي الكبير
- مراقبة الجودة -- ضمان جودة التعليقات التوضيحية
- MACE -- تقدير الكفاءة (مفيد للتحقق في الوضع الهجين)
لمزيد من تفاصيل التنفيذ، راجع الوثائق المصدرية.