تقييم مسارات DSPy
المقاييس، ومجموعات التطوير، والدالة evaluate() للتقييم الآلي
تقييم مسارات DSPy درس مجاني في AI Prompt Engineering على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Prompt Engineering، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
لماذا يهم التقييم في DSPy
لا يكون تحسين DSPy أفضل من جودة تقييمكم. فالمقياس الضعيف ينتج برنامجًا مُجمّعًا يحقق نتيجة جيدة وفق ذلك المقياس، لكنه يفشل في بيئة الإنتاج. يتيح إطار التقييم السليم مقارنة البرامج غير المُحسّنة بالبرامج المُحسّنة، واكتشاف حالات التراجع عند تحديث خط المعالجة لديكم.
الفئة dspy.Evaluate
تشغّل dspy.Evaluate برنامجكم على مجموعة بيانات، وتطبّق مقياسًا، وتعرض الدرجات الإجمالية. كما تدعم التنفيذ المتوازي عبر num_threads لتقييم مجموعات البيانات الكبيرة بسرعة.
import dspy
# Build a devset of labeled examples
devset = [
dspy.Example(question='What is 7 * 8?', answer='56').with_inputs('question'),
dspy.Example(question='Name the largest planet.', answer='Jupiter').with_inputs('question'),
# ... more examples
]
# Create evaluator
evaluate = dspy.Evaluate(
devset=devset,
metric=exact_match_metric, # Your metric function
num_threads=4, # Parallel evaluation
display_progress=True, # Show progress bar
display_table=True, # Show per-example results
)
# Run
score = evaluate(my_program)
print(f'Overall score: {score:.1%}')كتابة دوال المقاييس
تتبع دوال المقاييس التوقيع (example, prediction, trace=None) -> float. وهي تقارن تنبؤ البرنامج بالحقيقة الأساسية الموجودة في المثال.
تكون قيمة المعامل trace غير مساوية لـ None أثناء التحسين، وليس أثناء التقييم — ويمكنكم استخدامه لتطبيق منطق مختلف أثناء التجميع والتقييم.
import dspy
def exact_match_metric(example, prediction, trace=None):
return float(
example.answer.strip().lower() == prediction.answer.strip().lower()
)
def contains_metric(example, prediction, trace=None):
"""Check if expected answer appears anywhere in prediction."""
return float(example.answer.lower() in prediction.answer.lower())
def length_penalized_metric(example, prediction, trace=None):
"""Reward correct answers, penalize overly long ones."""
correct = float(example.answer.lower() in prediction.answer.lower())
length_ok = float(len(prediction.answer.split()) <= 20)
return correct * (0.8 + 0.2 * length_ok)
# Use any of these as the metric parameter
evaluate = dspy.Evaluate(devset=devset, metric=contains_metric)أنماط عتبة النجاح والفشل
بالنسبة إلى المقاييس الثنائية، يمكنكم تحديد عتبة: يُعدّ التنبؤ «ناجحًا» إذا استوفى حدًا أدنى من الجودة. ويفيد ذلك في تصفية العروض التوضيحية ذات اللقطات القليلة أثناء التحسين بالتهيئة.
import dspy
def quality_metric(example, prediction, trace=None):
"""
Multi-factor metric with pass/fail threshold.
Returns float 0.0 to 1.0.
During compilation (trace is not None), DSPy uses this to decide
which traces to bootstrap as demos.
"""
score = 0.0
# Factor 1: Factual correctness (0.6 weight)
if example.answer.lower() in prediction.answer.lower():
score += 0.6
# Factor 2: Conciseness (0.4 weight)
word_count = len(prediction.answer.split())
if word_count <= 15:
score += 0.4
elif word_count <= 30:
score += 0.2
# During optimization: only use examples scoring >= 0.6
if trace is not None:
return score >= 0.6
return scoreتقسيم البيانات: التدريب والتطوير والاختبار
اتبعوا ممارسات تقسيم بيانات تعلّم الآلة القياسية في DSPy:
- مجموعة التدريب: يستخدمها المُحسِّن لتهيئة العروض التوضيحية (من 20 إلى 200 مثال)
- مجموعة التطوير: يستخدمها المُحسِّن للتحقق أثناء البحث
- مجموعة الاختبار: تُحجز بالكامل — ولا تُستخدم إلا للتقييم النهائي
import random
# All labeled examples
all_examples = load_examples() # Returns list of dspy.Example
random.shuffle(all_examples)
total = len(all_examples)
train_end = int(total * 0.6)
dev_end = int(total * 0.8)
trainset = all_examples[:train_end] # 60% for optimization
devset = all_examples[train_end:dev_end] # 20% for validation
testset = all_examples[dev_end:] # 20% held out
print(f'Train: {len(trainset)}, Dev: {len(devset)}, Test: {len(testset)}')مقارنة البرامج المُحسّنة وغير المُحسّنة
اختبروا دائمًا أداء برنامجكم المُجمّع مقارنةً بالبرنامج الأساسي (غير المُجمّع) باستخدام مجموعة الاختبار نفسها. فهذا يثبت أن التحسين حقق فائدة فعلية، ويحدد مقدار التحسن.
import dspy
evaluate = dspy.Evaluate(
devset=testset,
metric=exact_match_metric,
num_threads=4,
display_progress=True,
)
# Baseline: unoptimized program
baseline_score = evaluate(unoptimized_program)
print(f'Baseline (no optimization): {baseline_score:.1%}')
# BootstrapFewShot compiled
bs_score = evaluate(bootstrap_compiled_program)
print(f'BootstrapFewShot compiled: {bs_score:.1%}')
# MIPRO compiled
mipro_score = evaluate(mipro_compiled_program)
print(f'MIPRO compiled: {mipro_score:.1%}')
# Pick the winner
print(f'Best improvement: +{max(bs_score, mipro_score) - baseline_score:.1%}')التنفيذ المتوازي باستخدام num_threads
قد يستغرق تقييم مجموعات البيانات الكبيرة ساعات عند تنفيذه تسلسليًا. يشغّل num_threads في dspy.Evaluate التنبؤات بالتوازي، مما يقلل الوقت الفعلي المستغرق بما يتناسب مع عدد الخيوط.
وازِنوا قيمة num_threads مع حدود معدل واجهة API لديكم — إذ يؤدي استخدام عدد كبير جدًا من الخيوط إلى أخطاء تجاوز حد المعدل.
import dspy
import time
devset = [...] # 200 examples
# Sequential evaluation
start = time.time()
evaluate_seq = dspy.Evaluate(devset=devset, metric=metric, num_threads=1)
score_seq = evaluate_seq(program)
print(f'Sequential: {time.time()-start:.0f}s')
# Parallel evaluation (4 threads)
start = time.time()
evaluate_par = dspy.Evaluate(devset=devset, metric=metric, num_threads=4)
score_par = evaluate_par(program)
print(f'Parallel (4 threads): {time.time()-start:.0f}s')
# Typically ~4x faster — same score, less wait timeتفسير مخرجات التقييم
عند ضبط display_table=True، يعرض DSPy جدولًا مفصلًا يتضمن كل مثال، والتنبؤ، وما إذا كان قد اجتاز المقياس. ويفيد ذلك كثيرًا في تشخيص أنماط الإخفاق.
ابحثوا عن: إخفاقات منهجية في نوع معين من الأسئلة، أو حالات خاصة في المقياس، أو أمثلة لا تغطيها مجموعة التدريب لديكم.
import dspy
evaluate = dspy.Evaluate(
devset=devset,
metric=exact_match_metric,
num_threads=2,
display_progress=True,
display_table=10, # Show first 10 rows of results table
return_outputs=True, # Return (score, outputs) tuple
)
score, outputs = evaluate(program, return_all_scores=True)
# Find failing examples
failures = [
(ex, pred, s)
for ex, pred, s in outputs
if s == 0.0
]
print(f'Failures: {len(failures)}/{len(devset)}')
for ex, pred, _ in failures[:3]:
print(f'Q: {ex.question}')
print(f'Expected: {ex.answer}')
print(f'Got: {pred.answer}')استخدام المقاييس التي تقيّمها نماذج LLM
بالنسبة إلى المخرجات المفتوحة التي لا ينجح معها التطابق التام، استخدموا نموذج LLM لتقييم الجودة. ويجعل DSPy ذلك سهلًا — إذ يمكن لدالة المقياس نفسها استدعاء متنبئ من DSPy.
import dspy
class GradeAnswer(dspy.Signature):
"""Grade whether the predicted answer is correct given the reference."""
question: str = dspy.InputField()
reference_answer: str = dspy.InputField()
predicted_answer: str = dspy.InputField()
is_correct: bool = dspy.OutputField(
desc='True if the predicted answer is semantically correct'
)
grader = dspy.Predict(GradeAnswer)
def llm_graded_metric(example, prediction, trace=None):
result = grader(
question=example.question,
reference_answer=example.answer,
predicted_answer=prediction.answer,
)
return float(result.is_correct)
# Use this metric when answers can vary in phrasing
evaluate = dspy.Evaluate(devset=devset, metric=llm_graded_metric)اختبار التراجع باستخدام التقييم
تعاملوا مع مجموعة تقييم DSPy باعتبارها مجموعة اختبارات. ففي كل مرة تحدّثون فيها التوقيع، أو بنية الوحدات، أو بيانات التدريب، أعيدوا تشغيل التقييم وقارنوا الدرجات لاكتشاف حالات التراجع.
import json
import dspy
def run_and_save_evaluation(program, program_name, testset, metric):
evaluate = dspy.Evaluate(
devset=testset,
metric=metric,
num_threads=4,
)
score = evaluate(program)
# Save score to history file
history_file = 'eval_history.json'
try:
with open(history_file) as f:
history = json.load(f)
except FileNotFoundError:
history = []
history.append({'program': program_name, 'score': score})
with open(history_file, 'w') as f:
json.dump(history, f, indent=2)
print(f'{program_name}: {score:.1%}')
return scoreأفضل ممارسات التقييم
مبادئ التقييم الأساسية لخطوط معالجة DSPy:
- أبقوا مجموعة الاختبار معزولة تمامًا — ولا تحسّنوا البرنامج باستخدامها مطلقًا
- استخدموا ما لا يقل عن 50 إلى 100 مثال اختبار للحصول على درجات موثوقة
- طابقوا المقياس مع هدفكم الفعلي في بيئة الإنتاج
- قارنوا بين مُحسِّنات متعددة — فالنتائج تختلف باختلاف المهمة
- تتبّعوا الدرجات بمرور الوقت لاكتشاف حالات التراجع
- افحصوا حالات الإخفاق يدويًا لتحسين بيانات التدريب
اختبار معرفي: معامل trace في دالة المقياس
في دالة مقياس في DSPy، إلى ماذا يشير معامل trace غير المساوي لـ None؟
مراجعة: تقييم خطوط معالجة DSPy
تشغّل dspy.Evaluate برنامجكم على مجموعة تطوير موسومة، وتطبّق دالة مقياس، وتعرض الدرجات الإجمالية. وتتبع دوال المقاييس النمط (example, prediction, trace=None) -> float. استخدموا num_threads للتقييم المتوازي، وdisplay_table=True لتشخيص حالات الإخفاق. وقارنوا دائمًا البرامج المُحسّنة بالبرامج غير المُحسّنة باستخدام مجموعة اختبار معزولة. وبالنسبة إلى المخرجات المفتوحة، تتفوق المقاييس التي تقيّمها نماذج LLM على مطابقة السلاسل النصية تطابقًا تامًا.
الأسئلة الشائعة
هل درس «تقييم مسارات DSPy» مجاني؟
نعم — نص درس «تقييم مسارات DSPy» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Prompt Engineering، انتقل إلى CoddyKit PRO. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
ماذا ستتعلم في «تقييم مسارات DSPy»؟
المقاييس، ومجموعات التطوير، والدالة evaluate() للتقييم الآلي تتمرن على AI Prompt Engineering مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Prompt Engineering؟
لا تُشترط خبرة سابقة. AI Prompt Engineering على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «تقييم مسارات DSPy»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Prompt Engineering هذا؟
نعم. كل درس في AI Prompt Engineering يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مقدمة إلى إطار DSPy
- تعريف التوقيعات والوحدات
- تجميع المطالبات وتحسينها
- تقييم مسارات DSPy