الدرس 14 من 23

البحث الهجين وإعادة الترتيب

استراتيجيات إعادة الترتيب

3 دقيقة للقراءة

إعادة الترتيب تأخذ نتائج الاسترجاع الأولية وتعيد ترتيبها باستخدام نماذج أكثر تطوراً لدقة محسنة.

لماذا إعادة الترتيب؟

الاسترجاع الأولي سريع لكن غير دقيق. إعادة الترتيب تضيف الدقة:

الاسترجاع الأولي (سريع، مركز على الاستدعاء)
├── استرجع أعلى 100 مرشح
└── باستخدام تضمينات bi-encoder

إعادة الترتيب (أبطأ، مركز على الدقة)
├── سجل كل مرشح مقابل الاستعلام
└── باستخدام cross-encoder أو LLM
└── أرجع أعلى 10
المرحلة السرعة الجودة الاستخدام
الاسترجاع سريع (~10ms) استدعاء جيد شبكة واسعة
إعادة الترتيب أبطأ (~100ms) دقة عالية اختر الأفضل

إعادة الترتيب بـ Cross-Encoder

Cross-encoders تعالج أزواج الاستعلام-المستند معاً لتسجيل صلة أفضل:

from sentence_transformers import CrossEncoder

class CrossEncoderReranker:
    def __init__(self, model_name: str = "cross-encoder/ms-marco-MiniLM-L-6-v2"):
        self.model = CrossEncoder(model_name)

    def rerank(
        self,
        query: str,
        documents: list[str],
        top_k: int = 5
    ) -> list[tuple[str, float]]:
        """
        أعد ترتيب المستندات حسب الصلة بالاستعلام.

        يرجع:
            قائمة (مستند، درجة) مرتبة حسب الصلة
        """
        # أنشئ أزواج استعلام-مستند
        pairs = [(query, doc) for doc in documents]

        # سجل جميع الأزواج
        scores = self.model.predict(pairs)

        # رتب حسب الدرجة تنازلياً
        doc_scores = list(zip(documents, scores))
        doc_scores.sort(key=lambda x: x[1], reverse=True)

        return doc_scores[:top_k]

# الاستخدام
reranker = CrossEncoderReranker()
results = reranker.rerank(
    query="كيف أتعامل مع مصادقة API؟",
    documents=retrieved_docs,
    top_k=5
)

نماذج cross-encoder الشائعة:

النموذج الحجم السرعة الجودة
ms-marco-MiniLM-L-6-v2 23M سريع جيدة
ms-marco-MiniLM-L-12-v2 33M متوسط أفضل
bge-reranker-large 560M بطيء الأفضل

Cohere Rerank

API إعادة ترتيب تجاري بجودة ممتازة:

import cohere

co = cohere.Client(api_key="your-key")

def cohere_rerank(
    query: str,
    documents: list[str],
    top_k: int = 5
) -> list[dict]:
    """إعادة الترتيب باستخدام API Cohere."""
    response = co.rerank(
        model="rerank-english-v3.0",
        query=query,
        documents=documents,
        top_n=top_k
    )

    return [
        {
            "document": documents[r.index],
            "score": r.relevance_score,
            "index": r.index
        }
        for r in response.results
    ]

# الاستخدام
results = cohere_rerank(
    query="تنفيذ OAuth 2.0",
    documents=retrieved_docs,
    top_k=5
)

التفاعل المتأخر ColBERT

ColBERT يوفر إعادة ترتيب سريعة من خلال التفاعل المتأخر:

from colbert import Searcher
from colbert.infra import ColBERTConfig

class ColBERTReranker:
    def __init__(self, index_path: str):
        config = ColBERTConfig(
            doc_maxlen=512,
            query_maxlen=64
        )
        self.searcher = Searcher(index=index_path, config=config)

    def rerank(self, query: str, doc_ids: list[int], top_k: int = 5):
        """إعادة الترتيب باستخدام التفاعل المتأخر ColBERT."""
        scores = []

        for doc_id in doc_ids:
            score = self.searcher.score(query, doc_id)
            scores.append((doc_id, score))

        scores.sort(key=lambda x: x[1], reverse=True)
        return scores[:top_k]

كيف يعمل ColBERT:

  1. حساب تضمينات الرموز للمستندات مسبقاً
  2. في وقت الاستعلام، حساب تضمينات رموز الاستعلام
  3. التفاعل المتأخر: MaxSim بين رموز الاستعلام والمستند
  4. أسرع بكثير من cross-encoder الكامل

إعادة الترتيب المعتمدة على LLM

استخدم LLMs لإعادة الترتيب بدون تدريب:

from openai import OpenAI

client = OpenAI()

def llm_rerank(
    query: str,
    documents: list[str],
    top_k: int = 5
) -> list[tuple[str, int]]:
    """إعادة الترتيب باستخدام GPT-4."""

    # تنسيق المستندات مع الفهارس
    doc_list = "\n".join([f"[{i}] {doc[:500]}" for i, doc in enumerate(documents)])

    prompt = f"""بالنظر للاستعلام والمستندات أدناه، رتب المستندات حسب الصلة.
أرجع فقط فهارس المستندات بترتيب الصلة، الأكثر صلة أولاً.

الاستعلام: {query}

المستندات:
{doc_list}

تنسيق الإرجاع: فهارس مفصولة بفواصل (مثال: "3, 1, 4, 2, 0")

الترتيب:"""

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0
    )

    # تحليل الاستجابة
    indices = [int(i.strip()) for i in response.choices[0].message.content.split(",")]

    return [(documents[i], idx) for idx, i in enumerate(indices[:top_k])]

خط أنابيب إعادة الترتيب

خط أنابيب استرجاع + إعادة ترتيب كامل:

class RAGPipelineWithReranking:
    def __init__(self, retriever, reranker):
        self.retriever = retriever
        self.reranker = reranker

    def search(self, query: str, retrieve_k: int = 20, final_k: int = 5):
        """
        استرجاع من مرحلتين مع إعادة الترتيب.

        المعاملات:
            query: استعلام البحث
            retrieve_k: العدد للاسترجاع أولياً
            final_k: العدد للإرجاع بعد إعادة الترتيب
        """
        # المرحلة 1: استرجاع سريع
        candidates = self.retriever.search(query, k=retrieve_k)

        # المرحلة 2: إعادة الترتيب
        documents = [c["content"] for c in candidates]
        reranked = self.reranker.rerank(query, documents, top_k=final_k)

        return reranked

# الاستخدام
pipeline = RAGPipelineWithReranking(
    retriever=HybridRetriever(documents),
    reranker=CrossEncoderReranker()
)

results = pipeline.search("كيف أنفذ OAuth؟", retrieve_k=50, final_k=5)

اختيار معيد الترتيب

معيد الترتيب زمن الاستجابة الجودة التكلفة
Cross-encoder (صغير) ~50ms جيدة مجاني
Cross-encoder (كبير) ~200ms أفضل مجاني
Cohere Rerank ~100ms ممتازة $$
ColBERT ~30ms جيدة مجاني
LLM (GPT-4) ~500ms ممتازة $$$
البداية
زمن الاستجابة حرج (<100ms)؟
  ├─ نعم → ColBERT أو cross-encoder صغير
الجودة أولوية قصوى؟
  ├─ نعم → Cohere Rerank أو cross-encoder كبير
ميزانية محدودة؟
  ├─ نعم → cross-encoder مفتوح المصدر
الافتراضي → ms-marco-MiniLM-L-6-v2 (أفضل توازن)

نصيحة الأداء: استرجع 3-5x مرشحين أكثر مما تحتاج، ثم أعد الترتيب. النقطة المثلى عادة استرجاع 20-50 مرشح لأعلى 5 نتائج.

التالي، لنستكشف تقنيات تعزيز الاستعلام لتحسين الاسترجاع قبل أن يبدأ حتى. :::

اختبار

الوحدة 4: البحث الهجين وإعادة الترتيب

خذ الاختبار