لقد غيّر التوليد المعزز بالاسترجاع (RAG) طريقة تفاعلنا مع نماذج اللغة الكبيرة (LLMs) من خلال ربطها بمعرفة خارجية. ومع ذلك، تعتمد جودة المخرجات بشكل كبير على جودة السياق المسترجع. وعلى الرغم من أن البحث في التشابه المتجهي فعال في إيجاد وثائق ذات صلة عامة، إلا أنه غالباً ما يواجه صعوبة في المحاذاة الدلالية الدقيقة، مما يؤدي إلى "إيجابيات خاطئة" قد تربك النموذج. وهنا يأتي دور إعادة الترتيب.
لماذا إعادة الترتيب ضرورية
تستخدم خوارزميات البحث المتجهي القياسية عادةً محوّلات ثنائية (bi-encoders)، والتي ترمّز الاستعلام والوثيقة بشكل مستقل. وعلى الرغم من أن هذا سريع وقابل للتوسع، إلا أنه يفتقر إلى القدرة على التفاعل بين رموز الاستعلام والوثيقة لالتقاط العلاقات الدقيقة. تطبّق إعادة الترتيب عملية أكثر تكلفة من حيث الحساب، تتضمن عادةً محوّلات تقاطع (cross-encoders)، على المرشحين الأوائل (Top K) الذين يعيدهم البحث الأولي. من خلال تحليل التفاعل بين الاستعلام وكل وثيقة، يخصص معيد الترتيب درجة صلة جديدة وأكثر دقة، مما يدفع المقاطع الأكثر صلة إلى أعلى القائمة.
محوّلات التقاطع مقابل المحوّلات الثنائية
فهم الفرق أمر بالغ الأهمية. ينشئ المحوّل الثنائي تمثيلات (embeddings) منفصلة للاستعلام والوثيقة، ويحسب التشابه الجيبية (cosine similarity) بينهما. في المقابل، يأخذ محوّل التقاطع الاستعلام والوثيقة كمدخل مدمج واحد ومعالجتهما بشكل متزامن عبر نموذج التحويل (transformer). وهذا يسمح للنموذج بفهم اعتماديات السياق التي تُفقد في الترميز المستقل. وعلى الرغم من أن محوّلات التقاطع أبطأ، إلا أنها أكثر دقة بشكل كبير، مما يجعلها مثالية لمرحلة إعادة الترتيب حيث تحتاج فقط إلى معالجة مجموعة فرعية صغيرة من الوثائق (مثلاً، أعلى 20 من أصل 1000).
تنفيذ إعادة الترتيب بلغة بايثون
دمج معيد ترتيب في خط أنابيب RAG الخاص بك أمر بسيط باستخدام أطر عمل الذكاء الاصطناعي الحديثة. أدناه مثال باستخدام مكتبة `sentence-transformers` مع نموذج محوّل تقاطع، وهو خيار شائع لتوازن الأداء وسهولة الاستخدام.
from sentence_transformers import CrossEncoder
from typing import List, Tuple
class ReRanker:
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[int, float]]:
"""
يعيد ترتيب قائمة من الوثائق بناءً على صلتها بالاستعلام.
Args:
query: نص الاستعلام.
documents: قائمة من نصوص الوثائق لإعادة ترتيبها.
top_k: عدد النتائج العلوية المراد إرجاعها.
Returns:
قائمة من السجلات (tuples) تحتوي على (مؤشر الوثيقة، الدرجة).
"""
# تحضير أزواج المدخلات (الاستعلام، الوثيقة)
inputs = [(query, doc) for doc in documents]
# تقييم الأزواج
scores = self.model.predict(inputs)
# الحصول على مؤشرات أعلى K درجات
top_indices = sorted(range(len(scores)), key=lambda i: scores[i], reverse=True)[:top_k]
# إرجاع المؤشرات الأصلية والدرجات
return [(idx, scores[idx]) for idx in top_indices]
# مثال على الاستخدام
query = "ما هي الفوائد الصحية للزنجبيل؟"
documents = [
"الزنجبيل له خصائص مضادة للالتهابات ويمكن أن يساعد في الغثيان.",
"الطقس مشمس اليوم في لندن.",
"شاي الزنجبيل علاج شائع للزكام ومشاكل الهضم.",
"بايثون لغة برمجة شائعة.",
"كعك الزنجبيل (Gingerbread) يُصنع بهارات تشمل الزنجبيل."
]
reranker = ReRanker()
results = reranker.rerank(query, documents, top_k=3)
for idx, score in results:
print(f"Score: {score:.4f} | Doc: {documents[idx]}")
أفضل الممارسات والاعتبارات
- مقايضات زمن الاستجابة (Latency): حدّد دائماً عدد المرشحين الممررين إلى معيد الترتيب. إعادة ترتيب 1000 وثيقة ستزيد زمن الاستجابة بشكل كبير. إعادة ترتيب أعلى 20-50 نتيجة من البحث المتجهي هي نقطة مثالية.
- اختيار النموذج: اختر معيد ترتيب تم تدريبه على بيانات مشابهة لمجالك. تعمل النماذج العامة مثل
ms-marco-MiniLMبشكل جيد للمعرفة العامة، لكن النماذج المتخصصة في المجال (مثلاً، للنصوص القانونية أو الطبية) قد تعطي نتائج أفضل. - التكامل: استخدم درجات إعادة الترتيب لتعديل عدد المقاطع الممررة إلى LLM بشكل ديناميكي. إذا كانت الدرجة العلوية منخفضة جداً، ففكّر في الرجوع إلى بحث أوسع أو عدم الاسترجاع على الإطلاق.
الخلاصة
إعادة الترتيب مكوّن حاسم في بناء أنظمة RAG عالية الجودة. من خلال إضافة طبقة التكرير هذه، يمكنك تقليل الهلوسة (hallucinations) بشكل كبير وتحسين الدقة الواقعية لمخرجات LLM الخاصة بك. مع استمرار تحسين نماذج محوّلات التقاطع في السرعة والكفاءة، سيتقلص الفجوة بين البحث التقريبي السريع وتقييم الصلة الدقيق، مما يجعل إعادة الترتيب أداة متاحة بشكل متزايد وجوهرية في مجموعة أدوات مهندس الذكاء الاصطناعي.