العودة إلى المدونة

الذكاء الاصطناعي للمبتدئيندليل

اختبر موجّهك على 20 حالة: تقييم بالمطابقة التامة في Python

ابنِ مجموعة اختبار من 20 حالة، وقيّم موجّهاً بالمطابقة التامة باستخدام سكربت Python قصير، وانظر هل ساعد تغيير الموجّه فعلاً.

بواسطة CheapTokens Teamنُشر في 6 دقيقة قراءة

الغلاف: مقتطف كود يقارن إجابة نموذج بالتصنيف المتوقع، بعنوان اختبر موجّهك على 20 حالة
في هذه الصفحة
  1. ابنِ مجموعة الاختبار: 20 رسالة والإجابة التي تتوقعها
  2. السكربت: أرسل كل حالة، قارن، اطبع الإخفاقات
  3. غيّر شيئاً واحداً، شغّل مرة أخرى
  4. المجموعة نفسها، نموذج آخر: هل يحافظ على الدرجة؟
  5. أين تتوقف المطابقة التامة عن العمل

نجح موجّهك على الرسالتين اللتين جرّبتهما. هل يعني ذلك أنه يعمل؟ ليس بعد. شغّله على 20 رسالة حقيقية بإجابات معروفة، واحسب كم منها يصيب، واقرأ التي يخطئها. سكربت Python قصير يقوم بالعدّ، وعندما تغيّر الموجّه يخبرك السكربت نفسه هل ساعد التغيير بدلاً من ترك الأمر لحدسك.

توثيق Anthropic حول تحديد معايير النجاح وبناء التقييمات (تم التحقق في 7 نوفمبر 2026) يصوغ ذلك بكلماته: اجعل الاختبارات خاصة بمهمتك، وضمّن الحالات الصعبة، وفضّل أسئلة كثيرة تُقيَّم آلياً على قليلة تُقيَّم يدوياً. فيما يلي أصغر نسخة من ذلك يمكنك تشغيلها اليوم.

أربع خطوات: 20 حالة تذهب إلى النموذج، تُقارن الإجابات بالمطابقة التامة، وتحصل على درجة دقة بالإضافة إلى الإخفاقات
الطريقة كاملة: حالات تدخل، رقم واحد وقائمة إخفاقات تخرج

ابنِ مجموعة الاختبار: 20 رسالة والإجابة التي تتوقعها#

لنفترض أنك تصنّف رسائل العملاء إلى ثلاث فئات: إيجابية أو سلبية أو مختلطة. افتح ملفاً باسم cases.csv واكتب 20 رسالة يمكن أن تستقبلها فعلاً، كل واحدة مع التصنيف الذي أنت ستعطيه إياها. اكتب التصنيفات قبل تشغيل أي شيء. إذا نسخت إجابات النموذج على أنها "صحيحة"، فلن يستطيع الاختبار إلا أن يوافق النموذج.

csv
text,label
"Arrived a day early and works perfectly. Thank you!",positive
"The charger stopped working after two days.",negative
"Great screen, but the battery barely lasts until lunch.",mixed
"Support answered in five minutes and fixed it.",positive
"I waited three weeks and nobody replied.",negative
"Oh great, another update that deletes my settings.",negative
"Nice design. Pity about the price.",mixed
"Exactly what I ordered.",positive
"The box was crushed, but the headphones inside are fine and sound great.",mixed
"Refund took 10 days. Never again.",negative
"Love it!!",positive
"Cheaply made, but honestly it does the job for the price.",mixed
"Worst purchase of the year.",negative
"Five stars. Would buy again.",positive
"Fast delivery, wrong colour.",mixed
"It's fine. Not amazing, not terrible.",mixed
"Zero issues in six months of daily use.",positive
"The app crashes every time I open the camera.",negative
"Thanks for nothing.",negative
"Setup was a pain, but once it ran, it's been rock solid.",mixed

انظر إلى المزيج: 6 إيجابية، 7 سلبية، 7 مختلطة. العبارات الساخرة ("Oh great, another update…"، "Thanks for nothing.") والحالة الحدّية ("It's fine. Not amazing, not terrible.") موجودة عن قصد. مجموعة مكوّنة من رسائل واضحة فقط تحصل على 100% ولا تعلّمك شيئاً. خذ الرسائل الحقيقية من صندوق بريدك أو تذاكرك أو تصدير الدردشة؛ الحالات الحدّية هي التي تعرف مسبقاً أنها مزعجة.

لماذا 20؟ إنه حجم بداية، وليس رقماً من التوثيق (مثالهم يستخدم 1,000 تغريدة). عشرون صغيرة بما يكفي لكتابتها يدوياً في نصف ساعة وكبيرة بما يكفي ألا تحدد إجابة محظوظة واحدة الدرجة.

السكربت: أرسل كل حالة، قارن، اطبع الإخفاقات#

تتكون الخطة من أربع خطوات، والكود يتبعها سطراً بسطر.

رتّب بالترتيب

رتّب حلقة التقييم

  1. حمّل الحالات العشرين من ملف CSV
  2. أرسل كل رسالة إلى النموذج مع موجّهك
  3. قارن الإجابة بتصنيفك
  4. اطبع الدقة والحالات التي فشلت

تعمل الحلقة فقط عندما تكون التصنيفات موجودة قبل أول استدعاء للنموذج، وتأتي الإخفاقات في النهاية لأنها ما تقرأه وتتصرف بناءً عليه.

ثبّت SDK باستخدام pip install openai واحفظ المفتاح في متغير بيئة باسم CHEAPTOKENS_API_KEY. أي واجهة برمجة متوافقة مع OpenAI تعمل بالطريقة نفسها؛ هنا يشير السكربت إلى CheapTokens وGLM-5.3-Flash (تفاصيل الإعداد في التوثيق).

python
import csv
import os
from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'zai-org/GLM-5.3-Flash'

PROMPT = (
    'Classify the customer message as positive, negative or mixed. '
    'Answer with one word only.'
)


def ask(text):
    r = client.chat.completions.create(
        model=MODEL,
        temperature=0,
        max_tokens=100,
        messages=[
            {'role': 'system', 'content': PROMPT},
            {'role': 'user', 'content': text},
        ],
    )
    return r.choices[0].message.content or ''


with open('cases.csv', newline='', encoding='utf-8') as f:
    cases = list(csv.DictReader(f))

correct, failed = 0, []
for case in cases:
    got = ask(case['text'])
    ok = got.strip().strip('.').lower() == case['label']
    correct += ok
    if not ok:
        failed.append((case['text'], case['label'], got.strip()))

print(f'Accuracy: {correct}/{len(cases)} = {correct / len(cases):.0%}')
for text, want, got in failed:
    print(f'- {text!r}: expected {want}, got {got!r}')

ثلاثة تفاصيل تستحق نظرة ثانية.

  • temperature=0 يبقي الإجابات ثابتة قدر الإمكان، بحيث يأتي التغيير في الدرجة من موجّهك وليس من النرد.
  • max_tokens=100 أكثر بكثير مما يحتاجه تصنيف من كلمة واحدة. إذا رجعت إجابة فارغة أو مقطوعة، تحقق من finish_reason؛ دليل finish_reason "length" يوضح ما يجب رفعه.
  • سطر التقييم هو وصفة التوثيق، strip().lower() مقارنةً بالإجابة الصحيحة، مع إضافة واحدة: يحذف أيضاً نقطة النهاية، لأن "Negative." و"negative" هما الإجابة نفسها بالنسبة لك.

ماذا ترى عند التشغيل؟ سطر دقة واحد، ثم سطر لكل إخفاق. لنفترض أن التشغيل الأول يطبع هذا:

text
Accuracy: 14/20 = 70%
- 'Oh great, another update that deletes my settings.': expected negative, got 'positive'
- "It's fine. Not amazing, not terrible.": expected mixed, got 'positive'
…

(الأرقام هنا افتراض لإظهار شكل المخرجات؛ أرقامك ستختلف.) السخرية والصياغة الحدّية هي نوع الرسائل التي يميل الموجّه القصير إلى إخفائها. النقطة هي أنك لم تعد تخمّن: لديك قائمة.

غيّر شيئاً واحداً، شغّل مرة أخرى#

الآن الجزء المفيد. اقرأ الإخفاقات، اختر سبباً، غيّر الموجّه في مكان واحد وأعد التشغيل. تغيير واحد في كل مرة، وإلا لن تعرف أي تعديل حرّك الدرجة.

قارن

الموجّه v1 → v2: أضف قاعدة ومثالين

v1

text
Classify the customer message as positive, negative or mixed.
Answer with one word only.

v2

text
Classify the customer message as positive, negative or mixed.
Sarcasm counts as negative. Praise plus a complaint is mixed.
Answer with one word only.

Message: Lovely colour, but it arrived with a scratch.
Answer: mixed

Message: Sure, thanks a lot. Now my order is lost.
Answer: negative

المثالان مبتكران، وهذا متعمد. لا تضع أبداً رسالة من cases.csv في الموجّه كمثال: عندها سيُقيَّم النموذج على إجابة سلّمتها له، وستكون الدرجة منتفخة. هذه هي تقنية few-shot؛ مجموعة الاختبار هي ما يخبرك هل أثمرت. إذا كان موجّه v1 لديك لا يزال غامضاً، فإن كيفية كتابة موجّه جيد هي نقطة البداية قبل أن تقيس.

الصق v2 في PROMPT (تعمل علامات الاقتباس الثلاثية لعدة أسطر) وشغّل السكربت مرة أخرى. لنفترض أنه يطبع Accuracy: 17/20 = 85%. ثلاث حالات إضافية صحيحة، لذا يبدو v2 أفضل. إلى أي مدى تثق بذلك؟ كل حالة تساوي 5 نقاط في مجموعة من 20 حالة، لذا 70% → 85% هي ثلاث رسائل. هذا تلميح جيد، وليس دليلاً. إذا انخفضت الدرجة، فقد تعلمت شيئاً قيّماً بالقدر نفسه ونجّيت نفسك من شحن موجّه أسوأ.

المجموعة نفسها، نموذج آخر: هل يحافظ على الدرجة؟#

يجيب الملف نفسه على سؤال ثانٍ: هل تدفع مقابل نموذج أكبر مما تحتاجه هذه المهمة؟ غيّر سطراً واحداً وأعد التشغيل:

python
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'

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

كم يكلف كل هذا؟ افترض حوالي 150 رمزاً مدخلاً لكل حالة (التعليمة والرسالة) وحوالي 5 رموز مخرجة لتصنيف من كلمة واحدة. أي 3,000 رمز مدخل و100 رمز مخرج لكل تشغيل من 20 حالة، ما يعادل $0.000064 على GLM-5.3-Flash. عشر إعادات تشغيل للمجموعة هي 200 طلب؛ يوضح الجدول أدناه هذا الحمل لكل نموذج، مع OpenRouter بجانبه. عند هذا الحمل، مع احتساب المدخل والمخرج معاً، يكلف كل نموذج في الجدول أقل من سعر OpenRouter المرجعي.

النموذج لكل طلب 200 طلبات OpenRouter، 200 طلبات
GLM-5.3-Flash $0.0000032 $0.00064 $0.0011
DeepSeek-V4-Flash $0.0000028 $0.00055 $0.0022
MiniMax-M2.7 $0.0000083 $0.0017 $0.0198

150 رمز إدخال و5 رمز إخراج لكل طلب. الأسعار لكل مليون رمز حالية وتتغير مع تعريفاتنا؛ يعرض عمود OpenRouter أسعارًا مرجعية لنفس حجم العمل.

يُستخدم اثنان منهما في هذه المقالة: GLM-5.3-Flash لديه سياق 390K وحتى 8,192 رمز مخرج لكل إجابة؛ DeepSeek-V4-Flash لديه سياق 380K وحتى 32,768 رمز مخرج، بسعر واحد في أي ساعة من اليوم، ونفس الرصيد كأي نموذج آخر. الأسعار الحالية على صفحة الأسعار، والقائمة الكاملة في النماذج.

أين تتوقف المطابقة التامة عن العمل#

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

عادة أخرى: عندما يتوقف v2 عن التحسن، لا تستمر في الصقل ضد الرسائل العشرين نفسها. أضف 5–10 رسائل جديدة، ويفضل أن تكون إخفاقات حقيقية من الإنتاج، وأعد التشغيل.

فحص سريع

يسجل v2 17/20 وسجل v1 15/20 على الحالات نفسها. ما هو الاستنتاج الأكثر أماناً؟

إظهار الإجابة

الإجابة: يبدو v2 أفضل، لكن حالتين من 20 فجوة صغيرة: أضف حالات جديدة وأعد التشغيل

كل حالة 5 نقاط، لذا فجوة حالتين إشارة إلى النظر عن كثب، وليست حكماً. الحالات الجديدة التي لم يرها v2 أبداً هي الفحص التالي.