تخطّي إلى المحتوى

تهيئة تدريب النماذج ومساراته

كل مفتاح في كتلة model_training، وكيف تُرتَّب التشغيلات في الطابور وتُقيَّم وتُخزَّن، ومسارات الإدارة والوكيل، مع حلول لأخطاء التشغيل الشائعة.

جديد في v2.14.0

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

تهيئة كاملة

تدرّب التهيئة أدناه مصنِّف مشاعر على مراجعات منتجات. يعيد auto_retrain تدريب sklearn-text بعد كل 25 تعليقاً توضيحياً جديداً. ومع ميزات TF-IDF الافتراضية يتدرّب sklearn-text على المعالج ولا يحتاج إلى شيء يتجاوز التثبيت العادي لـ Potato. ولذلك تكلّف التشغيلات التلقائية المتكررة قليلاً. وتعرض الكتابة الراجعة على المعلّقين كل تنبؤ بثقة لا تقل عن 0.8. ومع include_unlabeled تتنبأ التشغيلة أيضاً بالمراجعات التي لم يصنّفها أحد بعد. وتخدم القيم الافتراضية لـ hf-text-classification والخلفية gpu-server التشغيلات التي تُبدأ يدوياً من صفحة التدريب:

yaml
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
  - "data/reviews.json"
item_properties:
  id_key: "id"
  text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels: ["positive", "negative"]
 
model_training:
  enabled: true
  split_seed: 0
  splits: {train: 0.7, val: 0.15, test: 0.15}
  aggregation: consensus
  retain_runs: 5
  queue_max: 10
  max_wall_seconds: 3600
  max_ram_mb: 8192
  num_threads: 4
  trainer_params:
    sklearn-text:
      classifier: sklearn.linear_model.LogisticRegression
      classifier_kwargs: {max_iter: 1000}
    hf-text-classification:
      model_name: answerdotai/ModernBERT-base
      epochs: 4
      lora: true
  auto_retrain:
    enabled: true
    trainer: sklearn-text
    schemas: [sentiment]
    min_interval_s: 600
    update_frequency: 25
  writeback:
    schemas: [sentiment]
    min_confidence: 0.8
    include_unlabeled: true
  backends:
    gpu-server:
      type: ssh
      host: gpu-server
      python: /opt/conda/bin/python3
      gpus: auto
      min_free_gpu_mb: 4000

أبقِ split_seed ثابتاً طوال عمر الدراسة. فالبذرة الجديدة تعيد توزيع كل العناصر، فتصبح العناصر التي كانت محجوزة جزءاً من التدريب، وتكفّ الدرجات اللاحقة عن أن تكون قابلة للمقارنة بالسابقة. والحدّ الأدنى للثقة min_confidence البالغ 0.8 نقطة بداية، ويعتمد الحدّ المناسب على درجة العناصر المحجوزة الأولى. فعّل include_unlabeled حين تدعم تلك الدرجة عرض التصنيفات المسبقة، لأن التصنيفات المسبقة تثبّت المعلّقين على إجابة النموذج.

المفاتيح في model_training

كل مفتاح يقع تحت model_training:

المفتاحالقيمة الافتراضيةالمعنى
enabledfalseيسجّل صفحة التدريب والمسارات تحت /admin/training ومسارات الوكيل تحت /api/training. ومن دون enabled: true لا توجد المسارات.
retain_runs5التشغيلات المنتهية المحفوظة في سجل التشغيلات. تغادر التشغيلة الأقدم السجل ما لم تكن تنبؤاتها ما زالت مخزّنة. وتبقى مجلدات التشغيلات على القرص.
grace_seconds20الثواني التي تُمنح للتشغيلة الملغاة لتخرج قبل أن ينهي Potato العملية. صفر أو أكثر، وتُرسل مع المهمة إلى الخلفيات من النوع ssh وslurm وagent.
queue_max10عدد التشغيلات التي يجوز أن تنتظر خلف التشغيلة الجارية.
split_seed0البذرة لتوزيع العناصر على أقسام train وval وtest.
splits{train: 0.7, val: 0.15, test: 0.15}كسور الأقسام، وتُطبَّع ليكون مجموعها 1. الأسماء هي train وval وtest، وtrain مطلوب.
aggregationconsensusكيف تصبح تصنيفات عدة معلّقين على عنصر تصنيفاً واحداً. يلائم consensus نموذج Dawid-Skene حين يكون في الدراسة أكثر من معلّق، ويعود إلى تصويت الأغلبية إذا فشل الملاءمة. ويأخذ majority تصويت الأغلبية.
max_wall_secondsغير مضبوطحدّ زمني لتشغيلة واحدة. يفحص Potato التشغيلة المحلية في كل مرة تبلغ فيها عن حدث، وتشغيلة ssh أو الوكيل كل ثانية.
max_ram_mbغير مضبوطحدّ لمساحة العناوين لعملية التدريب، يُضبط بـ setrlimit. وعلى منصة لا تدعم الحدّ تسجّل التشغيلة تحذيراً وتواصل.
deviceautoauto أو cpu أو cuda أو cuda:N أو mps. يختار auto وحدة CUDA ثم Metal من Apple ثم المعالج.
num_threadsغير مضبوطيضبط OMP_NUM_THREADS وMKL_NUM_THREADS وOPENBLAS_NUM_THREADS للتشغيلة، ما لم تكن البيئة تضبط هذه المتغيرات أصلاً.
auto_retrainمعطّلإعادة التدريب مع وصول التعليقات التوضيحية. انظر auto_retrain.
writebackلا شيءنشر التنبؤات تصنيفات مسبقة. انظر writeback.
backendlocalالخلفية للتشغيلات التي لا تسمّي خلفية أخرى.
backendsلا شيءخلفيات مسمّاة من الأنواع ssh وslurm وagent. انظر الخلفيات.
max_predictions_mb512أكبر predictions.jsonl يجوز لوكيل بعيد أن يرفعه.
trainer_paramsلا شيءالقيم الافتراضية للمعاملات، مفهرسة باسم المُدرِّب.
tilingenabled: autoتقطيع الصور الكبيرة إلى مربعات لمُدرِّبات الكشف والتجزئة. انظر tiling.

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

auto_retrain

تفحص إعادة التدريب التلقائية الحاجة إلى تشغيلة جديدة بعد كل حفظ لتعليق توضيحي:

المفتاحالقيمة الافتراضيةالمعنى
enabledfalseيشغّل الفحص.
trainerلا شيءاسم المُدرِّب. مطلوب.
schemasلا شيءالمخططات المراد تدريبها. مطلوب.
min_interval_s600الثواني منذ انتهاء آخر تشغيلة قبل أن تبدأ تشغيلة أخرى.
update_frequency25التعليقات التوضيحية الجديدة منذ آخر تشغيلة تلقائية قبل أن تبدأ تشغيلة أخرى.
params{}معاملات المُدرِّب، كما في params لتشغيلة عبر API.
backendmodel_training.backendالخلفية للتشغيلات التلقائية.
accept_licencefalseيؤكد ترخيص مُدرِّب يطلب التأكيد (ultralytics-detect وultralytics-segment وlayoutlmv3). ومن دون التأكيد تُتخطى التشغيلات التلقائية لتلك المُدرِّبات.

حين يقرر الفحص عدم بدء تشغيلة يظهر السبب في الحقل skip_reason في GET /admin/training/api/status، مثل "waiting for 3 more annotation(s)" أو "a run is already in progress". ولا تنضم التشغيلات التلقائية إلى طابور التشغيلات. فالتعليق التوضيحي التالي الذي يُحفظ بعد أن يفرغ الطابور يفحص من جديد، ومعه تعليقات أكثر للتدريب عليها. ويحتفظ Potato بأعداد التعليقات التوضيحية في الذاكرة، ولذلك يعدّ المشروع الذي تدرّب من قبل التعليقات الجديدة بعد إعادة التشغيل من لحظة إعادة التشغيل.

writeback

تقرر الكتابة الراجعة أي التنبؤات يراها المعلّقون:

المفتاحالقيمة الافتراضيةالمعنى
schemas[]المخططات التي يرى المعلّقون تنبؤاتها. القائمة الفارغة لا تعرض شيئاً.
min_confidence0.0التنبؤات التي تقل عن الحدّ تُخزَّن ولا تُعرض. والتنبؤ بلا ثقة يمرّ.
fieldpredictionsحقل العنصر الذي تُكتب فيه التصنيفات المسبقة.
include_unlabeledfalseيتنبأ أيضاً بالعناصر التي لم يصنّفها أحد، ويضع لها تصنيفات مسبقة. ومن دون include_unlabeled تتنبأ التشغيلة بعناصر val وtest الخاصة بها فقط.

tiling

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

المفتاحالقيمة الافتراضيةالمعنى
enabledautoيقطّع auto صيغ الشرائح (.svs و.ndpi و.mrxs و.scn وغيرها) والصور التي لا يقل ضلعها الأطول عن auto_min_side. ويقطّع true كل صورة، ولا يقطّع false أياً منها.
auto_min_side4096طول الضلع الأطول، بالبكسل، الذي يبدأ عنده auto تقطيع صورة.
tile_size1024ضلع المربع، بالبكسلات التي يراها المُدرِّب.
overlap128البكسلات التي يشترك فيها المربعان المتجاوران، وحدها الأقصى نصف tile_size. أبقِ التداخل بحجم الأجسام على الأقل، وإلا وُجد الجسم الكبير قطعاً.
downsample1بكسلات الدقة الكاملة لكل بكسل في المربع.
mppلا شيءالميكرونات لكل بكسل في المربع. يتجاوز downsample في شريحة تسجّل دقتها.
background0.25مربعات فارغة تُؤخذ عيّنة لكل مربع فيه جسم. اضبط background: 0 للشرائح التي عُلّق على جزء منها فقط.
max_predict_tiles2000أكثر عدد من المربعات يُتنبأ به لكل صورة. وتُبقى المربعات الأغنى بالنسيج.
min_visible0.4نصيب الجسم الذي يجب أن يقع داخل مربع ليتدرّب الجسم هناك.
tissue_threshold0.05نصيب مربع الشريحة الذي يجب أن يكون نسيجاً ليتنبأ النموذج على المربع.

تُقرأ الشرائح بـ openslide، ويثبّتها pip install "potato-annotation[wsi]"، على الجهاز الذي يبني بيانات التدريب. وتنزّل الخلفية البعيدة المربعات ولا تنزّل الشريحة أبداً.

طابور التشغيلات

تعمل تشغيلة واحدة في كل مرة. والتشغيلة التي تبدأ من صفحة التدريب أو API أثناء تشغيلة جارية تنتظر ولا تُرفض. يعيد طلب البدء الرمز 202 مع queued: true وposition التشغيلة، ويسرد جدول التشغيلات التشغيلة بالصيغة waiting #N مع زر Cancel run. وحين تنتهي التشغيلة الجارية تبدأ أقدم تشغيلة منتظرة.

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

أرسل "queue": false في متن الطلب لتحصل على 409 بدلاً من مكان في الطابور. وإذا كانت queue_max تشغيلات تنتظر بالفعل يحصل البدء الجديد على 429. ويسرد GET /admin/training/api/status التشغيلات المنتظرة بالترتيب تحت queue.

الفحوص قبل التشغيلة

يبلغ potato validate عن كل مشكلة في كتلة model_training دفعة واحدة، ويرفض الخادم البدء عند المشكلات نفسها:

bash
potato validate config.yaml --strict

تغطي الفحوص هذه الحالات:

  • splits باسم غير train وval وtest، أو كسر أقل من 0 أو ليس عدداً، أو كسور مجموعها 0، أو غياب train.
  • مفتاح ليس في writeback أو auto_retrain، أو مدخل في writeback.schemas ليس مخططاً، أو min_confidence خارج المدى من 0 إلى 1. ويُبلَّغ عن accept_license بوصفه خطأ إملائياً في accept_licence.
  • كتلة pre_annotation مفعّلة يختلف field فيها عن writeback.field. فلن يظهر أي تصنيف مسبق من التدريب تحت كتلة كهذه.
  • مع auto_retrain.enabled: مُدرِّب أو مخطط غير موجود، أو مخطط لا يستطيع المُدرِّب التعلّم منه، أو معاملات لا يقبلها المُدرِّب أو من نوع خاطئ، أو backend غير موجود في backends، أو decision-calibrate على خلفية غير local.
  • معامل تحت trainer_params لا يقبله المُدرِّب أو من نوع خاطئ. وداخل dp يشمل الفحص كل مفتاح ومدى قيمته.
  • قيمة grace_seconds أقل من 0 أو غير رقمية، أو قيمة retain_runs أو split_seed أقل من 0 أو غير عدد صحيح.
  • تحت backends: type مفقود أو غير معروف، أو مفتاح لا يوجد في النوع، أو خلفية ssh بلا host، أو قيمة gpus غير auto أو none أو فهارس GPU، أو خلفية بعيدة اسمها local، أو model_training.backend غير معرَّف.

يختبر potato training check خلفية واحدة قبل أن تستخدمها تشغيلة. وللخلفية local يطبع الأمر الجهاز الذي ستستخدمه التشغيلة، مثل local: this machine, Apple Metal (mps) على Mac بمعالج Apple. ولخلفية ssh يبلغ الأمر عن إصدار Python وكل GPU مع ذاكرته الحرة والـ GPU الذي ستحصل عليه التشغيلة وحِزم التدريب التي ينقصها مفسّر Python البعيد. ويؤدي زر Check في صفحة التدريب الاختبار نفسه، ويطبع --json التقرير بصيغة JSON:

bash
potato training check local config.yaml
potato training check gpu-server config.yaml

وتُفحص التشغيلة المبدوءة من صفحة التدريب أو API مرة أخرى عند بدئها. وتُسرد رموز الحالة تحت المسارات.

الخلفيات

تعمل التشغيلة على خلفية، وتسرد قائمة Runs on في صفحة التدريب الخلفيات المهيأة. يحدد model_training.backend الخلفية الافتراضية، ويستطيع تشغيل عبر API أو auto_retrain أن يسمّي خلفية مختلفة بـ backend. لدى Potato أربعة أنواع من الخلفيات:

النوعأين يعمل المُدرِّبمن يبدأ المُدرِّب
localهذا الجهاز، في عملية فرعية. متاحة دائماً، وهي الافتراضية.Potato
sshجهاز آخر يصل إليه Potato عبر ssh، مثل خادم GPU.Potato، عبر ssh
slurmعقدة حوسبة في عنقود، بوصفها مهمة دفعية.Potato، بـ ssh إلى عقدة تسجيل الدخول ثم sbatch
agentجهاز لا يصل إليه Potato، مثل محطة عمل خلف NAT.شخص، بالأمر potato training agent

تستخدم خلفية ssh المصادقة بالمفاتيح مع تفعيل BatchMode، فيفشل طلب كلمة المرور بدلاً من أن يتعلّق. وتستخدم خلفية slurm الأوامر sbatch وsqueue وscancel فقط، إضافة إلى scontrol في العناقيد التي توفّر scontrol، وتحتاج إلى remote_dir على تخزين تشترك فيه عقد الحوسبة. ولا تحتاج خلفية agent إلى منفذ وارد، لأن الوكيل هو الذي يفتح كل اتصال. والاسم local محجوز لهذا الجهاز، ولا يعمل decision-calibrate إلا على local. ويستعرض التدريب على خادم GPU أو عنقود SLURM أو جهاز خلف NAT الأنواع البعيدة الثلاثة بمفاتيحها.

درجات العناصر المحجوزة

تقيّم كل تشغيلة تنبؤاتها الخاصة على عناصر val وtest مقابل التصنيفات البشرية المحسومة. تحمل أسماء المقاييس القسم، كما في val_macro_f1 أو test_f1. والعنصر الذي له تصنيف ولا تنبؤ له يُحتسب خاطئاً، فلا يرفع استبعاد العناصر الصعبة درجة المُدرِّب. ويبلغ <split>_coverage عن نصيب العناصر التي حصلت على تنبؤ.

تظهر الدرجة الرئيسية في عمود Held-out score في جدول التشغيلات، مع القسم والمقياس في التلميح. والدرجة الرئيسية هي المقياس الرئيسي لأول مخطط على أول قسم من val وtest فيه عناصر. وحين اختار المُدرِّب أفضل نقطة حفظ بدرجة val يجرّب Potato test أولاً، لأن المُدرِّب رأى درجة val بالفعل. وتأخذ مُدرِّبات الضبط الدقيق التي تحتفظ بأفضل حقبة، مثل hf-text-classification وtorchvision-detect وllm-sft، الدرجة الرئيسية من test. أما sklearn-text وsetfit وrdkit-property ومُدرِّبات نماذج القرار وجسور الاستدلال فلا تختار شيئاً على val، وتأخذ تشغيلة أي منها الدرجة الرئيسية من val متى كان في val عناصر. وتُعرض التشغيلة التي لا عناصر val أو test فيها بعبارة "not scored".

يعتمد المقياس الرئيسي على نوع التعليق التوضيحي للمخطط، كما يبيّن الجدول أدناه للأنواع الشائعة:

نوع التعليق التوضيحيالمقياس الرئيسي
radio, select, likertmacro-F1 (وكذلك الدقة، ومتوسط الخطأ المطلق لتصنيفات likert الرقمية)
multiselectmicro-F1 (وكذلك macro-F1 والتطابق التام)
spanF1 على النطاقات المتطابقة في البداية والنهاية والتصنيف
texttoken F1 (وكذلك التطابق التام)
pairwise في وضع binaryالدقة على العناصر التي لم تُجب كتعادل
rankingKendall's tau
image_annotation, microscopy, geo_annotationCOCO mAP عند IoU 0.5 (map_50)، مع تسجيل map_50_95 أيضاً
audio_annotationF1 على المقاطع ذات التصنيف نفسه عند IoU 0.5 أو أكثر
speech_transcriptword_accuracy، أي 1 ناقص معدل أخطاء الكلمات
volume_annotationmean_dice

يمنح token F1 رصيداً لإجابة تستخدم الكلمات الصحيحة بترتيب خاطئ، ولذلك اقرأ token F1 مع التطابق التام. وتستخدم الدرجة الرئيسية للكشف IoU 0.5 بدلاً من متوسط 0.5 إلى 0.95، لأن صندوقَي معلّقَين لجسم واحد نادراً ما يتداخلان عند IoU 0.9. ويسرد جدول درجات العناصر المحجوزة في المرجع الأصلي المقاييس لكل نوع من أنواع التعليق التوضيحي.

الكتابة الراجعة

بعد تشغيلة ناجحة يخزّن Potato تنبؤات التشغيلة ويكتب التنبؤات التي تجتاز أربعة فحوص في حقل predictions لكل عنصر، أو في الحقل الذي يسمّيه writeback.field. تعمل الفحوص بهذا الترتيب، ويعدّ تقرير الكتابة الراجعة للتشغيلة كل تخطٍّ:

  1. لا تحصل عناصر قسم train على تصنيف مسبق أبداً. ويشمل الفحص قسم train لكل تشغيلة ما زالت في السجل، ويُزال التصنيف المسبق الذي تركته تشغيلة سابقة على عنصر حين تتدرّب تشغيلة لاحقة عليه.
  2. لا تُنشر إلا المخططات في writeback.schemas. القائمة فارغة افتراضياً، ولذلك لا يغيّر تفعيل التدريب شيئاً مما يراه المعلّقون.
  3. تُتخطى الأزواج المرفوضة. فالزوج (عنصر، مخطط) الذي له حكم reject في مراجعة النموذج لا يُعرض ثانيةً.
  4. يسري الحدّ الأدنى للثقة. التنبؤ الذي يقل عن min_confidence يُخزَّن ولا يُنشر.

لا تغيّر الكتابة الراجعة تصنيفاً بشرياً أبداً، لأن التنبؤات تدخل في بيانات العنصر بينما تعيش التعليقات التوضيحية في حالة كل معلّق. ويظهر التصنيف المسبق إجابةً معبّأة مسبقاً يستطيع المعلّق تحريرها، مثل خيار محدد في الاختيارات وإجابة نصية في مربع نص المخطط، ولا حاجة إلى كتلة pre_annotation. ولا يصبح التصنيف المسبق إجابة المعلّق إلا حين يعدّله المعلّق أو ينتقل إلى التالي. ولذلك لا يصبح التصنيف المسبق الذي لم يعدّله أحد ولم يتجاوزه أحد تصنيف تدريب أبداً. أما الزوج (معلّق، عنصر) الذي تضعه ai_support.holdout في مجموعة المقارنة بلا مساعدة في الدراسة فلا يعرض تصنيفاً مسبقاً، وتستبعد بيانات العنصر المرسلة لذلك الزوج كلاً من writeback.field وpre_annotation.field. وتقرير الكتابة الراجعة هو الحقل writeback في GET /admin/training/api/status، ويذكر summary في التقرير سبب عدم نشر التشغيلة شيئاً.

يحتفظ Potato بتنبؤ واحد لكل عنصر ومخطط، ويحل تنبؤ تشغيلة أحدث محل تنبؤ تشغيلة أقدم. وحين يُخزَّن التنبؤ الأحدث ولا يُعرض، لأنه أقل من min_confidence أو فارغ أو مرفوض، يُزال التصنيف المسبق للتشغيلة الأقدم عن العنصر فوراً، ويحسب تقرير الكتابة الراجعة العنصر في n_superseded_cleared. أما التصنيفات المسبقة المرفقة مع البيانات فتُترك كما هي. وعند البدء تُكتب التنبؤات المخزّنة للمخططات في writeback.schemas راجعةً إلى بيانات العناصر بالفحوص الأربعة نفسها، فتنجو التصنيفات المسبقة من إعادة التشغيل. ولسحب التصنيفات المسبقة لتشغيلة أرسل DELETE /admin/training/api/runs/<run_id>/predictions. يزيل الطلب التنبؤات المخزّنة ويرفع التصنيفات المسبقة عن العناصر.

التصحيحات والعناصر المثبّتة تتدرّب دائماً

يذهب نوعان من العناصر إلى قسم train في كل تشغيلة لاحقة، أياً كان موضع العنصر في التقسيم الثابت:

  • العناصر التي صحّحها مراجع. حكم correct في مراجعة النموذج يعني أن شخصاً أصلح إجابة النموذج. وتأتي التصحيحات من العناصر التي كان النموذج أسوأ ما يكون فيها، فيقيس عنصر مصحَّح في val أو test أداء النموذج على عيّنة من أخطائه هو. أما حكما accept وreject فيتركان العنصر حيث كان.
  • العناصر المثبّتة. يثبّت Train on these بجانب شريحة في صفحة الفهرس العناصر التي تطابقها الشريحة، مثل الشريحة المدمجة model-found-nothing. ويتدرّب العنصر المثبّت متى صنّفه أحد.

تسجّل التشغيلة التي نقلت عناصر محجوزة إلى train تحذيراً بالعدد. وتُحسب حينئذ درجة عناصرها المحجوزة من دون تلك العناصر، فلا تكون قابلة للمقارنة المباشرة بدرجة تشغيلة سابقة. والأعداد تحت stats.forced_train في manifest.json لبيانات التدريب.

حفظ قسم إصداراً من مجموعة بيانات

يحفظ Keep this split as a dataset في صفحة التشغيلة عناصر val أو test أو train للتشغيلة مع تصنيفاتها البشرية المتفق عليها إصداراً جديداً من مجموعة بيانات. لا يتغير إصدار مجموعة البيانات بعد ذلك، ولذلك يمكن مقارنة نماذج وموجِّهات نماذج لغوية كبيرة لاحقة على هذه العناصر بعينها. وتحتاج الميزة إلى datasets.enabled: true. ويضم كل إصدار محفوظ قسماً واحداً ويبدأ من الصفر بدلاً من الإضافة إلى آخر إصدار في مجموعة البيانات. فإضافة عناصر val للتشغيلة 2 إلى عناصر التشغيلة 1 كانت ستضم عناصر تدرّبت عليها التشغيلة 2. وتستبعد inputs كل مثال حقلَ التصنيف المسبق، فلا يستطيع تقييم قراءة إجابة النموذج.

من أين جاء التصنيف المسبق

يتضمن GET /admin/model-review الحقل provenance لكل عنصر في طابور المراجعة كتبت تشغيلةُ تدريب تصنيفه المسبق. ويعطي المدخل لكل مخطط معرّف التشغيلة والمُدرِّب ودرجة العناصر المحجوزة للتشغيلة. وليس للتصنيفات المسبقة المرفقة مع البيانات مدخل.

أين تُخزَّن التشغيلات

لكل تشغيلة مجلد في <task_dir>/<output_annotation_dir>/training/runs/<run_id>/:

المسارالمحتويات
bundle/بيانات التدريب: train.jsonl وval.jsonl وtest.jsonl وunlabeled.jsonl مع include_unlabeled وlabels.json وmanifest.json وmedia/.
artifacts/model_card.json وpredictions.jsonl والنموذج، مثل model.pkl لـ sklearn-text أو مجلد model/ لمُدرِّبات المحوِّلات.
spec.jsonما طُلب من التشغيلة.
events.jsonl, stdout.log, stderr.logأحداث تقدّم التشغيلة ومخرجاتها.
agent.logمخرجات الوكيل البعيد نفسه، في خلفيات ssh.
bundle.tar.gzبيانات التدريب كما نزّلها الوكيل، مع الوسائط، في الخلفيات البعيدة.

يعيش سجل التشغيلات في قاعدة بيانات المشروع <task_dir>/project.sqlite، ويسجّل التشغيلات وقسم كل عنصر في كل تشغيلة والعناصر المثبّتة للتدريب والتنبؤات المخزّنة ورموز الوكلاء وعمليات النشر على Hugging Face Hub. ويقلّم retain_runs السجل ولا يقلّم أبداً تشغيلة ما زالت تنبؤاتها مخزّنة، فيمكن تتبع كل تصنيف مسبق إلى التشغيلة التي كتبته. ويترك التقليم مجلدات التشغيلات على القرص.

تحفظ تشغيلة LoRA المهايئ فقط، من بضعة ميغابايتات إلى بضع مئات منها، وتحمّل النموذج الأساسي باسم model_name حين تتنبأ التشغيلة. أما الضبط الدقيق الكامل فيحفظ النموذج كله. اضبط متغير البيئة POTATO_MODEL_CACHE على مجلد، فتستخدم عملية التدريب ذلك المجلد لـ HF_HOME وTRANSFORMERS_CACHE وSENTENCE_TRANSFORMERS_HOME ما لم تكن تلك المتغيرات مضبوطة بالفعل. وعلى جهاز معزول عن الشبكة ضع النماذج التي تسمّيها المُدرِّبات في ذلك المجلد مسبقاً.

المسارات

تقع صفحة التدريب ومسارات JSON الخاصة بها تحت /admin/training وتحتاج إلى صلاحية المسؤول. وتعني صلاحية المسؤول جلسة مسؤول أو الترويسة X-API-Key. ويجب أن تكون طلبات POST وDELETE من المتصفح من المصدر نفسه. وتضع مواصفة OpenAPI لـ Potato على كل عمليات التدريب الـ 26 العلامة x-potato-requires-config: model_training.enabled: true:

المسارالغرض
GET /admin/trainingصفحة التدريب، بنموذج التشغيلة وقائمة التشغيلات والمُدرِّبات.
GET /admin/training/runs/<run_id>صفحة تشغيلة واحدة، بالحالة والمقاييس والأحداث وقسم كل عنصر.
GET /admin/training/api/trainersكل مُدرِّب، مع أنواعه ووسائطه وترخيصه وحالة تثبيته.
GET /admin/training/api/schemasمخططات الدراسة، ونوع كل مخطط، والمُدرِّبات التي تناسب كل مخطط.
GET /admin/training/api/statusالتشغيلة الحالية أو الأخيرة، بالحالة والتقدم والمقاييس والتحذيرات وskip_reason وwriteback وqueue.
GET /admin/training/api/runsسجل التشغيلات. ?limit= افتراضيه 50 وأقصاه 500.
POST /admin/training/api/runsيبدأ تشغيلة. 200 حين تبدأ التشغيلة، و202 مع queued: true وposition حين تنتظر.
GET /admin/training/api/runs/<run_id>سجل تشغيلة واحدة، إضافة إلى review، أي دقة تنبؤات التشغيلة بحسب أحكام المراجعة.
GET /admin/training/api/runs/<run_id>/eventsسجل أحداث التشغيلة. ?limit= افتراضيه 200.
POST /admin/training/api/runs/<run_id>/cancelيلغي التشغيلة الجارية أو تشغيلة منتظرة. 400 لأي معرّف تشغيلة آخر.
DELETE /admin/training/api/runs/<run_id>/predictionsيسحب التنبؤات المخزّنة للتشغيلة وتصنيفاتها المسبقة.
POST /admin/training/api/runs/<run_id>/push-to-hubينشر نموذج التشغيلة على Hugging Face Hub. انظر النشر على Hugging Face Hub.
POST /admin/training/api/runs/<run_id>/pin-splitيحفظ قسماً إصداراً من مجموعة بيانات، بالمتن {"dataset": name, "split": "val"}.
GET /admin/training/api/backendsالخلفيات المهيأة.
POST /admin/training/api/backends/<name>/checkيختبر خلفية، كما يفعل potato training check.
GET /admin/training/api/pinnedالعناصر المثبّتة، مجمّعة بحسب السبب.
POST /admin/training/api/pinnedيثبّت عناصر في train، بـ {"slice": name} أو {"instance_ids": [...]}.
DELETE /admin/training/api/pinnedيلغي تثبيت instance_ids المسرودة، أو كل عنصر مثبّت حين لا يسرد المتن شيئاً.

يقبل طلب التشغيلة trainer وschemas (قائمة أو اسماً واحداً) وparams وbackend وaccept_licence وqueue. ويدرّب كل مُدرِّب أول مخطط مسمّى فقط. يبدأ الطلب أدناه تشغيلة sklearn-text على مخطط sentiment في المثال:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'

يعطي البدء المرفوض السبب في error:

الحالةمتى
400لا مُدرِّب أو لا مخطط في المتن، أو مُدرِّب أو مخطط غير معروف، أو مخطط لا يستطيع المُدرِّب التعلّم منه، أو مُدرِّب لا يستطيع المشروع تشغيله، أو مُدرِّب يحتاج ترخيصه إلى تأكيد، مع needs_licence_ack: true، إلى أن يضبط الطلب accept_licence: true
409معامل لا يقبله المُدرِّب أو من نوع أو مدى خاطئ، أو خلفية غير معروفة، أو decision-calibrate على خلفية غير local، أو تشغيلة جارية مع "queue": false
429queue_max تشغيلات تنتظر بالفعل

بروتوكول الوكيل

يسجّل model_training.enabled أيضاً المسارات التي يستدعيها وكيل التدريب، تحت /api/training. يرسل الوكيل رمزه بالصيغة Authorization: Bearer <token>، ويحصل الرمز المفقود أو غير الصالح على 401. ويحتاج تسجيل خلفية إلى مفتاح API الخاص بالمسؤول بدلاً من ذلك. ويصف potato/training/protocol.py البروتوكول لمن يكتب وكيلاً جديداً، ويمثّل potato/training/agent.py التنفيذ المرجعي:

المسارالغرض
POST /api/training/backends/registerيصدر رمز وكيل لاسم خلفية، مع X-API-Key. يستدعي potato training register هذا المسار.
POST /api/training/backends/<name>/heartbeatيبلغ وكيل خامل أنه حي. 403 لرمز صدر لخلفية أخرى.
GET /api/training/jobs/next?wait=30استطلاع طويل. 200 مع مهمة، أو 204 حين لا تصل مهمة خلال wait ثانية.
GET /api/training/jobs/<run_id>المهمة ومواصفتها وهل أُلغيت.
GET /api/training/jobs/<run_id>/bundleبيانات التدريب بصيغة tar.gz، مع الوسائط. يجيب المسار عن طلبات Range، فيستأنف الوكيل تنزيلاً انقطع، حتى خمس محاولات. و410 متى زالت الحزمة.
POST /api/training/jobs/<run_id>/progressأحداث التقدم. ويعود الإلغاء في الاستجابة.
POST /api/training/jobs/<run_id>/predictionspredictions.jsonl. 413 فوق max_predictions_mb.
POST /api/training/jobs/<run_id>/completeرمز الخروج والأحداث الأخيرة.

QLoRA

يقبل llm-sft وllm-dpo وhf-text-classification وvlm-sft وreward-model الإعداد lora: {quantize: 4bit}، وهو إعداد QLoRA (Dettmers et al., 2023). يُحمَّل النموذج الأساسي بأوزان NF4 من 4 بتات وبتكميم مزدوج، ويتدرّب مهايئ LoRA فوقه بصيغة bf16 حيث يدعم الـ GPU صيغة bf16. وquantize: 8bit هو الخيار الوسط، وتحمّل التنبؤات النموذج الأساسي بالطريقة نفسها.

yaml
model_training:
  trainer_params:
    llm-sft:
      model_name: Qwen/Qwen2.5-7B-Instruct
      lora: {quantize: 4bit}

في 4 بتات تأخذ الأوزان الأساسية ربع الذاكرة التي تأخذها الأوزان نفسها في bf16، وتأتي التنشيطات والمهايئ وحالة المُحسِّن فوق ذلك. لم يقس Potato بعد ذاكرة تشغيلة QLoRA على GPU، ولذلك خطّط انطلاقاً من سطر "Peak GPU memory" في التشغيلة نفسها. تسجّل كل تشغيلة لمحوِّل هذا السطر في نهايتها. ويحتاج QLoRA إلى GPU من نوع CUDA وإلى بناء bitsandbytes لإصدار CUDA في ذلك الجهاز. وتتحقق التشغيلة من الأمرين قبل تحميل النموذج بتكميم بضعة أرقام على الـ GPU، وحين لا يتطابق الإصداران يسمّي الخطأ الإصدارين. ويطبّق درس الضبط الدقيق للنماذج اللغوية الكبيرة QLoRA على تشغيلات SFT وDPO.

النشر على Hugging Face Hub

للتشغيلة الناجحة التي يوجد نموذجها على خادم Potato الزر Publish to the Hugging Face Hub في صفحتها. يرفع النشر النموذج وبطاقة نموذج README.md مكتوبة من التشغيلة، تسمّي المُدرِّب والنموذج الأساسي والمهايئ والمخططات والتصنيفات وأحجام الأقسام ودرجة العناصر المحجوزة والقسم الذي قيست عليه الدرجة ومعرّفي التشغيلة والحزمة. وتضم بطاقة تشغيلة dp أيضاً صفاً بعنوان "Differential privacy" فيه epsilon المنفق مقابل الهدف، وdelta، وقسم train الذي يغطيه الضمان. ويحذف الصف الهدف أو delta حين لا تكون التشغيلة قد سجّلت القيمة.

الرفع قائمة ثابتة من الملفات وليس مجلد artifacts/ كله. تضم القائمة ملفات الأوزان، مثل .safetensors و.bin و.pt و.pkl، وملفات التهيئة والمُرمِّز في مجلد model/ المحفوظ، وmodel_card.json مع استبدال المسارات المحلية بأسماء ملفات، وcalibration.json. أما إجابات النموذج على عناصر المشروع (predictions.jsonl، وraw_answers.jsonl لنماذج القرار) فتبقى على الخادم. وتُستبعد كذلك نقاط الحفظ وحالة المُحسِّن ونسخ بيانات التدريب التي تصنعها بعض المُدرِّبات (yolo_data/ وwev_data/ وlaya_data/) وأي رابط رمزي يشير إلى خارج artifacts/.

يحمي النموذج من النشر العرضي أو العلني بعدة طرق:

  • تكتب اسم المستودع مرتين، ولا يمضي النشر إلا إذا تطابق الاسمان.
  • خيار Private محدد افتراضياً. وما دام Private محدداً لا ينشر Potato في مستودع عام موجود، ويجيب API بـ 409.
  • يسمّي النموذج متغير بيئة على الخادم، HF_TOKEN افتراضياً، يحمل رمز كتابة من Hugging Face. ولا يُكتب الرمز نفسه في الصفحة أبداً. ويجب أن يحتوي اسم المتغير على TOKEN أو يبدأ بـ HF_، وأن تبدأ القيمة بـ hf_، فلا تصل قيمة أي متغير آخر إلى Hub.
  • حين لا يستطيع Hub أن يقول هل المستودع موجود لا يُنشر شيء، ويُحذف المستودع الذي أنشأه النشر مرة أخرى إذا فشل الرفع بعد ذلك.
  • ترخيص بطاقة النموذج هو معرّف ترخيص Hub الذي تعطيه، مثل apache-2.0. وإن لم تعطِ شيئاً تذكر البطاقة أن ترخيص النموذج الأساسي هو الساري. والمُدرِّب الذي يحتاج ترخيصه إلى تأكيد، مثل ultralytics-detect (AGPL-3.0)، يحتاج إلى التأكيد نفسه للنشر.
  • النموذج المتروك على مضيف بعيد مع fetch_artifacts: false، أو المدرَّب على خلفية وكيل، لا يمكن نشره من الخادم، ويسمّي الخطأ مكان النموذج.

كل نشر هو commit واحد. وتسرد صفحة التشغيلة كل نشر مع المستودع والرؤية والـ commit، ويسجّل السجل من أجرى النشر. وعبر API يقبل متن POST /admin/training/api/runs/<run_id>/push-to-hub المفاتيح repo_id وconfirm_repo_id وprivate (والافتراضي true) وtoken_env (والافتراضي HF_TOKEN) وlicence وaccept_licence. ويعيد المسار 201 مع الـ commit، و400 عند عدم التطابق أو غياب متغير الرمز أو غياب ملفات النموذج أو ترخيص غير مؤكَّد، و502 حين يرفض Hub.

استكشاف الأخطاء

تغطي المدخلات أدناه الأخطاء الأرجح في الإعداد الأول. ويغطي قسم استكشاف الأخطاء في المرجع الأصلي برامج تشغيل GPU وإصدارات CUDA والرسائل الخاصة بكل مُدرِّب.

  • /admin/training يعيد 404. المفتاح model_training.enabled ليس true، ولا يسجّل Potato المسارات إلا حين يكون المفتاح true.
  • "Only N items in the train split". صنّف عناصر أكثر، أو خفّض min_instances في params التشغيلة. يضم قسم train 70% من العناصر المصنّفة افتراضياً.
  • "Schema 'x' has 1 distinct label(s) in the data". يحتاج المصنِّف إلى تصنيفين مستخدمين على الأقل.
  • "No resolved annotations to train on". المخطط المسمّى في التشغيلة يختلف عن المخطط الجاري التعليق عليه، أو لم يعلّق أحد على شيء بعد.
  • لم تنشر التشغيلة أي تصنيفات مسبقة. اقرأ تقرير writeback في GET /admin/training/api/status. العبارة "No predictions were published: write-back is not enabled for any schema" تعني أن writeback.schemas فارغة، وتبيّن أعداد التخطّي كم تنبؤاً أزاله كل فحص.
  • <trainer> does not take <name>. معامل في التشغيلة أو تحت trainer_params فيه خطأ إملائي أو ينتمي إلى مُدرِّب آخر. وتسرد الرسالة الأسماء التي يقبلها المُدرِّب.
  • قُتلت التشغيلة بعد أن نفدت ذاكرة الجهاز. خرجت العملية بالإشارة SIGKILL، وغالباً من قاتل نفاد الذاكرة. استخدم نموذجاً أصغر أو عناصر أقل، أو اضبط max_ram_mb لتفشل التشغيلة داخل حدّها الخاص.
  • "Stopped: the run took longer than model_training.max_wall_seconds". بلغت التشغيلة الحدّ الزمني. ارفع max_wall_seconds، أو درّب على عناصر أقل.
  • "The GPU ran out of memory". خفّض batch_size وارفع gradient_accumulation للحفاظ على الدفعة الفعلية، واضبط lora: true أو lora: {quantize: 4bit}، أو اضبط لـ llm-sft الخيار gradient_checkpointing: true أو اختر نموذجاً أصغر.
  • "ssh to host failed: Permission denied". يشغّل Potato الأمر ssh مع BatchMode=yes، ولذلك يجب أن ينجح ssh <host> true من حساب الخادم بلا طلب. ويعمل المفتاح ذو عبارة المرور حين يحمله ssh-agent.
  • تشغيلة على خلفية وكيل تبقى في الطابور. لا وكيل بهذا الاسم للخلفية يستطلع الخادم. شغّل وكيلاً بالأمر potato training agent --backend <name>، وافحص الرمز بزر Check في صفحة التدريب.

قراءات إضافية

المراجع