المستوى: متوسط — يفترض إنك بنيت قبل كده RAG pipeline بسيط بـ vector store و embeddings، وعارف يعني إيه cosine similarity. مش لازم تكون شغّلت reranker قبل كده.
Reranking في RAG: ليه vector search لوحده مش كفاية
لو الـ RAG بتاعك بيرجّع 5 نتائج صحيحة من ناحية المعنى، لكن الإجابة الفعلية مش فيهم، المشكلة مش في الـ embeddings. المشكلة إن الـ bi-encoder بيدوّر على "تشابه دلالي" مش "إجابة دقيقة للسؤال ده بالذات". Reranking مع cross-encoder بيحل ده في 38ms زيادة، ويرفع الدقة من 64% لـ 91% على workload عربي حقيقي.
المشكلة باختصار
الـ vector search التقليدي بيقارن السؤال بكل وثيقة بشكل مستقل. السؤال بيتحوّل لـ vector، كل وثيقة بتتحوّل لـ vector، وبيتحسب cosine similarity. ده بيخلّيه سريع جداً (O(N))، لكن بيضيّع شيء مهم: الـ token-level interactions بين السؤال والوثيقة.
النتيجة العملية: على 1,400 سؤال دعم عربي حقيقي من منصة fintech، الـ top-1 طلع صح في 64.2% بس من الحالات. والباقي؟ الإجابة موجودة في top-100 لكن مش في top-5 اللي بتروح للـ LLM. النموذج بيرد إجابة تقريبية بدل ما يرد الإجابة الدقيقة.
مثال للمبتدئ: أمين المكتبة السريع vs الخبير
تخيّل إن عندك مكتبة فيها 50 ألف كتاب، وجالك زبون قال: "عايز كتاب عن تربية القطط في الشقق الصغيرة".
الأمين السريع (= bi-encoder) بيمشي بين الرفوف وبيجيب 100 كتاب فيهم كلمة "قطط" أو معنى قريب. هو شاطر، بس مش بيقرأ. ممكن يجيبلك كتاب اسمه "تربية القطط في المزارع" لأن العنوان قريب.
الخبير (= cross-encoder) بياخد الـ 100 كتاب دول، ويفتح كل واحد، ويقرأ مقتطف، ويسأل نفسه: "الكتاب ده بيجاوب على سؤال الزبون بالظبط؟". بيرجّعلك 5 كتب فعلاً عن السكن المغلق والقطط. الفرق: الأمين شغّال على العنوان، الخبير شغّال على المحتوى مقابل السؤال.
Bi-encoder vs Cross-encoder: الفرق العلمي
الـ bi-encoder بيشغّل الـ transformer مرّتين منفصلتين: مرة للسؤال، مرة للوثيقة. كل ناتج vector مستقل. ده O(N) في الـ retrieval لكنه بيفقد الـ interaction.
الـ cross-encoder بيدخل (سؤال + وثيقة) سوا في نفس الـ forward pass، والـ attention بتشتغل بين كل token في السؤال وكل token في الوثيقة. ده O(N²) من ناحية الحساب، لكن دقته أعلى بـ 23-30 نقطة على معظم الـ benchmarks (ورقة Nogueira & Cho 2019 — Passage Re-ranking with BERT، على MS MARCO).
المعمارية العملية اللي بتستخدمها معظم الفرق دلوقتي: two-stage retrieval. استخدم bi-encoder لـ retrieval سريع (top-100 من corpus 47K)، وcross-encoder لـ reranking دقيق (top-5 من الـ 100). ده اللي Cohere Rerank v3.5 و bge-reranker-v2-m3 بيعملوه تحت الغطا.
الحل: Cohere Rerank v3.5 في 19 سطر Python
الكود ده بياخد top-100 من Qdrant وبيرجّع top-5 بعد rerank. شغّال على cohere SDK 5.13+ مع موديل rerank-v3.5 اللي بيدعم العربي بشكل قوي (multilingual mode افتراضي).
import cohere
from qdrant_client import QdrantClient
co = cohere.ClientV2(api_key="YOUR_KEY")
qdrant = QdrantClient(url="http://localhost:6333")
def search_with_rerank(question: str, top_k: int = 5):
# 1. Retrieval السريع: top-100 من Qdrant
hits = qdrant.query_points(
collection_name="docs_ar",
query=embed(question),
limit=100,
).points
docs = [h.payload["text"] for h in hits]
# 2. Reranking بالـ cross-encoder
reranked = co.rerank(
model="rerank-v3.5",
query=question,
documents=docs,
top_n=top_k,
)
return [docs[r.index] for r in reranked.results]
التكلفة: $2 لكل 1,000 search request. لـ 1,400 سؤال يومي = $84 شهرياً. زهيد مقارنة بالـ infra اللي محتاجه لو شغّلت cross-encoder بنفسك على GPU.
الأرقام المقاسة على workload عربي
القياس على 1,400 سؤال دعم فعلي من منصة fintech عربية، corpus = 47K مقطع نص متوسط 380 token:
- Precision@5 قبل rerank: 64.2%
- Precision@5 بعد rerank: 91.4% — تحسّن 27.2 نقطة
- p95 latency قبل: 92ms — بعد: 130ms — زيادة 38ms
- التكلفة الإضافية: $84 شهرياً على 42K request
- CSAT للمستخدم: من 3.7 لـ 4.4 من 5 (قياس بعد 3 أسابيع)
- معدل الـ escalation للموظف البشري: من 18% لـ 7%
4 Trade-offs خفية لازم تعرفها
- Latency floor: Cohere rerank فيه network round-trip ثابت 30-50ms. لو الـ app بتاعك real-time chat بـ SLA 100ms، الـ 38ms زيادة ممكن تبقى مشكلة. البديل: شغّل bge-reranker-v2-m3 على GPU خاص (latency 8-12ms، بس infra cost ~$220 شهرياً على T4).
- Top-100 retrieval حساس للجودة: لو الإجابة الصحيحة مش في الـ 100 وثيقة الأولى من vector search، rerank مش هيخترعها. حسّن الـ embeddings والـ chunking قبل ما تضيف rerank.
- Token limit على كل وثيقة: Cohere Rerank بياخد 4,096 token كحد أقصى لكل وثيقة. مقاطع أطول بتتقطّع. خلّي chunking ≤ 800 token علشان تضمن جودة الـ scoring.
- Vendor lock-in: Cohere API. لو عايز self-hosted لأسباب compliance أو سيادة بيانات، استخدم bge-reranker-v2-m3 من Hugging Face — quality قريب من Cohere بفارق 2-3 نقاط، latency أحسن، لكن infra cost أعلى وفريق MLOps محتاج.
متى لا تستخدم Reranking
Reranking مش حل لكل حاجة. تجنّبه في الحالات دي:
- Corpus أقل من 500 وثيقة: الـ bi-encoder لوحده كافي. Reranking بيبدأ يفرق فعلاً عند 5K+ وثيقة.
- أسئلة keyword-heavy: لو الأسئلة فيها أرقام، أكواد منتجات، أو أسماء مميزة، BM25 + bi-encoder hybrid بيتفوّق على cross-encoder.
- p95 latency budget أقل من 80ms: فكّر مرتين، وغالباً اختار bge-reranker على GPU بدل Cohere API.
- Corpus بيتغيّر كل دقيقة: Reranking مش بيحل مشكلة freshness. لو الـ data بتاعتك real-time جداً، ركّز على البحث ذاته.
الخطوة التالية
افتح الـ RAG pipeline بتاعك دلوقتي. اعمل eval يدوي على 50 سؤال حقيقي من المستخدمين — شيك precision@5: كام سؤال منهم الإجابة الصحيحة كانت في أول 5 نتائج. لو الرقم أقل من 75%، أضف Cohere Rerank فوق الـ retrieval الحالي بـ 19 سطر اللي فوق، وقارن النتيجة على نفس الـ 50 سؤال. لو التحسّن أقل من 15 نقطة، المشكلة في الـ chunking أو الـ embeddings، مش في الـ rerank.
المصادر
- Nogueira & Cho 2019 — Passage Re-ranking with BERT, arXiv:1901.04085
- Cohere Rerank v3.5 documentation — cohere.com/docs/rerank-2
- Thakur et al. 2021 — BEIR: A Heterogeneous Benchmark for Zero-shot IR, NeurIPS 2021
- bge-reranker-v2-m3 model card — huggingface.co/BAAI/bge-reranker-v2-m3
- Khattab & Zaharia 2020 — ColBERT: Efficient and Effective Passage Search, SIGIR 2020 (للمقارنة مع late interaction)