تقييم وكلاء الذكاء الاصطناعي: كيف تبني evals وتقيس الموثوقية لا الانطباع
تقييم وكلاء الذكاء الاصطناعي (evals) هو تشغيل منتظم لمجموعة ثابتة من المهام الحقيقية، مع فحص آلي للنتيجة وحساب للمقاييس، لا الاكتفاء بانطباع من جلستين ناجحتين. والمهم أن تقيس pass@k (نجحت محاولة واحدة على الأقل من k) وpass^k (نجحت كل المحاولات الـ k)، لأن الثبات هو ما يحدد إمكانية تكليف الوكيل بالعمل دون إشراف.
لماذا نحتاج تقييم وكلاء الذكاء الاصطناعي ما دام العمل واضحاً؟
الواقع أن الرؤية هنا سيئة. هل توقف الوكيل خلال أسبوع عن التعثر بعد تعديل الـ prompt؟ أهو إصلاح حقيقي أم أسبوع من المهام السهلة؟ يقتنع مهندس بأن القالب الجديد غيّر كل شيء، بينما يقرأ زميله السجل نفسه ولا يلاحظ فرقاً. كلاهما محق بقدر ما لم يحسب شيئاً.
تقييم الوكلاء (evals) يستبدل الانطباع بالرقم. تأخذ مجموعة ثابتة من المهام، وتشغّل الوكيل، وتفحص النتيجة آلياً، وتقارن المقاييس قبل التغيير وبعده. فيُحسم الجدل حول «هل تحسّن الأمر؟» بجدول لا بسلطة شخص.
من دون evals يصبح أي تغيير في الهارنس، من prompt أو AGENTS.md أو مجموعة الأدوات أو النموذج، رهاناً أعمى. ومعها يصبح تجربةً لها نتيجة قابلة للقياس.
لماذا يخدعنا الانطباع؟
لانطباعنا عن عمل الوكيل ثلاثة انحيازات منهجية، وكلها تدفع نحو يقين زائف.
- تحيز البقاء. تُتذكَّر التشغيلات الناجحة وتُعرض على الزملاء، أما الفاشلة فتُعاد أو تُنسى. الموثوقية المحسوبة من الناجح وحده لا تخبرك أين ينكسر الوكيل فعلاً.
- عينة صغيرة. ثلاث مهام ناجحة متتالية حدث عادي حتى لوكيل ينجح في نصف الحالات. احتمال ذلك 0.5 أس 3 = 12.5%، أي تقريباً مرة في كل ثماني سلاسل.
- نبرة واثقة. يكتب الوكيل «تم، وكل الاختبارات تمر» بالثقة نفسها سواء كان ذلك صحيحاً أم لا. ثقة النموذج غير معايرة، ونبرة الإجابة ليست مؤشراً على صحتها.
من هنا القاعدة: كل ما لم يُسجَّل ولم يُحسب يُعدّ غير مقاس.
pass@k وpass^k: مقياسان يُخلط بينهما
الوكيل غير حتمي: المهمة نفسها قد تنجح عند إعادتها وقد تفشل. لذلك تُشغَّل المهمة عدة مرات ويُحسب أحد مقياسين.
pass@k: نجحت محاولة واحدة على الأقل من k
المقياس قادم من تقييم توليد الشيفرة. يجيب عن سؤال: «هل النظام قادر أصلاً على حل المهمة إذا أُعطي عدة محاولات؟». وهو مقياس صادق في حالة يختار فيها الإنسان أفضل نتيجة من بين عدة نتائج، أو عندما يوجد فحص آلي موثوق يستبعد المحاولات الفاشلة.
pass^k: نجحت كل المحاولات الـ k
يجيب هذا المقياس عن سؤال آخر: «ما مدى ثبات الوكيل في حل المهمة؟». وهو يصف العمل دون إشراف، حين يُشغَّل الوكيل مرات كثيرة وتكلّف كل إخفاقة مالاً أو وقتاً.
الفرق بينهما كبير. لنفترض أن الوكيل يحل المهمة باحتمال 70% في المحاولة الواحدة، وأن المحاولات مستقلة:
| k | pass@k = 1 − 0.3^k | pass^k = 0.7^k |
|---|---|---|
| 1 | 70% | 70% |
| 3 | 97.3% | 34.3% |
| 5 | 99.8% | 16.8% |
| 10 | ~100% | 2.8% |
بمقياس pass@5 يبدو الوكيل مثالياً تقريباً، وبمقياس pass^5 يبدو غير موثوق. كلا الرقمين صحيح، لأنهما يصفان أشياء مختلفة. إذا كنت تنوي ترك الوكيل يعمل بشكل مستقل فانظر إلى pass^k، فهو أقرب إلى ما ستراه في العمل الفعلي.
كيف يُحسب عملياً
شغّل كل مهمة n مرة (مثلاً 5) وسجّل عدد النجاحات c. بالنسبة إلى pass^k يساوي تقريباً نسبة التشغيلات التي نجحت فيها المحاولات الـ k كلها متتالية، والأبسط أن تقدّر احتمال النجاح p = c / n وترفعه للأُسّ k. ولمجموعة المهام تأخذ المتوسط عبر المهام.
import json
from statistics import mean
# results.jsonl: {"task": "add-pagination", "runs": [true, true, false, true, true]}
rows = [json.loads(line) for line in open("results.jsonl")]
def pass_at_k(runs, k):
p = sum(runs) / len(runs)
return 1 - (1 - p) ** k
def pass_pow_k(runs, k):
p = sum(runs) / len(runs)
return p ** k
for k in (1, 3, 5):
print(k,
round(mean(pass_at_k(r["runs"], k) for r in rows), 3),
round(mean(pass_pow_k(r["runs"], k) for r in rows), 3))
التقدير بالأُسّ تقريبي عند n صغيرة، لكنه يكفي عادة للمقارنة بين نسخ الهارنس. الأهم أن يبقى n ومجموعة المهام ثابتين بين المقارنات.
كيف تُبنى مجموعة المهام للتقييم
مجموعة المهام هي الأصل الأهم. مقياس جيد على مهام رديئة يقيس الشيء الخطأ.
خذ المهام من واقعك
البنشمارك العامة مثل SWE-bench مفيدة لمقارنة النماذج، لكن مهامها مختارة: وصف واضح واختبارات جاهزة. أما في مستودعك فالمتطلبات غامضة وبعض الاختبارات غير موجودة، لذلك يكون رقم البنشمارك دائماً أعلى مما سيُظهره الوكيل عندك. أفضل مصدر للمهام هو التذاكر المغلقة والإخفاقات الحقيقية للوكيل من السجل.
تركيب المجموعة
- من 20 إلى 50 مهمة للبداية. الأقل منها يبتلع الضوضاء الفرق بين النسخ، والأكثر يصبح مكلفاً فيتوقف الناس عن تشغيله.
- أنواع متنوعة: ميزة جديدة، إصلاح خطأ، إعادة هيكلة، مهمة في وحدة غريبة، ومهمة فيها فخ (حيث الجواب الصحيح هو «لا يجوز فعل هذا» أو «يلزم توضيح»).
- كل مهمة تفشل في العمل تصبح اختباراً. هكذا تنمو المجموعة مع فهمك لمواضع ضعف الوكيل، ولا تعود الانتكاسات دون أن تُلاحظ.
- حالة بداية ثابتة: commit محدد، وتبعيات مثبتة، وبيئة واحدة. وإلا فأنت تقيس انجراف البيئة لا الوكيل.
شكل المهمة
كل مهمة هي وصف وحالة بداية ومعيار نجاح قابل للفحص دون إنسان.
id: add-pagination
repo_ref: 3f2c1ab
prompt: |
أضف الترقيم الصفحي إلى GET /payments: المعاملان limit (الافتراضي 20، والحد الأقصى 100)
وcursor. يحتوي الرد على next_cursor.
check:
- pytest tests/test_payments_pagination.py
- mypy app/
limits:
max_changed_files: 6
لاحظ أن معيار النجاح هو Definition of Done مكتوباً بأوامر. وإذا تعذّر كتابة المعيار لمهمة ما فهذه إشارة إلى أن المهمة مُسندة إلى الوكيل بغموض أيضاً.
الفحص الآلي أم حكم LLM؟
يمكن فحص النتيجة بالشيفرة أو بنموذج آخر. ولكل طريقة نطاقها.
| الفحص الآلي (شيفرة) | حكم LLM | |
|---|---|---|
| ما الذي يفحصه | الاختبارات، والأنواع، والمدقق اللغوي، وe2e، وحجم الـ diff، والملفات الممنوعة | مطابقة المتطلبات، وسهولة القراءة، والأسلوب، وجودة الشرح |
| الحتمية | كاملة | لا: التقييم يتذبذب من تشغيل إلى آخر |
| التكلفة | شبه معدومة | استدعاء نموذج إضافي لكل مهمة |
| الخطر الأكبر | لا يفحص كل شيء: الاختبارات خضراء والميزة غير المطلوبة | يوافق الحكم على حل واثق لكنه خاطئ |
القاعدة: الشيفرة أولاً، والحكم فوقها
كل ما يمكن فحصه حتمياً ففحصه حتمياً. أضف حكم LLM فقط للخصائص التي لا تُعبَّر عنها الشيفرة، ولا تستعمله أبداً بديلاً عن الاختبارات.
كيف تجعل حكم LLM مفيداً
- سياق مختلف عن المولِّد. لا ينبغي للحكم أن يرى استدلال الوكيل، بل المهمة والمعايير والـ diff النهائي فقط. وإلا كرّر الأخطاء نفسها. هذا هو مبدأ N-versioning: رأيان مستقلان بدلاً من رأي واحد.
- قائمة تحقق بدل «قيّم من عشرة». أسئلة محددة بإجابة نعم/لا: «هل يوجد تحقق من أن limit لا يتجاوز 100؟»، «هل تغيّرت ملفات خارج app/payments؟».
- معايرة على تصنيف يدوي. صنّف يدوياً 20 إلى 30 نتيجة وقارنها بأحكام الحكم. إذا كان التطابق ضعيفاً فعدّل قائمة التحقق، ولا تثق بالحكم أكثر.
- عدم تماثل الأخطاء. الحكم الخاطئ بـ«جاهز» أغلى من الحكم الخاطئ بـ«غير جاهز»: الأول يصل إلى الإنتاج، والثاني يكلّف إعادة تشغيل واحدة. اضبط الحكم ليرفض عند الشك.
مقاييس أخرى غير نسبة النجاح
نسبة المهام المحلولة قمة الجبل فقط. ولمعرفة أين يجب الإصلاح تحتاج مقاييس الموثوقية من الهندسة الكلاسيكية.
- MTBF: عدد الخطوات أو المهام التي يجتازها الوكيل قبل أن يتوقف. يُظهر مدى ندرة تعطّله.
- MTTR: الوقت اللازم للعودة إلى حالة عمل بعد عطل. تخفيضه غالباً أرخص من رفع MTBF: ملف تقدم جيد وبيئة قابلة للتكرار تقلّصان الاستعادة بمقدار كبير.
- نطاق الضرر: كم من الشيفرة تُفسده خطوة فاشلة واحدة. يُحدّ بسقف على الـ diff وبعزل نسخة العمل.
- نسبة «المنجز» الكاذب: المهام التي أعلن فيها الوكيل النجاح بينما فشل الفحص. أخطر المقاييس على الإطلاق، فهو يبيّن هل يمكن الوثوق بتقرير الوكيل.
- التكلفة والزمن: الـ tokens والدقائق لكل مهمة. هارنس رفع النجاح 5% لكنه ضاعف التكلفة لا يفوز دائماً.
سجل الإخفاقات: evals من العمل اليومي
ليس كل فريق مستعداً لبناء منظومة تشغيل كاملة. والنسخة الدنيا من التقييم سجل إخفاقات من ثلاثة أعمدة.
| المهمة | النتيجة | الطبقة |
|-------------------------|------------------------------------|---------------|
| ترقيم /payments الصفحي | «تم»، واختباران أحمران | التحقق |
| إصلاح مهلة webhook | 30 دقيقة على pip install | البيئة |
| إعادة هيكلة refunds | صيغة ORM قديمة | السياق |
الطبقة هي واحد من خمسة أماكن ينكسر فيها الوكيل: مواصفات المهمة، والسياق، وبيئة التنفيذ، وتغذية التحقق الراجعة، وإدارة الحالة. بعد عشرين سجلاً يتضح عنق الزجاجة الحقيقي، ونادراً ما يكون في المكان الذي كنت تظنه. وكل سطر في السجل مرشح لأن يصبح مهمة في مجموعة الـ evals.
لماذا لا تنقذ النماذج القوية الوضع؟
أول رد فعل على إخفاقات الوكيل هو اختيار نموذج أغلى. أحياناً يفيد ذلك، لكن غالباً تُغلق الفجوة بين البنشمارك وواقعك لا بالنموذج، بل بالبيئة المحيطة به.
إذا قضى الوكيل نصف ساعة في إعداد البيئة فهذه مشكلة طبقة البيئة، والنموذج الرائد سيقضي الوقت نفسه في الإعداد. وإذا قال الوكيل «تم» مع اختبارات حمراء فهذه مشكلة طبقة التحقق: لا توجد أمر يقول له الحقيقة. وإذا كتب شيفرة بأسلوب غريب عن المشروع فلأنه لم تُعطَ له أعراف المشروع. لا واحدة من هذه المشكلات تتعلق بذكاء النموذج.
تتيح الـ evals فحص ذلك بأمانة. شغّل المجموعة بالنموذج الحالي وبنموذج أغلى، ثم بالنموذج الحالي مع إضافة AGENTS.md فيه أوامر التحقق. غالباً ما يعطي التغيير الثاني مكسباً أكبر من الأول وبلا تكلفة. لكن لا تصدّق ذلك على الكلام، ولهذه المقارنات بالضبط وُجدت المجموعة.
خطة عملية: تقييم وكلاء الذكاء الاصطناعي في أسبوع
- اليوم الأول. افتح سجل إخفاقات واكتب فيه كل فشل للوكيل مع تحديد الطبقة.
- اليوم الثاني. اختر 20 مهمة من التذاكر المغلقة والسجل. ولكل مهمة ثبّت الـ commit واكتب معيار النجاح بأوامر.
- اليوم الثالث. اكتب مشغّل التقييم: نسخة عمل نظيفة، وتشغيل الوكيل بنص المهمة، وتشغيل الفحوص، وتسجيل النتيجة في JSONL.
- اليوم الرابع. شغّل كل مهمة 3 إلى 5 مرات. واحسب pass@1 وpass^3 ونسبة «المنجز» الكاذب ومتوسط التكلفة.
- اليوم الخامس. غيّر شيئاً واحداً في الهارنس وأعد التشغيل. قارن فقط عند تطابق المجموعة وعدد التكرارات.
غيّر متغيراً واحداً في كل مرة. إذا غيّرت النموذج والـ prompt والأدوات معاً في تجربة واحدة فلن تعرف ما الذي نجح.
أخطاء شائعة في تقييم الوكلاء
- تشغيل واحد لكل مهمة. عدم الحتمية تجعل النتيجة يانصيباً. ثلاثة تكرارات على الأقل.
- تغيّر المجموعة بين المقارنات. أضفت مهام جديدة وغيّرت الـ prompt في الوقت نفسه، فالأرقام غير قابلة للمقارنة.
- الوكيل يرى اختبارات التحقق. إذا كانت الاختبارات في المستودع فقد يعدّل الوكيل الشيفرة لتناسبها، أو يعدّل الاختبارات نفسها. احفظ الفحوص المخفية خارج نسخة العمل، وتحقق من أن الوكيل لم يلمس ملفات الاختبار.
- تقرير الوكيل بدل الفحص. عبارة «كل الاختبارات نجحت» في رد النموذج ليست نتيجة. النتيجة هي رمز خروج الأمر الذي شغّله المشغّل.
- pass@k وحدها. رقم جميل للعرض وتنبؤ سيئ للعمل المستقل.
خلاصة
تقييم وكلاء الذكاء الاصطناعي يعني مجموعة ثابتة من المهام الحقيقية، وفحوصاً آلية، ومقاييس تُعاد حسابها بعد كل تغيير في الهارنس. يخبرك pass@k بما يستطيع الوكيل فعله، ويخبرك pass^k إن كان يمكن الوثوق به دون إشراف. الفحوص الآلية تعطي الحقيقة، وحكم LLM بقائمة تحقق وسياق منفصل يكمّلها حيث تعجز الشيفرة. وسجل الإخفاقات على الطبقات الخمس يُظهر ما يجب إصلاحه أولاً، وغالباً لا تكون المشكلة في النموذج. وتُشرح مقاييس الموثوقية والحلقة التشخيصية بالتطبيق العملي في دورة الهارنس.
الأسئلة الشائعة
كم مهمة أحتاج لتقييم وكيل ذكاء اصطناعي؟
للبداية تكفي من 20 إلى 50 مهمة حقيقية لها معيار نجاح آلي، مع 3 إلى 5 تكرارات لكل منها. المجموعة الأصغر لن تميّز التحسن من الضوضاء، والأكبر تصبح مكلفة فيتوقف الناس عن تشغيلها.
هل يمكن تقييم الوكيل بالبنشمارك العامة وحدها؟
لا. البنشمارك العامة تقارن النماذج على مهام مختارة لها اختبارات جاهزة، بينما المتطلبات والاختبارات في مستودعك مختلفة. لقرارات تخص الهارنس الخاص بك تحتاج إلى مجموعة مهام خاصة بك.
ما الفرق بين pass@1 وpass^1؟
لا فرق: مع محاولة واحدة يتساوى المقياسان وهما نسبة التشغيلات الناجحة. يبدأ الفرق عند k أكبر من واحد.
هل يمكن أن يكون حكم LLM هو النموذج نفسه الذي يعمل به الوكيل؟
يمكن، إذا كان له سياق منفصل: يرى المهمة وقائمة التحقق والـ diff النهائي فقط، دون استدلال الوكيل. لكن أحكامه تحتاج إلى مقارنة بتصنيف يدوي على أي حال.
كم مرة يجب تشغيل الـ evals؟
بعد كل تغيير ملحوظ في الهارنس: الـ prompt أو ملف التعليمات أو مجموعة الأدوات أو النموذج. ومن المفيد أيضاً تشغيل المجموعة وفق جدول زمني لاكتشاف انجراف البيئة والتبعيات.
يُشرح هذا الموضوع بالتفصيل مع التطبيق العملي في دورة «Harness Engineering: инженерия надёжности AI-агентов».
- Метрики надёжности AI-агента: MTBF, MTTR, радиус поражения и закон Литтла
- Почему AI-агент ломается в проде: пять слоёв отказа и диагностическая петля