سير عمل بوابة تقييم الضبط الدقيق لنماذج LLM باستخدام Python
أنشئ بوابة إصدار محلية وقابلة للتدقيق لمجموعات بيانات الضبط الدقيق ومخرجات النماذج. يشرح هذا الدليل العملي كيفية التحقق من ملفات JSONL، وإنشاء بصمات لمجموعات البيانات، واكتشاف التداخل التام مع مجموعة الاختبار المحجوزة، وتقييم التنبؤات المنظمة، وإنتاج تقرير ترقية قبل اعتماد النموذج للاستخدام.
ملاحظة تحريرية: لا يحدد هذا الدليل عمداً نقطة رفع خاصة بمزوّد بعينه، أو معرّف نموذج، أو سعراً، أو API لمهام التدريب. يجب التحقق من هذه التفاصيل وفق الوثائق الرسمية الحالية وشروط معالجة البيانات المعتمدة في مؤسستك قبل إرسال أي مجموعة بيانات إلى مزوّد النماذج.
لماذا يجب وضع بوابة تقييم قبل الضبط الدقيق؟
يغيّر الضبط الدقيق سلوك النموذج باستخدام أمثلة خاصة بالمهمة. تميّز الأبحاث المتعلقة بتكييف نماذج اللغة الكبيرة بين الضبط الدقيق وPrompt Engineering: إذ يوجّه الـPrompt النموذج وقت الاستدلال، بينما يكيّف الضبط الدقيق السلوك انطلاقاً من corpus تدريبي. وتصف مراجعة شاملة لممارسات الضبط الدقيق دورة حياة تمتد من إعداد البيانات وتهيئة النموذج والتحسين، إلى التقييم والنشر. وتكتسب هذه الدورة أهميتها من أن اكتمال عملية تدريب لا يشكل، بحد ذاته، دليلاً على جاهزية النموذج للإصدار.
تحوّل بوابة الإصدار دورة الحياة هذه إلى أداة تحكم هندسية. قبل إرسال أي بيانات للتدريب، تحقق من أن الأمثلة تتبع المخطط المتوقع، وأن استجابات الهدف موجودة، وأن مجموعة الاختبار المحجوزة منفصلة. وبعد أن يعيد المزوّد نموذجاً مرشحاً، شغّل مطالبات الاختبار المحجوزة نفسها على النموذج الأساسي والمرشح، واحسب المقاييس الخاصة بالمهمة، واحفظ الأدلة، ولا تعتمد الترقية إلا عند اجتياز المتطلبات المحددة.
يفيد هذا النمط بصورة خاصة في المهام المستقرة والقابلة للقياس، مثل التصنيف والاستخراج والتنسيق المنضبط والتوجيه وقواعد مراجعة الكود. لكنه أقل ملاءمة كوسيلة لإدخال حقائق تتغير بسرعة. عندما يحتاج سير العمل إلى معلومات حالية عن السياسات أو المخزون أو الحسابات أو الحوادث، احصل عليها وقت التشغيل من أنظمة الاسترجاع المعتمدة أو الأنظمة الداخلية، بدلاً من افتراض أن مجموعة بيانات الضبط الدقيق ستبقى محدثة.
المتطلبات المسبقة
- Python ٣.١٠ أو أحدث.
- مجموعة بيانات تدريب موسومة ومجموعة اختبار محجوزة جرى إعدادها بشكل منفصل.
- نموذج أساسي ونموذج مرشح يمكن استدعاء كليهما عبر مسار الاستدلال المعتمد في مؤسستك.
- إجراء معتمد لمراجعة حقوق البيانات والمعلومات الحساسة ومتطلبات معالجة البيانات لدى المزوّد قبل الإرسال عن بُعد.
- إلمام أساسي بـJSON وJSON Lines وأدوات سطر الأوامر وبيئات Python الافتراضية.
يستخدم الكود أدناه مكتبة Python القياسية فقط. لذلك، يفيد قبل اختيار المزوّد ولا يفترض افتراضات غير متحقق منها حول SDK معيّن. مدخلاته هي بيانات JSONL وتنبؤات نماذج محفوظة، ويمكن لتكامل المزوّد المعتمد لديك إنشاء هذه التنبؤات لاحقاً.
الخطوة ١: أنشئ ملفات منفصلة للتدريب والاختبار المحجوز
استخدم JSONL، حيث يمثل كل سطر غير فارغ كائن JSON واحداً. تتمثل المهمة في هذا الدليل في توجيه طلبات الدعم. يتضمن ملف التدريب هدفاً للمساعد، بينما يتضمن ملف الاختبار المحجوز تسمية متوقعة يستخدمها المقيم فقط. لا ترسل بيانات expected الوصفية ضمن ملف تدريب المزوّد، ما لم يكن تنسيقه الموثق يسمح بذلك صراحة.
أنشئ data/train.jsonl:
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"My invoice shows two annual subscription charges."},{"role":"assistant","content":"{"queue":"billing","priority":"high"}"}]}
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"The dashboard fails when I export usage data."},{"role":"assistant","content":"{"queue":"technical","priority":"high"}"}]}
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"Someone changed our payout bank account without permission."},{"role":"assistant","content":"{"queue":"security","priority":"urgent"}"}]}أنشئ data/eval.jsonl بمطالبات لا تمثل نسخاً مكررة من مطالبات التدريب:
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"Our card was billed twice after adding seats."}],"expected":{"queue":"billing","priority":"high"}}
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"A former employee can still enter our organization."}],"expected":{"queue":"security","priority":"urgent"}}
{"messages":[{"role":"system","content":"Return JSON with queue and priority."},{"role":"user","content":"The mobile application closes immediately after launch."}],"expected":{"queue":"technical","priority":"high"}}الملفات الصغيرة أعلاه أمثلة على الصياغة وليست دليلاً كافياً لاتخاذ قرار إنتاجي. تحتاج مجموعة البيانات الفعلية إلى تغطية واسعة ومراجعة للحالات الشائعة والحالات الحدّية وتباين اللغة وأنماط الفشل المعروفة. وعند الحاجة، قسّم البيانات بحسب العميل أو الحادثة أو عائلة المستندات أو الفترة الزمنية. فقد يؤدي التقسيم العشوائي للصفوف إلى وضع مواد متطابقة تقريباً في التدريب والتقييم، ما يضخم النتائج بسبب تسرب البيانات.
الخطوة ٢: أنشئ أداة التحقق والتقييم المحلية
أنشئ fine_tune_gate.py. يتحقق البرنامج الكامل من مجموعتي البيانات، ويحسب بصمات SHA-256، ويرفض التداخل التام في المطالبات المطبّعة، ويقيّم التنبؤات المحفوظة. يحتوي ملف التنبؤات على كائن JSON واحد لكل حالة اختبار محجوزة، بالترتيب نفسه في ملف التقييم. ويجب أن يتضمن كل كائن سلسلة content تحتوي استجابة النموذج.
from __future__ import annotationsimport argparse
import hashlib
import json
import sys
from datetime import UTC, datetime
from pathlib import Path
from typing import AnyVALID_ROLES = {"system", "user", "assistant"}
VALID_QUEUES = {"billing", "technical", "security", "general"}
VALID_PRIORITIES = {"low", "normal", "high", "urgent"}def now() -> str:
return datetime.now(UTC).isoformat()def load_jsonl(path: Path) -> list[dict[str, Any]]:
if not path.is_file():
raise ValueError(f"Missing file: {path}")
records = []
for number, raw in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if not raw.strip():
continue
try:
value = json.loads(raw)
except json.JSONDecodeError as error:
raise ValueError(f"{path}:{number} is invalid JSON: {error.msg}") from error
if not isinstance(value, dict):
raise ValueError(f"{path}:{number} must be a JSON object")
records.append(value)
if not records:
raise ValueError(f"{path} has no records")
return recordsdef fingerprint(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()def validate_messages(record: dict[str, Any], location: str, require_target: bool) -> None:
messages = record.get("messages")
if not isinstance(messages, list) or len(messages) < 2:
raise ValueError(f"{location}:...تابع القراءة
سجل دخولك مجاناً لقراءة المقال كاملاً والوصول إلى أدوات الذكاء الاصطناعي.
تسجيل الدخول / إنشاء حساب