Retrieval-Augmented Generation (RAG)

تعزيز دقة RAG: غوص عميق في استراتيجيات إعادة الترتيب الدلالي

أصبحت عملية التوليد المعزز بالاسترجاع (RAG) هي البنية القياسية لترسيخ نماذج اللغات الكبيرة (LLMs) في البيانات الخاصة. ومع ذلك، فإن عنق الزجاجة الشائع في خطوط أنابيب RAG هو خطوة الاسترجاع الأولية. تعتمد محركات البحث المتجهية القياسية، التي تعتمد على خوارزميات الجيران الأقربين التقريبية (ANN)، على تقريبات سريعة وفعالة من حيث الحساب. وغالباً ما تسترجع هذه المحركات وثائق ذات صلة موضوعية ولكنها سطحية دلاليًا، مما يؤدي إلى سيناريوهات "قمامة داخلة، قمامة خارجة" حيث تقوم نماذج اللغات الكبيرة بتوليد هلاوس (أوهام) أو إجابات غير ذات صلة.

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

بنية الاسترجاع ذات الطابقين

لفهم إعادة الترتيب، من الضروري تصور بنية RAG الحديثة كقمع ذي مرحلتين:

  1. المرحلة 1: استرجاع المرشحين (الاستدعاء). تستخدم هذه المرحلة طرقًا خفيفة الوزن وعالية السرعة مثل البحث المتجهي المتناثر (BM25) أو البحث المتجهي الكثيف (التشابه جيب التمام). الهدف هو استرجاع مجموعة كبيرة من المرشحين (على سبيل المثال، 100 وثيقة) من مجموعة بيانات ضخمة.
  2. المرحلة 2: إعادة الترتيب (الدقة). تأخذ هذه المرحلة الاستعلام وأفضل N مرشحًا من المرحلة 1 وتطبق نموذجًا أكثر تعقيدًا لتقييم مدى صلة هذه الوثائق بدقة أكبر. يتم تمرير أفضل K نتيجة (على سبيل المثال، 5 وثائق) إلى نموذج اللغات الكبيرة.

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

لماذا المحركات المتقاطعة؟

المعيار الصناعي لإعادة الترتيب يتضمن المحركات المتقاطعة (Cross-Encoders). على عكس المحركات ثنائية التشفير (Bi-Encoders) المستخدمة في المرحلة 1، والتي تشفر الاستعلامات والوثائق بشكل مستقل إلى متجهات، تقوم المحركات المتقاطعة بمعالجة الاستعلام والوثيقة معًا في تمرير أمامي واحد. يتيح هذا للنموذج الانتباه إلى التفاعلات المحددة بين كلمات الاستعلام وكلمات الوثيقة، مما يسلط الضوء على العلاقات الدلالية الدقيقة.

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

تنفيذ مُرتبٍ باستخدام بايثون

يعد تنفيذ إعادة الترتيب أمرًا بسيطًا باستخدام مكتبات مثل sentence-transformers أو pyserini. فيما يلي مثال عملي باستخدام مكتبة sentence-transformers الشائعة، والتي توفر نماذج محركات متقاطعة محسنة.

from sentence_transformers import CrossEncoder

# تهيئة نموذج المحرك المتقاطع
# 'cross-encoder/ms-marco-MiniLM-L-6-v2' خيار سريع وفعال
model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')

# الاستعلام وقائمة بالوثائق المرشحة المسترجعة من المرحلة 1
query = "How to implement OAuth2 in Python?"
candidates = [
    "Python is a programming language.",
    "A step-by-step guide to implementing OAuth2 authentication in Python applications using Flask.",
    "Understanding the basics of HTTP requests.",
    "OAuth2 specification document version 2.0."
]

# تشفير أزواج الاستعلام-الوثيقة
# يعيد النموذج درجة صلة لكل زوج
scores = model.predict([(query, doc) for doc in candidates])

# دمج الدرجات مع الوثائق وترتيبها حسب الصلة
ranked_results = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)

# طباعة النتيجة الأعلى ترتيبًا
print("Top Ranked Result:")
print(f"Document: {ranked_results[0][0]}")
print(f"Score: {ranked_results[0][1]:.4f}")

في هذا المثال، ستحصل الوثيقة الثانية، التي تذكر صراحةً "OAuth2" و"Python"، على درجة أعلى بكثير من الوثائق العامة التي تتحدث عن "Python" أو "HTTP"، مما يضمن حصول نموذج اللغات الكبيرة على المعلومات الأكثر دقة من حيث السياق.

موازنة زمن الاستجابة والدقة

تعد المحركات المتقاطعة مكلفة حسابيًا لأنها تعالج أزواج النصوص بشكل تسلسلي بدلاً من متوازٍ. إذا كانت مجموعة البيانات الخاصة بك ضخمة وحجم الاستعلامات مرتفعًا، فإن تشغيل محرك متقاطع على آلاف المرشحين أمر مستحيل. ولهذا السبب تعد النهج ذو المرحلتين أمرًا حاسمًا: تقلل المرحلة الأولى مساحة البحث من ملايين إلى مئات، وتقوم المرحلة الثانية بتحسين هذه المجموعة الصغيرة.

في بيئات الإنتاج، فكر في استخدام واجهات برمجة التطبيقات (APIs) المخصصة لإعادة الترتيب أو النماذج المحسنة مثل ms-marco-TinyBERT-L-2-v2 لاستنتاج أسرع، أو استراتيجيات التخزين المؤقت للاستعلامات المتكررة.

الخاتمة

إعادة الترتيب ليست مجرد تحسين؛ بل هي ضرورة لبناء تطبيقات RAG موثوقة وجاهزة للإنتاج. من خلال فصل الاستدعاء عن الدقة، يمكن للمطورين الاستفادة من سرعة قواعد البيانات المتجهية مع الحفاظ على دقة الفهم الدلالي العميق. يعد تنفيذ مُرتبٍ يعتمد على المحرك المتقاطع أحد أعلى التغييرات عائدًا على الاستثمار (ROI) التي يمكنك إجراؤها لتحسين جودة إجابات نموذج اللغات الكبيرة، مما يقلل من الهلاوس ويزيد من ثقة المستخدم.

Share: