الـ RAG بالعربي: إزاي تخلي الـ AI يجاوب من بياناتك بدل ما يخترع
لو الـ chatbot بتاعك بيخترع إجابات مش موجودة في وثائقك، المشكلة مش في الموديل — المشكلة إنه بيجاوب من ذاكرته الداخلية. الحل اسمه RAG: نديله البيانات اللي محتاجها وقت السؤال بالظبط، فيرد من مصدر حقيقي بدل ما يهلوس.
المشكلة باختصار
نموذج زي GPT-4 أو Claude اتدرّب على بيانات الإنترنت لحد تاريخ معين. لما تسأله عن وثيقة داخلية في شركتك، أو مقال نزل الأسبوع الفات، أو منتج جديد — هو مش عارف حاجة. لو سألته بالعافية، هيخترعلك إجابة تبدو منطقية بس غلط. ده اسمه hallucination، وهو السبب رقم واحد اللي بيخلي مشاريع الـ AI تفشل في production.
الحل التقليدي كان fine-tuning: تاخد الموديل وتدرّبه من جديد على بياناتك. التكلفة: آلاف الدولارات، ساعات تدريب، وكل ما البيانات تتغير تعيد التدريب. مش عملي لأغلب الشركات.
RAG بمثال واضح للمبتدئ
تخيّل إنك داخل امتحان مفتوح الكتاب. السؤال بيقول: "إيه سياسة الإجازات في الشركة؟". أنت مش لازم تحفظ اللائحة من قلبك؛ كل اللي بتعمله:
- بتفتح ملف "لائحة الموارد البشرية".
- بتستخدم الفهرس أو Ctrl+F علشان توصل لقسم "الإجازات".
- بتقرأ الفقرتين الخاصين بالسؤال.
- بتكتب الإجابة بكلامك بناءً على اللي قريته.
RAG بيعمل نفس العملية دي بالظبط، لكن آليًا. الـ LLM هو الطالب، قاعدة البيانات هي الكتاب، ومحرك البحث المتجهي هو الفهرس.
التعريف العلمي الدقيق
RAG اختصار لـ Retrieval Augmented Generation. هي معمارية بتدمج بين نوعين من الأنظمة: نظام استرجاع (retriever) ونظام توليد (generator). البايبلاين بالظبط:
- Indexing: تقسيم وثائقك إلى قطع صغيرة (chunks)، حساب embedding لكل قطعة، وتخزينها في قاعدة بيانات متجهية (Pinecone، Weaviate، أو pgvector داخل PostgreSQL).
- Retrieval: عند وصول سؤال، بنحوّله لـ embedding وبنجيب أقرب k قطعة له (غالبًا k من 3 إلى 8).
- Augmentation: بنبني برومبت يحط القطع دي كـ context قبل السؤال.
- Generation: بنبعت البرومبت المدموج للـ LLM ليولّد إجابة مبنية على الـ context المسترجع.
الافتراض اللي بيشتغل عليه النظام: الإجابة الصحيحة موجودة فعلاً في وثائقك، والمهمة هي إنك توصلها للموديل في الوقت المناسب بدون ما تعيد تدريبه.
إزاي تبنيه فعلاً — كود Python شغّال
المثال ده بيستخدم Anthropic للتوليد و OpenAI للـ embeddings مع قاعدة بيانات بدائية في الذاكرة. شغّال كما هو لو عندك الـ API keys:
import anthropic
from openai import OpenAI
import numpy as np
oa = OpenAI()
anth = anthropic.Anthropic()
documents = [
"سياسة الإجازات: كل موظف يحصل على 21 يوم إجازة سنوية مدفوعة.",
"ساعات العمل: من 9 صباحًا حتى 5 مساءً، الأحد إلى الخميس.",
"الرواتب: تُصرف في آخر يوم عمل من كل شهر.",
"التأمين الصحي: يغطي الموظف وأسرته المباشرة بحد 50 ألف جنيه سنويًا.",
]
def embed(text):
r = oa.embeddings.create(model="text-embedding-3-small", input=text)
return np.array(r.data[0].embedding)
doc_vectors = [embed(d) for d in documents]
def retrieve(question, k=2):
q = embed(question)
scores = [np.dot(q, v) for v in doc_vectors]
top = np.argsort(scores)[-k:][::-1]
return [documents[i] for i in top]
def answer(question):
context = "\n".join(retrieve(question))
msg = anth.messages.create(
model="claude-sonnet-4-6",
max_tokens=500,
messages=[{
"role": "user",
"content": f"جاوب باستخدام السياق فقط:\n\n{context}\n\nالسؤال: {question}"
}]
)
return msg.content[0].text
print(answer("كام يوم إجازة في السنة؟"))
# الناتج المتوقع: حسب السياسة، كل موظف يحصل على 21 يوم إجازة سنوية مدفوعة.