الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
الذكاء الاصطناعي

إعادة الترتيب (Reranking): ليه أفضل 5 نتائج بحثك مش الأفضل فعلاً

متوسط8 أغسطس 20264 دقائق قراءة
إعادة الترتيب (Reranking): ليه أفضل 5 نتائج بحثك مش الأفضل فعلاً

المستوى المطلوب: متوسط — يفترض إنك تعرف أساسيات البحث الدلالي (embeddings) وجرّبت RAG أو بحث متجهات مرة على الأقل.

إعادة الترتيب (Reranking): ليه أفضل 5 نتائج بحثك مش الأفضل فعلاً

لو بتعرض أفضل 5 نتائج من بحث دلالي أو RAG وهي مش دقيقة، المشكلة غالباً مش في الـ embeddings. طبقة إعادة ترتيب (Reranking) فوق نتائجك بترفع جودة الترتيب بشكل ملموس مقابل زمن بسيط لكل استعلام. ركز في السطور الجاية على الفرق بالظبط بين "استرجاع سريع" و"ترتيب دقيق".

المشكلة باختصار

بحث المتجهات (bi-encoder) بيحوّل السؤال والمستند كل واحد لوحده لمتجه، وبعدين بيقارن بالتقارب (cosine similarity). ده سريع جداً لأنه بيحسب متجهات المستندات مقدماً ويخزّنها. لكنه بيضغط كل مستند في متجه واحد قبل ما يشوف سؤالك أصلاً، فبيضيّع تفاصيل التطابق الدقيقة. النتيجة اللي بتحصل فعلاً: المستند الأنسب لسؤالك بيطلع أحياناً في المركز السابع مش الأول.

مثال قبل الشرح العلمي

تخيّل لجنة توظيف قدّامها 1000 سيرة ذاتية. مستحيل تعمل مقابلة لكل واحد. فبتفلتر بسرعة بكلمات مفتاحية وتطلّع 50 مرشح مبدئي. الفلترة السريعة دي هي الـ bi-encoder: رخيصة وواسعة، بس تقريبية. القرار النهائي محتاج مقابلة تقارن كل مرشح بالوظيفة وجهاً لوجه. المقابلة دي هي الـ cross-encoder: غالية، بس بتشوف التفاعل الحقيقي بين المرشح والوظيفة. الفكرة إنك تستخدم الفلترة الرخيصة للتصفية الأولية الواسعة، والمقابلة الغالية للـ 50 اللي فضلوا بس.

الشرح العلمي: bi-encoder مقابل cross-encoder

الـ bi-encoder بينتج متجهين منفصلين: واحد للسؤال وواحد للمستند، والدرجة هي التقارب بينهم. عشان المتجهات مستقلة، تقدر تحسب متجهات ملايين المستندات مسبقاً وتبحث فيها في مللي ثانية. الـ cross-encoder مختلف: بيدخّل السؤال والمستند مع بعض في نفس المحوّل (Transformer) وبيطلّع درجة relevance واحدة. لأنه بيشوف النصين مع بعض، بيلتقط التفاعل الدقيق اللي الـ bi-encoder بيضيّعه. الثمن: لازم forward pass كامل لكل زوج (سؤال، مستند)، يعني ميصلحش تبحث بيه في الملايين — بس مثالي إنك تعيد ترتيب أفضل 50 أو 100 مرشح فقط.

الحل: خط أنابيب من مرحلتين

بدل ما تختار بين السرعة والدقة، اجمعهم في نمط "retrieve then rerank": استرجع أفضل 100 مرشح بالـ bi-encoder السريع، وبعدين أعد ترتيبهم بالـ cross-encoder وخُد أفضل 5.

  1. استرجاع واسع وسريع: الـ bi-encoder يجيب top-100.
  2. ترتيب دقيق: الـ cross-encoder يسجّل كل زوج (سؤال، مستند).
  3. خُد أفضل 5 بعد الترتيب التنازلي.
Python
from sentence_transformers import SentenceTransformer, CrossEncoder

# 1) استرجاع سريع: bi-encoder يجيب أفضل 100 مرشح
retriever = SentenceTransformer("all-MiniLM-L6-v2")
query = "كيف أوقف تسريب الذاكرة في Node.js؟"
q_emb = retriever.encode(query)
candidates = vector_search(q_emb, top_k=100)   # ترجع نصوص المستندات

# 2) إعادة ترتيب دقيقة: cross-encoder يسجّل كل زوج (سؤال، مستند)
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
scores = reranker.predict([(query, doc) for doc in candidates])

# 3) رتّب تنازلياً وخُد أفضل 5
ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
top5 = [doc for doc, _ in ranked[:5]]
كود Python لبناء خط أنابيب استرجاع ثم إعادة ترتيب بمكتبة sentence-transformers

الأرقام والافتراضات

النموذج cross-encoder/ms-marco-MiniLM-L-6-v2 يحقق NDCG@10 حوالي 74.3 على مجموعة TREC-DL 2019 ويعالج نحو 1800 زوج (سؤال، مستند) في الثانية على كارت V100، حسب توثيق Sentence-Transformers الرسمي. يعني إعادة ترتيب 100 مرشح بتاخد قرب 55 مللي ثانية على GPU حديث. الافتراض إن مرحلة الاسترجاع بتاعتك كويسة: لو المستند الصح مش موجود أصلاً ضمن top-100، الـ reranker مش هيخترعه — هو بيرتّب اللي جالُه بس.

الـ trade-offs

بتكسب دقة ترتيب أعلى بوضوح، بتخسر زمن لكل استعلام يتناسب طردياً مع عدد المستندات اللي بتعيد ترتيبها. الـ trade-off هنا في اختيار حجم K: كل ما تعيد ترتيب مستندات أكتر (top-200 بدل top-50) بتزود احتمال إنك تلقط المستند الصح، بس بتدفع زمن أكتر. وعلى CPU من غير GPU، الزمن ممكن يقفز لأرقام يحسّها المستخدم فعلاً.

متى لا تستخدم هذه الطريقة

لو الكوربوس صغير جداً (مئات المستندات) والـ bi-encoder المضبوط (fine-tuned) كافي، إعادة الترتيب غالباً مبالغة هندسية. ولو زمن الاستجابة عندك حرج (أقل من 50 مللي ثانية) وترافيكك عالي بدون GPU، تكلفة الـ cross-encoder ممكن تأذيك. وكمان لو الاستعلامات بتتكرر كتير، فكّر تخزّن نتائج الترتيب (cache) بدل ما تعيد حسابها كل مرة.

الخطوة التالية

خُد أول 20 استعلام حقيقي من اللوجز عندك، شغّل عليهم الاسترجاع الحالي (top-50)، وبعدين ضيف cross-encoder فوقهم. قيس NDCG@10 قبل وبعد على نفس المجموعة بالظبط. لو الرقم اتحسّن بشكل واضح، وسّع للإنتاج؛ لو مااتحركش، مشكلتك في مرحلة الاسترجاع مش في الترتيب.

المصادر

  • Reimers & Gurevych, "Sentence-BERT" (EMNLP 2019): https://arxiv.org/abs/1908.10084
  • Nogueira & Cho, "Passage Re-ranking with BERT" (2019): https://arxiv.org/abs/1901.04085
  • Sentence-Transformers — Retrieve & Re-Rank: https://www.sbert.net/examples/applications/retrieve_rerank/README.html
  • Pretrained Cross-Encoders (MS MARCO) والأرقام المذكورة: https://www.sbert.net/docs/pretrained-models/ce-msmarco.html
  • BEIR Benchmark (Thakur et al. 2021): https://arxiv.org/abs/2104.08663
  • Cohere Rerank (مثال على reranker مُدار): https://docs.cohere.com/docs/reranking

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة