عند بناء تطبيقات التوليد المعزز بالاسترجاع (RAG)، يواجه المطورون غالباً عنق زجاجة شائع: مشكلة "الإبرة في كومة القش". بينما تتفوق قواعد البيانات المتجهة في استرجاع المستندات المشابهة دلاليًا على نطاق واسع، فإنها تعتمد على تضمينات كثيفة تقترب من المحاكاة. هذا النهج قد يؤدي إلى ضوضاء، حيث تكون القطع المسترجعة ذات صلة موضوعية لكنها غير كافية سياقيًا للإجابة على الاستفسارات المعقدة. أدخل إعادة الترتيب—خطوة التحسين الحاسمة التي تحول نظام RAG الجيد إلى نظام رائع.
فهم فجوة الاسترجاع
في خط أنابيب RAG القياسي، تستخدم خطوة الاسترجاع عادةً بنية مزدوجة التشفير (bi-encoder). هنا، يتم تشفير الاستفسار والمستند بشكل مستقل إلى تضمينات متجهة، ويتم حساب التشابه عبر تشابه جيب التمام. بينما تكون هذه الطريقة فعالة من حيث الحساب وقابلة للتوسع لملايين المستندات، فإنها تفتقر إلى القدرة على فهم التفاعل الدقيق بين مصطلحات الاستفسار المحددة ومحتوى المستند.
على سبيل المثال، إذا سأل المستخدم: "هل يسمح العقد بإنهاء مبكر دون غرامة؟"، فقد يسترجع التشفير المزدوج بندًا يتعلق بالإنهاء المبكر من قسم مختلف يلمح إلى وجود غرامات، لمجرد تداخل الكلمات دلاليًا. هنا تتدخل مرحلة إعادة الترتيب لتصحيح هذه الأخطاء.
إعادة الترتيب باستخدام Cross-Encoders
المعيار الذهبي لإعادة الترتيب هو استخدام نماذج Cross-Encoders. على عكس التشفيرات المزدوجة، تعالج Cross-Encoders الاستفسار والمستند في وقت واحد. يمكنها الانتباه إلى كل كلمة في الاستفسار وكل كلمة في المستند، مما يسمح لها بالتقاط التفاعلات الدلالية المعقدة، والنفي، والقيود المحددة.
عادةً، يستخدم خط الأنابيب بحث المتجهات الكثيفة للاسترجاع الخشن الأولي (مثل جلب أفضل 50-100 مستند)، ثم يطبق Cross-Encoder لإعادة تقييم هذه المرشحين، ليعيد فقط أفضل 5-10 قطع ذات صلة إلى نموذج اللغات الكبيرة (LLM). يوازن هذا النهج الهجين بين السرعة والدقة.
التنفيذ العملي باستخدام Sentence Transformers
إن تنفيذ مُعيد ترتيب أمر بسيط باستخدام مكتبات Python الحديثة. توفر مكتبة sentence-transformers نماذج Cross-Encoder مدربة مسبقًا يمكن دمجها في أي خط أنابيب RAG. فيما يلي مثال عملي لكيفية تقييم المستندات المسترجعة مقابل استفسار.
from sentence_transformers import CrossEncoder
# تحميل نموذج Cross-Encoder مدرب مسبقًا
model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# استفسار المستخدم
query = "ما هي فوائد استخدام Cross-Encoders لإعادة الترتيب؟"
# المرشحين الأوليين المسترجعين من قاعدة بيانات متجهة (مرحلة التشفير المزدوج)
candidates = [
"تعد Cross-encoders بطيئة ولكنها دقيقة.",
"تستخدم قواعد البيانات المتجهة تشابه جيب التمام للبحث.",
"تحسن إعادة الترتيب الدقة من خلال معالجة أزواج الاستفسار-المستند بشكل مشترك.",
"يمكن أن يتوهّم نموذج اللغات الكبيرة (LLM) إذا كان السياق غير ذي صلة."
]
# حساب درجات الصلة
scores = model.predict([(query, text) for text in candidates])
# دمج الدرجات مع النصوص وترتيبها تنازليًا حسب الدرجة
results = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
for text, score in results:
print(f"الدرجة: {score:.4f} | النص: {text}")
في هذا الجزء من الكود، يعيد النموذج درجة صلة لكل مرشح. ومن خلال ترتيب هذه النتائج، نضمن أن يتلقى نموذج اللغات الكبيرة (LLM) المعلومات الأكثر صلة سياقيًا، مما يقلل بشكل كبير من معدلات التوهّم.
الخاتمة
إعادة الترتيب ليست مجرد ميزة اختيارية؛ بل هي مكون ضروري لأنظمة RAG الجاهزة للإنتاج. من خلال الاستفادة من Cross-Encoders لتحسين نتائج الاسترجاع الأولية، يمكن للمطورين تحسين دقة استرجاع المعرفة بشكل كبير. بينما يضيف هذا زخماً زمنياً (latency)، فإن المقايضة تستحق ذلك في الغالب مقابل التحسن في جودة الإجابة. ومع توسيع نطاق تطبيقات الذكاء الاصطناعي الخاصة بك، سيكون دمج استراتيجية قوية لإعادة الترتيب هو العامل المميز بين النمو الأولي والمنتج الموثوق.