Retrieval-Augmented Generation (RAG)

إتقان البحث الهجين: المعيار الذهبي لدقة RAG

لقد أحدث توليد المعزز بالاسترجاع (RAG) ثورة في طريقة تفاعل نماذج اللغة الكبيرة (LLMs) مع البيانات الخاصة. ومع ذلك، فإن البحث الدلالي البحت (المعتمد على المتجهات) يعاني من عيب حاسم: فهو غالبًا ما يواجه صعوبة في التعامل مع المعرفات المحددة، أو الأسماء الخاصة، أو المصطلحات التقنية الدقيقة. إذا طلبت من نظام RAG "رمز الخطأ 40412"، فقد يسترجع قاعدة بيانات المتجهات صفحات عن أخطاء 404 العامة أو أخطاء "مستوى 400" غير ذات صلة، لكن نادرًا ما تسترجع التعريف الدقيق الذي تحتاجه.

الحل؟ البحث الهجين.

يجمع البحث الهجين بين الفهم السياقي لتضمينات المتجهات (Vector Embeddings) ودقة مطابقة الكلمات المفتاحية التقليدية (البحث المتناثر). من خلال دمج هاتين المنهجيتين، تحسّن بشكل كبير من الاستدعاء (Recall) والدقة (Precision)، مما يضمن لنموذج اللغة الخاص بك استرجاع المستندات الأكثر صلة في كل مرة.

لماذا لا يكفي البحث بالمتجهات البحت

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

  • غياب التحديد: لا تستطيع المتجهات التمييز بين "الجزء أ" و"الجزء ب" إذا ظهرتا في سياقات متشابهة.
  • مشاكل التقطيع (Tokenization): قد تكون التمثيلات التضمينية للمعرّفات الفريدة، أو أرمات المنتجات، أو الأسماء الخاصة النادرة ضعيفة لأنها تفتقر إلى التكرار السياقي في بيانات التدريب.
  • فجوات الاستدعاء: إذا احتوت الاستعلام على كلمة مفتاحية بعيدة دلاليًا عن المستند المستهدف لكنها متطابقة لفظيًا، فسيغفل البحث بالمتجهات عنها.

في المقابل، البحث بالكلمات المفتاحية التقليدية (مثل BM25) رائع في إيجاد التطابقات الدقيقة لكنه يفشل في فهم النية. لا يمكنه القول إن "كيفية إصلاح أنبوب مسرب" و"إصلاح سباكة للمغاسل" مرتبطان ما لم تتداخل الكلمات.

بنية البحث الهجين

يتضمن خط أنابيب البحث الهجين النموذجي ثلاث خطوات رئيسية:

  1. الاسترجاع الكثيف (Dense Retrieval): قم بتضمين الاستعلام واسترجاع أفضل K نتائج بناءً على تشابه جيب التمام (Cosine Similarity).
  2. الاسترجاع المتناثر (Sparse Retrieval): استخدم محرك بحث تقليدي (مثل Elasticsearch، أو البحث النصي الكامل في PostgreSQL) لاسترجاع أفضل K نتائج بناءً على التداخل اللفظي (BM25).
  3. الدمج (Fusion): ادمج مجموعتي النتائج باستخدام خوارزمية ترتيب مثل الاندماج العكسي للترتيب (Reciprocal Rank Fusion - RRF).

مثال على التنفيذ

فيما يلي مثال بلغة بايثون باستخدام LangChain وChroma (للمتجهات) مع تنفيذ بسيط لـ BM25. في بيئة الإنتاج، قد تستخدم Elasticsearch أو OpenSearch للمكون المتناثر.

import numpy as np
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.retrievers import ParentDocumentRetriever
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1. إعداد مخزن المتجهات (البحث الكثيف)
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_texts(texts, embeddings=embeddings)
vector_retriever = vectorstore.as_retriever(k=5)

# 2. إعداد البحث المتناثر (BM25)
# ملاحظة: في تطبيق حقيقي، ستستخدم Elasticsearch أو فهرس TF-IDF/BM25
def bm25_search(query, documents, top_k=5):
    # كود زائف لترتيب BM25
    # يعيد قائمة من (document_id, score)
    pass

def reciprocal_rank_fusion(rank_lists, k=60):
    """
    يدمج قوائم مرتبة متعددة في قائمة مرتبة واحدة.
    k هو ثابت (عادة 60) لتخفيف تأثير العناصر ذات الترتيب الأدنى.
    """
    scores = {}
    for i, rank_list in enumerate(rank_lists):
        for rank, item in enumerate(rank_list, start=1):
            if item not in scores:
                scores[item] = 0
            scores[item] += 1.0 / (k + rank)
    
    # ترتيب حسب الدرجة تنازليًا
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

# 3. دالة الاسترجاع الهجين
def hybrid_search(query, documents):
    # الحصول على النتائج من البحث بالمتجهات
    vector_results = vector_retriever.get_relevant_documents(query)
    vector_ids = [doc.metadata['id'] for doc in vector_results]
    
    # الحصول على النتائج من BM25
    bm25_results = bm25_search(query, documents, top_k=5)
    bm25_ids = [res[0] for res in bm25_results]
    
    # دمج النتائج
    fused_ids, fused_scores = reciprocal_rank_fusion([vector_ids, bm25_ids])
    
    # إرجاع أفضل 3 مستندات
    return fused_ids[:3]

نصائح عملية للضبط

  • الوزن (Weighting): يمكنك تطبيق أوزان على معادلة RRF إذا كانت إحدى طرق البحث أكثر موثوقية تاريخيًا لمجالك. على سبيل المثال، إذا اعتمدت المستندات التقنية بشدة على أرقام الأجزاء، فامنح البحث المتناثر وزنًا أعلى.
  • نماذج التضمين: استخدم نماذج تضمين أحدث وأعلى أداء (مثل text-embedding-3-large) لتعظيم جودة مكون البحث الكثيف.
  • الفهرسة: تأكد من أن فهرسك المتناثر محسّن. استخدم n-grams أو قوائم المرادفات في إعدادات محرك البحث للتعامل بفعالية مع الاختصارات والجمع.

خاتمة

لم يعد البحث الهجين تحسينًا اختياريًا لأنظمة RAG؛ بل هو ممارسة مثالية للتطبيقات ذات الجودة الإنتاجية. من خلال سد الفجوة بين الفهم الدلالي والدقة اللفظية، تخلق طبقة استرجاع قوية ودقيقة. ابدأ بدمج RRF بسيط لعمليات البحث بالمتجهات والكلمات المفتاحية الموجودة لديك، وقِس تحسنك في جودة الإجابات، ثم قم بالتكرار من هناك. سيكون الناتج نظامًا يفهم بياناتك حقًا—سواء كان يطلب المعنى لمفهوم أو المعرف الدقيق لمكون.

Share: