Reranking في RAG: قلّل التوكنز وارفع دقة الإجابة
هتطلع من المقال ده بطريقة عملية تخلي نظام RAG يبعت للنموذج أجزاء أقل، بس أوثق. بدل ما تزود عدد النتائج وخلاص، هتضيف مرحلة Reranking تقيس الصلة الفعلية بين السؤال وكل جزء.
مستوى القارئ: متوسط
المشكلة باختصار
الطريقة الشائعة في RAG بتعمل retrieval من vector database، تاخد أول 10 أو 20 chunk، وتحطهم كلهم في prompt. الطريقة دي بتفشل لما النتائج الأولى تكون قريبة في المعنى العام، لكن مش هي الأدق للسؤال الحالي.
مثال واقعي: عندك مركز مساعدة فيه 8,000 صفحة. المستخدم يسأل: "هل أقدر أسترد فلوسي بعد 21 يوم لو اشتريت اشتراك سنوي؟" البحث الدلالي ممكن يرجع صفحات عن refund، subscription، billing، وcancelation. كلها قريبة، لكن مش كلها جاوبة السؤال. لو بعت 20 chunk للنموذج، هتزود التكلفة وتفتح باب الاستشهاد الغلط.
يعني إيه Reranking بمثال بسيط
ركز في المثال ده. عندك 20 ورقة على مكتبك، وكلهم طلعوا من بحث سريع. بدل ما تقرأهم كلهم للنموذج، بتجيب شخص متخصص يرتبهم حسب إجابة السؤال بالظبط. مش حسب التشابه العام. حسب: هل القطعة دي فيها معلومة تحسم السؤال؟
ده هو الـ Reranking. مرحلة بعد retrieval وقبل LLM. الـ retriever يجيب قائمة واسعة بسرعة. الـ reranker يعيد ترتيبها باستخدام نموذج مخصص للصلة بين query وdocument، ثم تختار top 3 أو top 5 فقط.
OpenAI Retrieval API يوضح إن البحث الدلالي يعتمد على vector stores ويرجع نتائج بدرجات صلة، ويمكن ضبط ranking options وscore threshold. Cohere Rerank يضيف طبقة أوضح: تدخل query وقائمة documents، ويرجع لك ترتيبًا وrelevance_score لكل نتيجة. الفكرة مش بديل للـ vector search. الفكرة فلتر دقة فوقه.
الطريقة العملية: Retrieve 20 ثم Rerank 5
الافتراض إن عندك نظام RAG بسيط: vector search يرجع 20 chunk، وكل chunk بين 300 و700 token. بدل ما تبعت 12,000 token للنموذج، ابعت أفضل 5 بعد reranking. في اختبار داخلي صغير على 50 سؤال دعم فني، الرقم الافتراضي هنا كان: من 12,000 token إلى 3,400 token تقريبًا، مع انخفاض الاستشهادات الخاطئة من 5 إلى 2 لكل 20 إجابة. الأرقام دي تقديرية للتوضيح، ولازم تقيسها على بياناتك.
مثال Python قابل للتعديل
الكود ده يفترض إنك جبت نتائج أولية من vector database أو OpenAI vector store. المهم هنا إنك تحتفظ بالنص والـ metadata، ثم تمرر النصوص للـ reranker وتختار top_n.
import os
import cohere
from openai import OpenAI
openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
co = cohere.ClientV2(api_key=os.environ["COHERE_API_KEY"])
query = "هل أقدر أسترد فلوسي بعد 21 يوم من اشتراك سنوي؟"
# 1) Retrieve: هات نتائج واسعة من vector store
search_results = openai_client.vector_stores.search(
vector_store_id=os.environ["OPENAI_VECTOR_STORE_ID"],
query=query,
max_num_results=20,
)
chunks = []
for result in search_results.data:
text = "\n".join(part.text for part in result.content if part.type == "text")
chunks.append({
"text": text,
"source": result.filename,
"score": result.score,
})
# 2) Rerank: رتب حسب السؤال الحالي، مش التشابه العام فقط
reranked = co.rerank(
model="rerank-v4.0-pro",
query=query,
documents=[chunk["text"] for chunk in chunks],
top_n=5,
)
selected = []
for item in reranked.results:
original = chunks[item.index]
selected.append({
"text": original["text"],
"source": original["source"],
"rerank_score": item.relevance_score,
})
context = "\n\n".join(
f"[source={doc['source']} score={doc['rerank_score']:.3f}]\n{doc['text']}"
for doc in selected
)
answer = openai_client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{"role": "developer", "content": "أجب من المصادر فقط. لو المعلومة غير موجودة قل لا أعرف."},
{"role": "user", "content": f"السؤال: {query}\n\nالمصادر:\n{context}"},
],
)
print(answer.choices[0].message.content)أفضل طريقة تبدأ بها: retrieve=20 وrerank top_n=5. بعد كده قيس. لو الأسئلة قصيرة والوثائق منظمة، ممكن top_n=3 يكفي. لو الأسئلة مركبة، زودها لـ 8، بس متخليش الرقم قرارًا ثابتًا بلا evals.
الـ trade-off هنا
المكسب واضح: context أقل، تكلفة أقل، وإجابات أقل تشويشًا. كمان النموذج بياخد مصادر أنضف بدل ما يتحرك وسط نصوص متشابهة. الخسارة: طلب API إضافي وزمن latency زيادة. لو rerank بياخد 120ms، وزمن إجابتك الحالي 900ms، الزيادة مقبولة غالبًا. لو عندك autocomplete لحظي تحت 150ms، ممكن تكون الزيادة مزعجة.
فيه تكلفة تانية: لازم تعمل logging. سجل query، أول 20 نتيجة، top 5 بعد rerank، والإجابة النهائية. من غير ده مش هتعرف هل الـ reranker بيحسن فعلاً ولا بس بيغير الترتيب بثقة شكلية.
متى لا تستخدم هذه الطريقة
لا تستخدم Reranking لو قاعدة المعرفة صغيرة جدًا، مثل 30 صفحة داخلية، والـ retrieval بيرجع نتائج دقيقة بالفعل. لا تستخدمه كحل لأول مشكلة في RAG قبل ما تصلح chunking والmetadata والscore threshold. كمان لو عندك أسئلة تعتمد على exact keyword مثل رقم فاتورة أو ID، keyword filter أو hybrid search قد يكون أهم من reranker.
الخلاصة: Reranking مفيد لما عندك نتائج كثيرة متقاربة، وسؤال المستخدم يحتاج تمييزًا دقيقًا بين مستندات شبه بعض. غير كده، هيبقى طبقة تكلفة إضافية.
مصادر اعتمدت عليها
- OpenAI Retrieval API: semantic search, vector stores, ranking options
- OpenAI Embeddings guide: search and similarity use cases
- Cohere Rerank API v2 reference
- Cohere Rerank overview: ترتيب الوثائق حسب الصلة الدلالية
الخطوة التالية
الخطوة التالية: خُد آخر 50 سؤال حقيقي من تطبيقك، شغّلهم مرة بـ top 10 retrieval فقط، ومرة بـ retrieve 20 ثم rerank top 5. قارن عدد التوكنز، صحة المصدر، وهل الإجابة قالت "لا أعرف" لما المصدر ناقص.