كشف المرتكزات لـ RAG: كواشف متوازية، ثم استدعاء نموذج لغوي كبير واحد في النهاية
تقنية لـ RAG الفعالة تستخدم كاشفات متوازية خفيفة الوزن لتحديد المرتكزات الدلالية قبل إجراء استدعاء واحد ومستهدف لنموذج اللغة الكبير، مما يقلل بشكل كبير من زمن الاستجابة والتكلفة.
الوسوم
ملخص سريع
تقنية لـ RAG الفعالة تستخدم كاشفات متوازية خفيفة الوزن لتحديد المرتكزات الدلالية قبل إجراء استدعاء واحد ومستهدف لنموذج اللغة الكبير، مما يقلل بشكل كبير من زمن الاستجابة والتكلفة.
كشف المرتكزات لـ RAG: كاشفات متوازية، ثم استدعاء واحد لنموذج اللغة الكبير في النهاية
أصبحت بنية التوليد المعزز بالاسترجاع (RAG) البنية الفعلية لتثبيت مخرجات نماذج اللغة الكبيرة (LLMs) في المعرفة الخارجية. ومع ذلك، لا يزال هناك تحدٍ مستمر: كيفية ضمان أن السياق المسترجع يحتوي على "مرتكزات" موثوقة وذات صلة قبل أن يولد النموذج استجابة. تستدعي الأساليب التقليدية النموذج عدة مرات - مرة للاسترجاع، ومرة للتحقق، ومرة للتوليد النهائي - مما يؤدي إلى زيادة زمن الاستجابة والتكلفة. ظهر نموذج أكثر كفاءة: تشغيل كاشفات خفيفة الوزن ومتوازية لتحديد المرتكزات في المستندات المسترجعة، ثم إجراء استدعاء واحد للنموذج في النهاية للتوليد. تستكشف هذه المقالة نهج كشف المرتكزات، وتوفر تنفيذًا ملموسًا، وتوضح كيفية بناء نظام جاهز للإنتاج باستخدام أدوات مفتوحة المصدر.
فهم كشف المرتكزات في RAG
المرتكز في RAG هو قطعة نصية مسترجعة تعمل كأساس موثوق لاستجابة النموذج. إنها حقيقة، أو إحصائية، أو اقتباس، أو عبارة منطقية يمكن التحقق منها واستخدامها مباشرة في التوليد. كشف المرتكزات هو عملية تحديد هذه القطع قبل أن يرى النموذج السياق. الفكرة الرئيسية هي أن العديد من المرتكزات المحتملة مشوشة - قد تكون غير ذات صلة، أو متناقضة، أو قديمة. من خلال تشغيل كاشفات متوازية، يمكنك تصفية وترتيب المرتكزات دون استدعاء النموذج، مع الاحتفاظ باستدعاء النموذج للمخرجات النهائية المصقولة.
يتماشى هذا النهج مع الاتجاهات الحديثة في تصميم أنظمة الذكاء الاصطناعي، حيث تتعامل النماذج المتخصصة خفيفة الوزن (مثل نماذج التضمين، أو المصنفات، أو المحولات الصغيرة) مع المعالجة المسبقة، بينما تُستخدم النماذج التوليدية الكبيرة بشكل مقتصد. نشرت شركات رائدة في الصناعة مثل OpenAI وGoogle وMicrosoft أبحاثًا حول تقليل استدعاءات النموذج من خلال خطوط أنابيب معالجة مسبقة فعالة، على الرغم من اختلاف تفاصيل التنفيذ المحددة. نهج الكاشفات المتوازية هو توليفة عملية من هذه الأفكار.
المتطلبات
لمتابعة هذا الدليل، ستحتاج إلى:
- Python 3.9 أو أحدث
- جهاز بذاكرة وصول عشوائي لا تقل عن 8 جيجابايت (16 جيجابايت موصى بها لتشغيل كاشفات متعددة)
- إلمام أساسي بلغة Python وأدوات سطر الأوامر
- حزم Python التالية: `transformers`، `sentence-transformers`، `torch`، `faiss-cpu`، `pandas`، `numpy`، `openai` (أو ما شابه ذلك للوصول إلى النموذج)
ستحتاج أيضًا إلى مفتاح API للنموذج (مثل من OpenAI) لخطوة التوليد النهائية. تعمل كاشفات المرتكزات محليًا.
التثبيت خطوة بخطوة
1. إنشاء بيئة افتراضية
ابدأ بإنشاء بيئة Python معزولة لتجنب تعارض التبعيات.
python3 -m venv anchor-rag-env
source anchor-rag-env/bin/activateيقوم هذا الأمر بإنشاء بيئة افتراضية باسم `anchor-rag-env` وتنشيطها.
2. تثبيت التبعيات الأساسية
قم بتثبيت المكتبات المطلوبة للكاشفات وتكامل النموذج.
pip install transformers sentence-transformers torch faiss-cpu pandas numpy openai- توفر `transformers` و `sentence-transformers` نماذج مدربة مسبقًا لتشفير النصوص وتصنيفها.
- `torch` هو المحرك الخلفي لـ PyTorch.
- `faiss-cpu` يتيح البحث السريع عن التشابه لترتيب المرتكزات.
- `pandas` و `numpy` يتعاملان مع معالجة البيانات.
- `openai` يُستخدم لاستدعاء النموذج النهائي (استبدله بموفر النموذج الذي تختاره).
3. التحقق من التثبيت
اختبر أن البيئة تم إعدادها بشكل صحيح عن طريق تشغيل فحص صغير.
python -c "import sentence_transformers; print('Installation OK')"إذا رأيت "Installation OK"، تابع. وإلا، تحقق من وجود أخطاء (مثل برامج تشغيل CUDA المفقودة لـ torch - إذا لم يكن لديك وحدة معالجة رسومية، فإن الإصدارات الخاصة بوحدة المعالجة المركزية فقط ستكون كافية).
نظرة عامة على البنية
يعمل نظام كشف المرتكزات على ثلاث مراحل:
1. **الاسترجاع** - الحصول على مجموعة من المستندات المرشحة (مثل من قاعدة بيانات متجهات أو بحث ويب). 2. **الكاشفات المتوازية** - تشغيل نماذج خفيفة الوزن متعددة في وقت واحد لتسجيل وتصفية المرتكزات:
- كاشف الصلة (مثل مصنف قائم على BERT)
- كاشف الواقعية (مثل نموذج الاستدلال اللغوي الطبيعي)
- كاشف التكرار (مثل تشابه جيب التمام)
- كاشف تماسك الكيانات (مثل تداخل الكيانات المسماة)
3. **استدعاء واحد للنموذج** - تجميع المرتكزات ذات الدرجات الأعلى وتمريرها كسياق مكثف للنموذج للتوليد.
يقلل هذا التصميم من استدعاءات النموذج مع زيادة جودة سياق الإدخال إلى أقصى حد.
التنفيذ: بناء الكاشفات المتوازية
الكاشف 1: تسجيل الصلة
يستخدم كاشف الصلة نموذج محول الجمل لحساب تشابه جيب التمام بين الاستعلام وكل قطعة مسترجعة. هذه خطوة سريعة وغير خاضعة للإشراف.
from sentence_transformers import SentenceTransformer, util
import numpy as np
# تحميل نموذج تضمين خفيف الوزن
model = SentenceTransformer('all-MiniLM-L6-v2')
def relevance_detector(query, chunks):
query_emb = model.encode(query, convert_to_tensor=True)
chunk_embs = model.encode(chunks, convert_to_tensor=True)
scores = util.cos_sim(query_emb, chunk_embs)[0].cpu().numpy()
return scoresترجع هذه الدالة مصفوفة numpy من درجات الصلة (0 إلى 1) لكل قطعة. تشير الدرجات العالية إلى توافق دلالي قوي مع الاستعلام.
الكاشف 2: التحقق من الواقعية
يستخدم كاشف الواقعية نموذج الاستدلال اللغوي الطبيعي (NLI) للتحقق مما إذا كانت كل قطعة تحتوي على عبارات متسقة منطقيًا. نستخدم نموذج NLI مدرب مسبقًا من Hugging Face.
from transformers import pipeline
nli_pipeline = pipeline("text-classification", model="roberta-large-mnli")
def factuality_detector(chunks):
# لكل قطعة، تحقق مما إذا كانت "مستلزمة" بذاتها (استدلال للاتساق الداخلي)
scores = []
for chunk in chunks:
result = nli_pipeline(chunk[:512]) # اقتطاع إلى الحد الأقصى لطول النموذج
# استخدام درجة "الاستلزام" كبديل للواقعية
if result[0]['label'] == 'ENTAILMENT':
scores.append(result[0]['score'])
else:
scores.append(0.0)
return np.array(scores)هذا استدلال مبسط. في الإنتاج، ستقارن القطع بقاعدة معرفية موثوقة أو تستخدم نموذج واقعية مخصص. النقطة الرئيسية هي أنه يعمل بالتوازي مع الكاشفات الأخرى.
الكاشف 3: مرشح التكرار
يتم اكتشاف التكرار عن طريق حساب تشابه جيب التمام الزوجي بين القطع. يتم تقليل وزن القطع المتشابهة جدًا مع بعضها البعض لتجنب المعلومات المكررة.
def redundancy_detector(chunks, threshold=0.85):
chunk_embs = model.encode(chunks, convert_to_tensor=True)
sim_matrix = util.cos_sim(chunk_embs, chunk_embs).cpu().numpy()
scores = np.ones(len(chunks))
for i in range(len(chunks)):
# حساب عدد القطع الأخرى المشابهة جدًا لهذه القطعة
redundant_count = np.sum(sim_matrix[i] > threshold) - 1
scores[i] = 1.0 / (1.0 + redundant_count) # معاقبة القطع المكررة
return scoresالقطعة الفريدة تحصل على درجة 1.0؛ القطعة المطابقة لثلاث قطع أخرى تحصل على درجة 0.25.
الكاشف 4: تماسك الكيانات
يضمن هذا الكاشف أن القطع تحتوي على كيانات (أشخاص، أماكن، تواريخ) ذات صلة بالاستعلام. يستخدم نموذجًا بسيطًا للتعرف على الكيانات المسماة (NER).
from transformers import pipeline
ner_pipeline = pipeline("ner", model="dslim/bert-base-NER", aggregation_strategy="simple")
def entity_coherence_detector(query, chunks):
query_entities = set([e['word'].lower() for e in ner_pipeline(query)])
scores = []
for chunk in chunks:
chunk_entities = set([e['word'].lower() for e in ner_pipeline(chunk[:512])])
overlap = len(query_entities & chunk_entities) / max(len(query_entities), 1)
scores.append(overlap)
return np.array(scores)درجة 1.0 تعني أن جميع كيانات الاستعلام تظهر في القطعة؛ 0.0 تعني عدم وجود تداخل.
تشغيل الكاشفات بالتوازي
لتشغيل جميع الكاشفات في وقت واحد، استخدم وحدة `concurrent.futures` في Python. هذا هو جوهر مفهوم "الكاشفات المتوازية".
from concurrent.futures import ThreadPoolExecutor
def run_all_detectors(query, chunks):
with ThreadPoolExecutor(max_workers=4) as executor:
future_relevance = executor.submit(relevance_detector, query, chunks)
future_factuality = executor.submit(factuality_detector, chunks)
future_redundancy = executor.submit(redundancy_detector, chunks)
future_entity = executor.submit(entity_coherence_detector, query, chunks)
relevance_scores = future_relevance.result()
factuality_scores = future_factuality.result()
redundancy_scores = future_redundancy.result()
entity_scores = future_entity.result()
# دمج الدرجات (مجموع مرجح بسيط)
combined = (0.4 * relevance_scores +
0.3 * factuality_scores +
0.2 * redundancy_scores +
0.1 * entity_scores)
return combinedاضبط الأوزان بناءً على حالة الاستخدام الخاصة بك. تُستخدم الدرجات المجمعة لتحديد أفضل k من المرتكزات.
استدعاء واحد للنموذج في النهاية
بعد أن تقوم الكاشفات المتوازية بتسجيل وتصفية القطع، تسترجع أفضل k من المرتكزات وتمررها إلى النموذج في استدعاء واحد. هذا هو المكان الذي يحدث فيه التوليد النهائي.
import openai
openai.api_key = "your-api-key-here"
def generate_with_anchors(query, top_anchors, llm_model="gpt-4"):
# دمج المرتكزات في سياق مكثف
anchor_text = "\n\n".join([f"[Anchor {i+1}] {chunk}" for i, chunk in enumerate(top_anchors)])
system_prompt = "أنت مساعد مفيد. استخدم فقط المرتكزات المقدمة للإجابة على الاستعلام. إذا كانت المرتكزات غير كافية، فقل ذلك."
user_prompt = f"الاستعلام: {query}\n\nالمرتكزات:\n{anchor_text}\n\nالإجابة:"
response = openai.ChatCompletion.create(
model=llm_model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=500,
temperature=0.3
)
return response.choices[0].message['content']تقوم هذه الدالة باستدعاء واحد بالضبط للنموذج. يتلقى النموذج فقط المرتكزات الأعلى ترتيبًا، مما يقلل من استخدام الرموز المميزة وخطر الهلوسة.
مثال على الاستخدام
الخطوة 1: تحضير بيانات نموذجية
افترض أنك استرجعت ثلاث قطع من قاعدة معرفية.
query = "ما هي عاصمة فرنسا؟"
chunks = [
"فرنسا دولة في أوروبا. عاصمتها باريس، التي تشتهر ببرج إيفل.",
"باريس هي عاصمة فرنسا وغالبًا ما تسمى مدينة النور.",
"يضم متحف اللوفر في باريس لوحة الموناليزا."
]الخطوة 2: تشغيل الكاشفات المتوازية
combined_scores = run_all_detectors(query, chunks)
top_indices = np.argsort(combined_scores)[-2:][::-1] # اختيار أفضل مرتكزين
top_anchors = [chunks[i] for i in top_indices]
print("أفضل المرتكزات:", top_anchors)قد يكون الناتج:
أفضل المرتكزات: ['فرنسا دولة في أوروبا. عاصمتها باريس، التي تشتهر ببرج إيفل.', 'باريس هي عاصمة فرنسا وغالبًا ما تسمى مدينة النور.']الخطوة 3: توليد الإجابة النهائية
answer = generate_with_anchors(query, top_anchors)
print(answer)الناتج:
عاصمة فرنسا هي باريس.تم إجراء استدعاء واحد فقط للنموذج، واستخدم فقط القطعتين الأكثر صلة وواقعية وعدم تكرار.
اعتبارات الأداء
- **زمن الاستجابة:** تعمل الكاشفات المتوازية في حوالي 0.5-2 ثانية على وحدة المعالجة المركزية (اعتمادًا على عدد القطع وحجم النموذج). يضيف استدعاء النموذج 1-3 ثوانٍ. إجمالي الوقت عادة ما يكون أقل من 5 ثوانٍ.
- **التكلفة:** تدفع مقابل استدعاء واحد للنموذج لكل استعلام بدلاً من ثلاثة أو أربعة. تعمل الكاشفات محليًا بدون تكلفة API.
- **الدقة:** يمكن ضبط نظام الدرجات المرجحة. للاستخدام في مجال محدد، استبدل نموذج NLI العام بنموذج واقعية مضبوط بدقة.
- **قابلية التوسع:** استخدم فهرسة FAISS لمجموعات القطع الكبيرة (مثل آلاف القطع) لتسريع كشف الصلة والتكرار.
الخلاصة
كشف المرتكزات باستخدام كاشفات متوازية متبوعة باستدعاء واحد للنموذج هو نمط تصميم عملي لأنظمة RAG الإنتاجية. يقلل من زمن الاستجابة، ويخفض تكاليف API، ويحسن جودة المخرجات عن طريق تصفية السياق المشوش قبل أن يراه النموذج. يستخدم التنفيذ الموضح هنا نماذج خفيفة الوزن ومفتوحة المصدر للصلة والواقعية والتكرار وتماسك الكيانات - وكلها تعمل بالتوازي. يقوم استدعاء النموذج النهائي بعد ذلك بتوليد استجابة مدعمة من مجموعة منسقة من المرتكزات. هذا النهج مستوحى من الاتجاهات الصناعية نحو خطوط أنابيب ذكاء اصطناعي فعالة متعددة المراحل، كما هو موضح في الأبحاث من OpenAI وGoogle وMicrosoft. من خلال اعتماد هذا النمط، يمكنك بناء أنظمة RAG سريعة وموثوقة، دون التضحية بالقوة التوليدية لنماذج اللغة الكبيرة.
المصادر
أسئلة شائعة
عن ماذا يتحدث هذا المقال؟
يتناول هذا المقال موضوع "كشف المرتكزات لـ RAG: كواشف متوازية، ثم استدعاء نموذج لغوي كبير واحد في النهاية" ضمن تصنيف أدوات الذكاء الاصطناعي. تقنية لـ RAG الفعالة تستخدم كاشفات متوازية خفيفة الوزن لتحديد المرتكزات الدلالية قبل إجراء استدعاء واحد ومستهدف لنموذج اللغة الكبير، مما يقلل بشكل كبير من زمن الاستجابة والتكلفة.
لمن يفيد هذا المقال؟
يفيد القراء المهتمين بفهم أدوات وتقنيات الذكاء الاصطناعي بطريقة عملية وواضحة.
ما الخطوة التالية؟
اقرأ المقال كاملاً، راجع المصادر المرفقة، ثم جرّب الأفكار المناسبة لاحتياجك بحذر.



