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)