مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG
ابنوا مجموعة بيانات مرجعية من الاستعلامات والمستندات ذات الصلة، ثم احسبوا معدل الإصابة ومتوسط الرتبة التبادلية وNDCG لقياس مدى عثور أداة الاسترجاع على الأجزاء الصحيحة.
مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
لماذا تختلف مقاييس الاسترجاع؟
يخبركم معدل الإصابة بما إذا كان جزء ذو صلة قد ظهر في أي موضع ضمن نتائج K الأولى، لكنه لا يخبركم بموضعه في الترتيب. فالنظام الذي يضع دائمًا أفضل جزء في المرتبة 5 أسوأ من نظام يضعه باستمرار في المرتبة 1، حتى لو كان لهما معدل الإصابة نفسه. تلتقط المقاييس الأكثر دقة، مثل MRR وNDCG، جودة الترتيب، وتكافئ الأنظمة التي تضع الأجزاء الأكثر صلة في المقدمة، حيث يُرجح أن يستخدمها كل من LLM والمستخدمين.
معدل الإصابة @K: المراجعة والتنفيذ
معدل الإصابة@K هو أبسط المقاييس: ما نسبة الاستعلامات التي يظهر فيها جزء واحد ذو صلة على الأقل ضمن نتائج K الأولى؟ إنه يعطي إشارة ثنائية لكل استعلام، ويسهل تفسيره. احسبوه من خلال التحقق من تقاطع المجموعة بين المعرّفات المسترجعة والمعرّفات المعروفة ذات الصلة. استخدموا K=5 كقيمة افتراضية، لأن معظم أنظمة RAG تسترجع 5 أجزاء. قارنوا بين hit rate@1 و@3 و@5 لفهم كيفية تغير الحساسية مع توسيع نطاق الاسترجاع.
def hit_rate_at_k(golden_dataset, retriever, k=5):
hits = 0
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
if any(rid in relevant_ids for rid in retrieved_ids):
hits += 1
return hits / len(golden_dataset)
for k in [1, 3, 5, 10]:
hr = hit_rate_at_k(golden_dataset, retriever, k=k)
print(f'Hit rate@{k}: {hr:.1%}')متوسط الرتبة التبادلي (MRR)
يقيس MRR (Mean Reciprocal Rank) متوسط مقلوب المرتبة التي يظهر فيها أول جزء ذي صلة. فإذا كان الجزء ذو الصلة في المرتبة 1، فإن مقلوب الرتبة يساوي 1/1 = 1.0. وفي المرتبة 2 يساوي 0.5، وفي المرتبة 5 يساوي 0.2. يُحسب MRR كمتوسط عبر جميع الاستعلامات. ويعني ارتفاع MRR أن نظام الاسترجاع يضع الأجزاء ذات الصلة باستمرار بالقرب من المقدمة، وهذا مهم لأن LLM يولي اهتمامًا أكبر للسياق الموجود في بداية prompt.
def mean_reciprocal_rank(golden_dataset, retriever, top_k=10):
reciprocal_ranks = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=top_k)
retrieved_ids = [r['id'] for r in retrieved]
relevant_ids = set(item['relevant_chunk_ids'])
rr = 0.0
for rank, rid in enumerate(retrieved_ids, start=1):
if rid in relevant_ids:
rr = 1.0 / rank
break # only the first relevant result counts
reciprocal_ranks.append(rr)
mrr = sum(reciprocal_ranks) / len(reciprocal_ranks)
print(f'MRR@{top_k}: {mrr:.3f}')
return mrrتفسير درجات MRR
تحمل درجات MRR تفسيرات واضحة: تعني MRR = 1.0 أن أول جزء ذي صلة يكون دائمًا في المرتبة 1 (أداء مثالي). وتعني MRR = 0.5 أنه يكون عادةً في المرتبة 2. وتعني MRR = 0.25 أنه يكون عادةً في المرتبة 4؛ أي إن المعلومات ذات الصلة تظهر في موضع منخفض بما يكفي لاحتمال اقتطاعها من السياق. في أنظمة RAG، استهدفوا MRR > 0.7 لضمان وجود الجزء الأكثر صلة بكم باستمرار ضمن الموضعين الأولين.
# MRR interpretation table
mrr_interpretations = {
1.0: 'Perfect — relevant chunk always at rank 1',
0.5: 'Good — typically at rank 2',
0.33: 'Acceptable — typically at rank 3',
0.25: 'Weak — typically at rank 4',
0.1: 'Poor — relevant chunk rarely near the top'
}
for score, description in mrr_interpretations.items():
print(f'MRR {score:.2f}: {description}')الدقة @K
تقيس Precision@K نسبة الأجزاء K المسترجعة التي تكون ذات صلة فعلًا. وعلى خلاف معدل الإصابة (الذي يكون ثنائيًا)، تقيس precision@K نسبة الإشارة إلى الضوضاء في نتائج الاسترجاع. تعني الدقة المنخفضة أن LLM يتلقى سياقًا غير ذي صلة إلى جانب الأجزاء ذات الصلة، مما يزيد خطر الالتباس أو حقن prompt. وفي أنظمة RAG، تُعد precision@5 > 0.6 قيمة مستهدفة جيدة.
def precision_at_k(golden_dataset, retriever, k=5):
precisions = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
relevant_retrieved = sum(
1 for rid in retrieved_ids if rid in relevant_ids
)
precision = relevant_retrieved / k
precisions.append(precision)
mean_precision = sum(precisions) / len(precisions)
print(f'Precision@{k}: {mean_precision:.3f}')
return mean_precisionالكسب التراكمي المخفَّض (DCG)
DCG هو مقياس لتقييم القوائم المرتبة، ويكافئ وضع الأجزاء الأكثر صلة في مواضع أعلى. فهو يجمع درجات صلة الأجزاء المسترجعة، لكنه يخفّض وزنها لوغاريتميًا بحسب موضعها: تحصل المرتبة 1 على كامل النقاط، وتحصل المرتبة 2 على تخفيض log(2)، وهكذا. تؤدي الأجزاء الأعلى صلة في المقدمة إلى DCG أعلى. أما النسخة المطبَّعة (NDCG)، فتقسم القيمة على DCG المثالي (أفضل ترتيب ممكن) لإنتاج درجة بين 0 و1.
import math
def dcg_at_k(relevances, k):
'''relevances[i] = 1 if chunk at rank i+1 is relevant, else 0'''
dcg = 0.0
for i, rel in enumerate(relevances[:k]):
# rank is i+1, discount is log2(rank + 1)
dcg += rel / math.log2(i + 2)
return dcg
def ndcg_at_k(retrieved_ids, relevant_ids, k):
relevances = [1 if rid in relevant_ids else 0
for rid in retrieved_ids[:k]]
actual_dcg = dcg_at_k(relevances, k)
ideal_dcg = dcg_at_k([1] * min(len(relevant_ids), k), k)
return actual_dcg / ideal_dcg if ideal_dcg > 0 else 0.0حساب NDCG عبر مجموعة البيانات
يُعد NDCG@K المقياس المعياري الذهبي للاسترجاع في أنظمة البحث. فهو يلتقط الصلة وموضع الترتيب في الوقت نفسه. ويعني NDCG@5 البالغ 0.85 أن نظام الاسترجاع يحقق في المتوسط 85% من أفضل ترتيب نظري ممكن. يتعامل NDCG مع الحالات التي تحتوي فيها الاستعلامات على عدة أجزاء ذات صلة (يحصل كل منها على درجة صلة)، ويعاقب الأنظمة التي تعثر على الأجزاء ذات الصلة لكنها تضعها في مراتب منخفضة جدًا.
def mean_ndcg_at_k(golden_dataset, retriever, k=5):
ndcg_scores = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
score = ndcg_at_k(retrieved_ids, relevant_ids, k)
ndcg_scores.append(score)
mean = sum(ndcg_scores) / len(ndcg_scores)
print(f'NDCG@{k}: {mean:.4f}')
return mean
# Compute all retrieval metrics together
hit_rate = hit_rate_at_k(golden_dataset, retriever, k=5)
mrr = mean_reciprocal_rank(golden_dataset, retriever, top_k=5)
ndcg = mean_ndcg_at_k(golden_dataset, retriever, k=5)استخدام RAGAS للمقاييس الآلية
توفر مكتبة RAGAS إطارًا جاهزًا للاستخدام في الإنتاج لتقييم أنظمة RAG. وهي تطبق مقاييس دقة السياق، واستدعاء السياق، والأمانة، وصلة الإجابة باستخدام أسلوب LLM بوصفه مُقيِّمًا. مرّروا أسئلتكم وإجاباتكم والسياقات المسترجعة وإجابات الحقيقة المرجعية إلى RAGAS، وستحصلون على تقرير تقييم كامل يتضمن درجات كل مقياس. وتُعد هذه أسرع طريقة لإعداد خط أنابيب شامل لتقييم RAG.
from ragas import evaluate
from ragas.metrics import (
context_precision,
context_recall,
faithfulness,
answer_relevancy
)
from datasets import Dataset
eval_data = Dataset.from_list([
{
'question': item['question'],
'answer': item['generated_answer'],
'contexts': item['retrieved_texts'],
'ground_truth': item['expected_answer']
}
for item in golden_dataset_with_answers
])
results = evaluate(
eval_data,
metrics=[context_precision, context_recall, faithfulness, answer_relevancy]
)
print(results)تقسيم المقاييس حسب فئة الاستعلام
تخفي المقاييس الإجمالية المتوسطة أنماطًا مهمة. قسّموا مجموعة البيانات الذهبية إلى فئات، مثل البحث عن حقائق محددة، والمقارنات، والأسئلة الإجرائية من نوع كيفية التنفيذ، والأسئلة خارج النطاق، ثم احسبوا المقاييس لكل فئة على حدة. قد تجدون أن معدل الإصابة يبلغ 95% في البحث عن الحقائق المحددة، لكنه لا يتجاوز 60% في المقارنات متعددة القفزات. تكشف المقاييس على مستوى الفئة أنماط الفشل المحددة التي تخفيها الدرجات الإجمالية.
from collections import defaultdict
def evaluate_by_category(golden_dataset, retriever):
by_category = defaultdict(list)
for item in golden_dataset:
category = item.get('category', 'unknown')
retrieved = retriever.retrieve(item['question'], top_k=5)
retrieved_ids = {r['id'] for r in retrieved}
hit = bool(retrieved_ids & set(item['relevant_chunk_ids']))
by_category[category].append(hit)
print('Hit rate by category:')
for cat, hits in sorted(by_category.items()):
hr = sum(hits) / len(hits)
print(f' {cat}: {hr:.1%} ({sum(hits)}/{len(hits)})')عندما تختلف المقاييس
ترسل المقاييس أحيانًا إشارات متعارضة. فقد تحسّنون NDCG (ترتيب أفضل) بينما يظل معدل الإصابة ثابتًا (العدد نفسه من حالات الإخفاق). يحدث ذلك عندما ينقل التحسين الأجزاء ذات الصلة من المرتبة 6 إلى المرتبة 2، من دون إدخال الاستعلامات التي لم تنجح سابقًا ضمن أعلى 5 نتائج. في هذه الحالات، تحققوا مما إذا كان تحسينكم قد أفاد الاستعلامات الناجحة أصلًا وأهمل الاستعلامات الفاشلة. افحصوا دائمًا أمثلة الإخفاق الفردية إلى جانب المقاييس الإجمالية.
def analyze_failures(golden_dataset, retriever, top_k=5):
failures = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=top_k)
retrieved_ids = {r['id'] for r in retrieved}
relevant_ids = set(item['relevant_chunk_ids'])
if not (retrieved_ids & relevant_ids):
failures.append({
'question': item['question'],
'expected_chunks': list(relevant_ids),
'retrieved_chunks': [r['id'] for r in retrieved],
'top_score': retrieved[0]['score'] if retrieved else None
})
print(f'Failures: {len(failures)}/{len(golden_dataset)}')
return failuresالاستدعاء @K: اكتمال الاسترجاع
يقيس Recall@K نسبة جميع الأجزاء ذات الصلة التي استُرجعت ضمن نتائج K الأولى. فإذا كان لسؤال ما 3 أجزاء ذات صلة في الفهرس، وأعاد نظام الاسترجاع جزأين منها ضمن أول 5 نتائج، فإن recall@5 يساوي 2/3 = 0.67. يكون الاستدعاء المرتفع مهمًا عندما يحتاج LLM إلى عدة أدلة لتركيب إجابة كاملة؛ إذ إن فقدان جزء أساسي واحد قد يجعل الإجابة غير مكتملة. وازنوا بين الدقة والاستدعاء بضبط K: فالقيمة الأكبر لـ K تحسّن الاستدعاء، لكنها تخفّض الدقة.
def recall_at_k(golden_dataset, retriever, k=5):
recalls = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = set(r['id'] for r in retrieved[:k])
relevant_ids = set(item['relevant_chunk_ids'])
if not relevant_ids:
continue # skip items with no annotated relevant chunks
retrieved_relevant = retrieved_ids & relevant_ids
recall = len(retrieved_relevant) / len(relevant_ids)
recalls.append(recall)
mean_recall = sum(recalls) / len(recalls)
print(f'Recall@{k}: {mean_recall:.3f}')
return mean_recallتحقق سريع
اختبروا فهمكم لمفاهيم هندسة الذكاء الاصطناعي التي تناولها هذا الدرس.
مراجعة الدرس
تعلّمتم في هذا الدرس: hit rate@K بوصفه مقياس الحضور الثنائي، وMRR لقياس متوسط موضع أول جزء ذي صلة، وprecision@K لقياس نسبة الإشارة إلى الضوضاء في الاسترجاع، وNDCG@K بوصفه المقياس المعياري الذهبي للقوائم المرتبة، ومكتبة RAGAS لأتمتة تقييم RAG باستخدام دقة السياق واستدعائه والأمانة وصلة الإجابة. سننتقل بعد ذلك إلى التعمق في مقاييس التوليد وقياس الأمانة.
تعلم Python مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 30
- الدروس
- 120
الأسئلة الشائعة
هل درس «مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG» مجاني؟
نعم — نص درس «مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
ماذا ستتعلم في «مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG»؟
ابنوا مجموعة بيانات مرجعية من الاستعلامات والمستندات ذات الصلة، ثم احسبوا معدل الإصابة ومتوسط الرتبة التبادلية وNDCG لقياس مدى عثور أداة الاسترجاع على الأجزاء الصحيحة. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟
لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟
نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- لماذا يهم التقييم في RAG
- مقاييس الاسترجاع: معدل الإصابة وMRR وNDCG
- مقاييس التوليد: الأمانة وملاءمة الإجابة
- بناء أداة تقييم آلية