Skip to content
إعلاناتمدة القراءة 7 دقيقة

Potato 2.3: التوصيف الوكيلي والوضع الفردي ومقياس الأفضل والأسوأ

يضيف Potato 2.3.0 الوضع الفردي (Solo Mode) للتوسيم المشترك بين الإنسان ونموذج اللغة الكبير، وتوصيف مسارات الوكلاء، ومقياس الأفضل والأسوأ، وتسجيل الدخول عبر SSO وOAuth، والتصدير إلى Parquet، و15 مشروعاً تجريبياً.

Potato Team

ملاحظة: يصف هذا المنشور Potato 2.3 كما كان عند إصداره في مارس 2026. أُعيدت تسمية عدد من مفاتيح الإعداد الواردة أدناه أو استُبدلت في إصدارات لاحقة، والصيغة الحالية موجودة في التوثيق. لا تنسخ هذه الكتل إلى مشروع يعمل بإصدار حالي من Potato.

يضيف Potato 2.3.0 الوضع الفردي (Solo Mode)، وهو سير عمل للتوسيم بين الإنسان ونموذج اللغة الكبير يمر بعشر مراحل موثقة، إلى جانب توصيف مسارات الوكلاء مع أحد عشر محوّلاً مسجلاً للمسارات، ومقياس الأفضل والأسوأ (Best-Worst Scaling) مع ثلاث طرق لحساب الدرجات، وتسجيل الدخول عبر SSO وOAuth لكل من Google وGitHub ومزودي OIDC العامّين، والتصدير إلى Parquet، و15 مشروعاً تجريبياً. تسجل ملاحظات الإصدار 50 عملية commit أو أكثر منذ الإصدار 2.2.0، وإصلاح 12 ثغرة أمنية في 8 وحدات.

يأتي هذا الإصدار استجابة لتغير في ما يوصّفه الناس. فالباحثون الذين كانوا قبل عامين يوسمون المشاعر والكيانات المسماة صاروا اليوم يفككون مسارات وكلاء متعددة الخطوات، ويقارنون مخرجات النماذج بكميات كبيرة، ويبنون مجموعات بيانات لمهام لم تكن موجودة حين صُممت مجموعة مخططات Potato. والوضع الفردي والعمل على مسارات الوكلاء موجهان كلاهما إلى هذا التحول.

الترقية

bash
pip install --upgrade potato-annotation==2.3.0

يحتاج التصدير إلى Parquet إلى PyArrow بالإصدار 12.0.0 أو أحدث، ويُثبَّت بشكل منفصل:

bash
pip install "pyarrow>=12.0.0"

توصيف مسارات الوكلاء

تشغيل الوكيل هو سلسلة من استدعاءات الأدوات وخطوات الاستدلال والمخرجات الوسيطة، وتسطيحه إلى نص عادي يُضيّع البنية التي يحتاج المُقيّم إلى رؤيتها. لذلك يعرض Potato 2.3 المسارات عبر نظام العرض، فيظهر المسار على هيئة محادثة ترتبط فيها التقييمات بأدوار منفردة.

يُعرَّف العرض في instance_display، وتتداخل مخططات التقييم لكل دور تحت الحقل الذي يحمل المحادثة:

yaml
instance_display:
  layout:
    direction: vertical
    gap: 16px
  fields:
    - key: task_description
      type: text
      label: "Task"
    - key: conversation
      type: dialogue
      label: "Agent Trace"
      span_target: true
      display_options:
        show_turn_numbers: true
        alternating_shading: true

يتولى نوعان من أنواع العرض عمل الوكلاء في الإصدار 2.3. يعرض نوع dialogue المسار على هيئة أدوار ويدعم توصيف المقاطع فوقها، ويغطي interactive_chat المحادثات التي يشارك فيها المُوصِّف بدلاً من أن يقرأها بعد وقوعها. ضبط span_target: true هو ما يتيح للمُوصِّفين تظليل مقطع داخل دور، وبهذه الطريقة تُعلَّم الهلوسات والادعاءات غير المدعومة في موضع حدوثها.

تدخل المسارات القادمة من أطر عمل أخرى عبر المحوّل، الذي يسجل في هذا الإصدار أحد عشر تنسيقاً: openai وanthropic وswebench وotel وmcp وmulti_agent وlangchain وlangfuse وreact وwebarena وatif.

bash
python -m potato.trace_converter -i traces.json -f react -o data/traces.jsonl

الوضع الفردي

يتطلب التوسيم بعدة مُوصِّفين توظيف أشخاص وتدريبهم وتنسيق عملهم، وفي كثير من المشاريع البحثية تكون هذه اللوجستيات هي عنق الزجاجة لا واجهة التوصيف. أما الوضع الفردي فيقرن خبيراً واحداً في المجال بنموذج لغة كبير. يوسم الإنسان، ويقترح النموذج، ويعود كل تصحيح إلى الموجِّه (prompt)، ويسلّم الإنسان جزءاً أكبر من قائمة الانتظار كلما تقارب الاثنان.

يمر سير العمل بعشر مراحل موثقة: الإعداد، ومراجعة الموجِّه، وتوليد الحالات الحدية، وتوسيم الحالات الحدية، والتحقق من الموجِّه، والتوصيف المتوازي، وحل الخلافات، والمراجعة الدورية، والتوسيم الذاتي، والتحقق النهائي. ولا يمر كل مشروع بكل المراحل.

yaml
solo_mode:
  enabled: true
 
  labeling_models:
    - endpoint_type: "ollama"
      model: "qwen3:4b"
      endpoint_url: "http://localhost:11434"
      max_tokens: 256
      temperature: 0.1
 
  revision_models:
    - endpoint_type: "ollama"
      model: "qwen3:4b"
      endpoint_url: "http://localhost:11434"
 
  uncertainty:
    strategy: "direct_confidence"
 
  thresholds:
    end_human_annotation_agreement: 0.90
    minimum_validation_sample: 20
    confidence_low: 0.5
    periodic_review_interval: 50
 
  instance_selection:
    low_confidence_weight: 0.4
    diversity_weight: 0.3
    random_weight: 0.2
    disagreement_weight: 0.1
 
  state_dir: "solo_state"

تحدد أوزان instance_selection الأربعة أي العناصر تستحق انتباه الإنسان. إعطاء الثقة المنخفضة وزن 0.4 والتنوع وزن 0.3 يوجّه معظم وقت الإنسان إلى الحالات التي لا يثق بها النموذج، مع الإبقاء على تغطية كافية لبقية التوزيع لرصد أي خطأ منهجي. أما الوزن 0.2 للعينات العشوائية فهو ما يجعل تقدير الاتفاق في end_human_annotation_agreement ذا معنى، لأن معدل الاتفاق المحسوب على الحالات الصعبة وحدها ليس المعدل الذي ستحصل عليه على المدوّنة كاملة.

يأتي الوضع الفردي مع 85 اختباراً للتكامل وللعمل من البداية إلى النهاية، ودليل للمطورين، ومشروعين نموذجيين في examples/advanced/solo-mode/ وexamples/advanced/simple-solo-mode/. ابدأ بالمشروع البسيط، فهو يعمل مع نموذج Ollama محلي ولا يحتاج إلى مفتاح API، وبذلك يكون أول ما تقيّمه هو ملاءمة سير العمل لمهمتك، لا ما إذا كان النموذج يستحق تكلفته.

مقياس الأفضل والأسوأ

يعرض مقياس الأفضل والأسوأ على المُوصِّف مجموعة (tuple) من العناصر، أربعة في الغالب، ويطلب منه فقط اختيار الأفضل والأسوأ وفق معيار واحد. يتضمن هذان الاختياران مجموعة من المقارنات الزوجية، والدرجات المستخلصة من مجموعات كثيرة متداخلة تأتي على مقياس حقيقي، انطلاقاً من أحكام أسرع من إعطاء تقدير.

yaml
annotation_schemes:
  - annotation_type: bws
    name: sentiment_bws
    description: "Sentiment Intensity"
    best_description: "Which sentence expresses the MOST positive sentiment?"
    worst_description: "Which sentence expresses the LEAST positive sentiment?"
    tuple_size: 4
    sequential_key_binding: true

تعمل ثلاث طرق لحساب الدرجات على المجموعات التي جُمعت. counting هي خط الأساس الشفاف بالصيغة (best_count - worst_count) / appearances، ولا تحتاج إلى أي تبعية إضافية، ونتائجها حتمية. أما bradley_terry فتلائم نموذج مقارنة زوجية وتنتج معاملات قوة على مقياس لوغاريتمي. وتلائم plackett_luce نموذج ترتيب كامل. وتحتاج الطريقتان القائمتان على النماذج إلى pip install choix.

bash
python -m potato.bws_scoring --config config.yaml --method bradley_terry

تُكتب الدرجات في bws_scores.tsv داخل مجلد المخرجات، مع درجة كل عنصر وترتيبه وعدد مرات اختياره الأفضل والأسوأ وعدد مرات ظهوره. وتضم لوحة الإدارة تبويب BWS Scoring الذي يجري الحساب نفسه بضغطة زر ويعرض النتائج في جدول.

SSO وOAuth

يحتاج أي نشر يصل إليه المُوصِّفون عبر الإنترنت إلى حسابات حقيقية، ولذلك يضيف الإصدار 2.3 دعم OAuth 2.0 وOpenID Connect ليتمكنوا من استخدام الهوية التي يملكونها أصلاً. الدعم متاح لـ Google وGitHub وأي مزود OIDC عام، ويمكن تقييد الوصول حسب نطاق البريد الإلكتروني أو حسب منظمة GitHub.

yaml
authentication:
  method: "oauth"
  providers:
    google:
      client_id: ${GOOGLE_CLIENT_ID}
      client_secret: ${GOOGLE_CLIENT_SECRET}
  user_identity_field: "email"
 
secret_key: ${POTATO_SECRET_KEY}

أضف هذه الكتلة إلى ملف الإعداد. ويأتي معها شرطان. يحتاج OAuth إلى نشر عبر HTTPS، مع استثناء localhost لأغراض التطوير، ويحتاج إلى secret_key ثابت، لأن مفتاح التوقيع الذي يتغير مع كل إعادة تشغيل يُبطل الجلسات التي أصدرها تسجيل الدخول بالفعل. سجّل عنوان إعادة التوجيه لدى المزود بالشكل https://your-domain.com/auth/callback/google، مع وضع اسم المزود في مكانه.

التصدير إلى Parquet

ينتهي المطاف ببيانات التوصيف بشكل متزايد في أدوات تحليل تتوقع تنسيقاً عمودياً، ولذلك يضيف الإصدار 2.3 تنسيق Parquet إلى سجل التصدير. ينتج التصدير ما يصل إلى ثلاثة جداول: annotations.parquet بصف واحد لكل حالة ومُوصِّف، وspans.parquet بصف واحد لكل توصيف مقطع، وitems.parquet ببيانات المصدر.

bash
python -m potato.export -c config.yaml -f parquet -o ./export/

تُمرَّر الخيارات عبر سطر الأوامر ولا تُضبط في المشروع، وترميز الضغط واحد من snappy (الافتراضي) أو gzip أو zstd أو lz4 أو none:

bash
python -m potato.export -c config.yaml -f parquet -o ./export/ \
    --option compression=gzip --option include_items=false

تُربط الجداول عبر مفتاح الحالة، وإن اختلف اسم العمود بينها: يحمل annotations.parquet وspans.parquet العمود instance_id، بينما يحمل items.parquet العمود item_id. وهذا ما يجعل التصدير قابلاً للاستخدام من DuckDB دون تحميل أي شيء في pandas أولاً:

python
import duckdb
duckdb.sql("""
  SELECT i.item_id, a.user_id, a.*
  FROM './export/annotations.parquet' a
  JOIN './export/items.parquet' i ON a.instance_id = i.item_id
""")

يحتوي annotations.parquet على صف واحد لكل حالة ومُوصِّف، ويُسطَّح كل مخطط توصيف في عمود خاص به، فلا يوجد عمود عام باسم value يمكن اختياره. والمخطط الذي يخزن عدة إجابات في آن واحد يتوسع إلى أعمدة فرعية تحتوي أسماؤها على نقطة بالشكل <scheme>.<part>.

الإصلاحات الأمنية

يصلح الإصدار 12 ثغرة أمنية في 8 وحدات، إلى جانب مشكلات في XSS والمتانة وسلامة البيانات عبر 25 ملفاً، وخللاً في الحذف المتتالي للمقاطع كان يمر على مفاتيح القاموس بدلاً من قيمه فيترك سجلات الروابط خلفه. كما حدّثت مراجعة للتبعيات تبعيات Python وJavaScript إلى إصداراتها الحالية.

اثنان من الإصلاحات الأخرى ربما غيّرا بيانات جمعتها بالفعل. فقد أثّر انهيار متعلق بالقيمة المنطقية has_free_response (المشكلة #111) وحلقة تنقل في وضع جميع المراحل على تسجيل التوصيفات كما هو مقصود، وأثّرت معالجة علامات الاقتباس في multirate الديناميكي على طريقة كتابة تلك القيم. إذا أجريت دراسة على الإصدار 2.2 باستخدام خيارات الإجابة الحرة أو مخططات multirate، فتحقق من المخرجات قبل اعتبارها نهائية.

المشاريع التجريبية

يتضمن الإصدار 15 مشروعاً تجريبياً في demo/، مرقمة بحسب ترتيب بناء بعضها على بعض، من 01-sentiment-admin إلى 15-agentic-chat، وتغطي المقاطع، وتخطيطات الإشراف المخصصة، وتصنيف الصور، والمشاعر في الصوت، والفيديو، والعناصر متعددة الوسائط، والتحكيم، والمنزلقات، والصناديق المحيطة، وأشجار الاعتماد، وتوصيف ELAN متعدد الطبقات، والدردشة الوكيلية. يحتوي كل مجلد تجريبي على config.yaml ومجلد data/ الخاص به، وتتشارك المجموعة سكربتاً واحداً يولّد الوسائط التي تحتاجها المشاريع القائمة على الوسائط.

bash
# From the repository root: generates the demo data, then starts all 15 servers
bash demo/launch.sh

للاطلاع على سجل التغييرات الكامل، بما في ذلك كل إصلاح ذُكر أعلاه، راجع ملاحظات إصدار v2.3.0 في المستودع. أبلغ عن المشكلات على GitHub أو ابدأ نقاشاً في GitHub Discussions.

روابط