هذا المقال يتطلب مستوى: متوسط. هتخرج منه فاهم إزاي تخلّي أي نموذج لغة يجاوب من بياناتك انت — ملفاتك، سياساتك، توثيق منتجك — بدل ما يخترع إجابة تبان مظبوطة وهي غلط.
التوليد المعزّز بالاسترجاع (RAG): النموذج يجاوب من مصدر، مش من ذاكرته
لو سألت ChatGPT عن سياسة استرجاع منتجك، هيرد بثقة بإجابة… غالبًا مخترعة. مش لأنه غبي، لكن لأنه ببساطة مشافش سياستك في التدريب. الحل مش إنك تدرّب نموذج من الأول. الحل اسمه RAG.
المشكلة باختصار
النموذج المدرّب معرفته مجمّدة عند لحظة انتهاء التدريب، ومحدودة بحجم نافذة السياق. أي معلومة خاصة بيك — عقد، تذاكر دعم، توثيق داخلي — هو مبيعرفهاش. ولمّا ميعرفش، بيكمّل بأكثر إجابة محتملة إحصائيًا، واللي بتطلع كلام متماسك لكنه ملوش أساس. ده اللي بنسمّيه هلوسة.
الطريقة الشائعة إن الناس بتحاول تحل ده بإنها تكتب البرومبت أطول وأطول وتلزّق فيه كل الوثائق. الطريقة دي بتفشل بسرعة: بتصطدم بحد نافذة السياق، وبتدفع تكلفة توكنات ضخمة على كل طلب حتى لو 99% من الوثائق مالهاش علاقة بالسؤال.
مثال بسيط: الامتحان مفتوح الكتاب
تخيّل طالبين في امتحان. الأول حافظ كل حاجة من بدري، فبيجاوب من دماغه، ولمّا ينسى بيألّف إجابة تبان واثقة. التاني امتحانه مفتوح الكتاب: قبل ما يكتب أي سؤال، بيفتح الفهرس، يلاقي الصفحة المظبوطة، يقراها، وبعدها يكتب الإجابة وهو باصص فيها.
الطالب التاني ده بالظبط هو RAG. النموذج نفسه لسه هو النموذج، لكن قبل ما يجاوب بنجيبله «الصفحة» الصح من مصادرك ونحطها قدامه في البرومبت. فبيتكلم من مصدر، مش من ذاكرة ناقصة.
يعني إيه RAG بالظبط (علميًا)
RAG اختصار Retrieval-Augmented Generation. الفكرة إنك بتضيف خطوة استرجاع قبل خطوة التوليد. المسار بيمرّ بخمس مراحل:
- التقطيع (Chunking): بتقسّم وثائقك لمقاطع صغيرة (فقرة أو 200-500 كلمة).
- التضمين (Embedding): بتحوّل كل مقطع لمتجه أرقام بيمثّل معناه. نموذج زي
all-MiniLM-L6-v2بيطلّع متجه من 384 رقم لكل مقطع. - الفهرسة: بتخزّن المتجهات في قاعدة بيانات متجهات (FAISS أو pgvector أو Qdrant).
- الاسترجاع: لمّا يجيلك سؤال، بتحوّله لمتجه بنفس النموذج، وتدوّر على أقرب
kمقاطع بتشابه جيب التمام (cosine similarity). - التوليد: بتحقن المقاطع دي في البرومبت مع السؤال، وتقول للنموذج «جاوب من السياق ده بس».
الفكرة الأساسية: المعنى المتقارب = متجهات متقاربة في الفضاء. فبدل ما تدوّر بالكلمة الحرفية، بتدوّر بالمعنى. سؤال «إزاي أرجّع المنتج؟» بيلاقي مقطع مكتوب فيه «سياسة الإرجاع خلال 14 يوم» حتى لو مفيش كلمة مشتركة بينهم.
مثال تنفيذي (Python شغّال)
import numpy as np
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2") # 384-dim
docs = [
"سياسة الإرجaع: تقدر ترجّع أي منتج خلال 14 يوم من الاستلام.",
"الشحن داخل القاهرة بياخد يوم إلى يومين عمل.",
"الدفع متاح بالبطاقة أو عند الاستلام.",
]
doc_vecs = model.encode(docs, normalize_embeddings=True) # (3, 384)
def retrieve(question, k=1):
q = model.encode([question], normalize_embeddings=True)[0]
scores = doc_vecs @ q # cosine (المتجهات مُطبَّعة)
top = np.argsort(scores)[::-1][:k]
return [(docs[i], float(scores[i])) for i in top]
ctx, score = retrieve("إزاي أرجّع المنتج؟")[0]
print(round(score, 3), "->", ctx)
prompt = f"""جاوب من السياق ده فقط. لو مش موجود، قول \"مش متوفر\".
السياق: {ctx}
السؤال: إزاي أرجّع المنتج؟"""
# ابعت prompt لأي LLM (OpenAI/Anthropic/محلي)
لاحظ: مفيش تدريب ولا fine-tuning. أضفت وثيقة جديدة؟ بتعمل لها embedding وتحطها في الفهرس، وبس. المعرفة بتتحدّث فورًا من غير ما تلمس النموذج.
الأرقام اللي بتفرق
الافتراض هنا إن عندك قاعدة معرفة بـ 10 آلاف مقطع وتستخدم نموذج زي GPT-4o أو Claude. الاسترجاع نفسه على 10 آلاف متجه بـ FAISS بياخد أقل من مللي ثانية للاستعلام الواحد. من غير RAG لو حبيت تلزّق كل الـ 10 آلاف مقطع في البرومبت، ده تقريبًا ملايين التوكنات — أكبر من نافذة السياق (128 ألف توكن) وبتكلفة خيالية. مع RAG بتبعت 3 إلى 5 مقاطع بس، يعني قرابة 1-2% من التكلفة، مع دقة أعلى لأن النموذج مش بيتشتّت في نص طويل.
الـ trade-offs
RAG بيكسّبك تحديث معرفة فوري، مصادر قابلة للاقتباس، وتكلفة أقل من إعادة التدريب. بتخسر مقابلها إن جودة الإجابة بقت مرهونة بجودة الاسترجاع: لو رجّعت المقطع الغلط، النموذج هيجاوب غلط بثقة. زوّدت طبقة بنية تحتية جديدة (قاعدة متجهات + خط تضمين) لازم تصونها. وحجم المقطع نفسه trade-off: مقاطع كبيرة تضيّع الدقة، ومقاطع صغيرة أوي بتقطع السياق.
متى لا تستخدم RAG
مش كل مشكلة محتاجة RAG. لو معرفتك ثابتة وصغيرة وتدخل في البرومبت مرة واحدة (زي تعليمات نبرة قصيرة)، حطها في البرومبت مباشرة وخلاص. ولو المطلوب سلوك أو أسلوب مش معرفة حقائق (زي إن النموذج يكتب بصيغة معينة دايمًا)، ده شغل fine-tuning مش استرجاع. RAG بيلمع لمّا يكون عندك معرفة كبيرة، متغيّرة، وخاصة بيك.
الخطوة التالية
خُد 20 وثيقة من توثيقك الحقيقي، قسّمها لمقاطع، شغّل الكود اللي فوق، وجرّب 10 أسئلة فعلية من عملاءك. بُصّ على درجة التشابه للمقطع المسترجَع: لو أقل من 0.3 باستمرار، مشكلتك في التقطيع أو في نموذج التضمين، مش في الـ LLM. ابدأ من هنا قبل ما تبني أي حاجة أكبر.
المصادر
- Lewis et al., "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", NeurIPS 2020 — arXiv:2005.11401 (الورقة الأصلية لمصطلح RAG).
- Sentence-Transformers (SBERT) Documentation — sbert.net، وبطاقة نموذج
sentence-transformers/all-MiniLM-L6-v2على Hugging Face (تضمين 384 بُعد). - Facebook AI Similarity Search (FAISS) — github.com/facebookresearch/faiss (البحث عن أقرب المتجهات).
- OpenAI و Anthropic — توثيق حدود نافذة السياق للنماذج (context window).