هذا المقال يتطلب: مستوى مبتدئ
لو عايز ChatGPT يجاوبك من ملفات شركتك أو من PDFs مش موجودة في تدريبه، مش لازم تدرّب موديل من الصفر. فيه طريقة اسمها RAG بتخليك تعمل ده في يومين شغل، بتكلفة أقل من 50 دولار شهريًا للتطبيقات الصغيرة، ودقة بترفع بنسبة 60% على الأقل مقارنة بسؤال الموديل لوحده.
RAG بالعربي: الطريقة اللي بتخلي AI يفهم بياناتك الخاصة
المشكلة باختصار
لو سألت ChatGPT "إيه سياسة الإجازات في شركتي؟" مش هيعرف يجاوب. الموديل اتدرّب على الإنترنت، مش على PDFs الشركة. لو حاولت تحط كل ملفات الشركة في الـ prompt، هتقابل مشكلتين:
- الـ context window محدود (200K توكن في Claude، 128K في GPT-4o، أقل في موديلات تانية).
- التكلفة بتفرقع. كل سؤال هيكلّفك دولارات بدل سنتات لأنك بتبعت كل الكتاب علشان تجيب جملة.
مثال بسيط جدًا قبل التعريف العلمي
تخيّل عندك مكتبة فيها 10 آلاف كتاب. عميل دخل سألك "فين كتاب الطبخ المغربي؟". هتعمل إيه؟
- لو روحت بتقرأ كل الـ 10 آلاف كتاب علشان تجاوب → ده غباء صريح. وده بالظبط اللي بيحصل لو حطّيت كل ملفاتك في prompt.
- المنطقي إنك تروح للفهرس، تجيب 3 كتب فيها "طبخ مغربي"، وتقدّمهم للعميل يقرأ منهم.
RAG بيشتغل بنفس الفكرة بالظبط، بس مع AI:
- الـ AI بيدوّر في "فهرس" ذكي للملفات بدل ما يقرأها كلها.
- بيجيب أهم 3 لـ 5 قطع نص متعلقة بالسؤال.
- بيبعتهم للموديل مع السؤال كـ context.
- الموديل بيرد بناءً على القطع دي بس، مش من ذاكرته العامة.
التعريف العلمي الدقيق
RAG اختصار لـ Retrieval-Augmented Generation. هي معمارية بتجمع خطوتين منفصلتين:
- Retrieval: البحث عن أجزاء نص متعلقة بالسؤال من قاعدة بيانات خارجية، مش من تدريب الموديل.
- Generation: استخدام الموديل اللغوي (LLM) لتوليد إجابة بناءً على النص اللي اتجاب من خطوة الـ retrieval.
المعمارية اقترحها Lewis et al. في ورقة Facebook AI سنة 2020. الفكرة الأساسية إن الموديل مش لازم "يحفظ" المعرفة، يكفي إنه "يقرأ" المعرفة الصحيحة وقت السؤال.
إزاي RAG بيشتغل خطوة بخطوة
عندك مرحلتين، الأولى بتعملها مرة واحدة، والتانية مع كل سؤال.
المرحلة الأولى: الفهرسة (one-time)
- تقسّم ملفاتك لقطع صغيرة (chunks) كل واحدة بين 200 و 500 كلمة.
- كل قطعة بتحوّلها لـ embedding (متجه أرقام بيمثّل المعنى). متجه واحد عادة بين 384 و 1536 رقم.
- تخزّن المتجهات دي في قاعدة بيانات مخصصة اسمها Vector Database، زي Pinecone أو Qdrant أو Chroma.
المرحلة الثانية: الرد (per-question)
- السؤال بيتحوّل لـ embedding بنفس الطريقة.
- تدوّر في الـ Vector DB عن أقرب 3 لـ 5 chunks للسؤال (cosine similarity).
- تبعت السؤال + الـ chunks دي للـ LLM في prompt واحد.
- الـ LLM يولّد الإجابة من الـ chunks بس.
كود Python شغّال (RAG في 30 سطر)
المثال ده بيستخدم sentence-transformers للـ embeddings و numpy للبحث، علشان نفهم الفكرة بدون تعقيد Vector DB. للإنتاج استخدم Pinecone أو Qdrant.
import anthropic
from sentence_transformers import SentenceTransformer
import numpy as np
# 1. الفهرسة (مرة واحدة)
embedder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
documents = [
"سياسة الإجازات: كل موظف يستحق 21 يوم إجازة سنوية مدفوعة الأجر.",
"ساعات العمل: من 9 صباحًا حتى 5 مساءً مع ساعة استراحة للغداء.",
"العمل عن بُعد: مسموح يومين في الأسبوع لمن قضى 3 شهور في الشركة.",
"التأمين الصحي: التأمين يشمل الموظف وزوجه وأطفاله حتى سن 18.",
"إجازة الأمومة: 4 شهور مدفوعة الأجر بالكامل.",
]
doc_embeddings = embedder.encode(documents)
def ask_rag(question: str, top_k: int = 3) -> str:
# 2. ابحث عن أقرب chunks
q_embedding = embedder.encode([question])[0]
similarities = np.dot(doc_embeddings, q_embedding)
top_indices = np.argsort(similarities)[-top_k:][::-1]
context = "\n".join(documents[i] for i in top_indices)
# 3. اسأل الموديل بـ context محدود
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=300,
messages=[{
"role": "user",
"content": (
"بناءً على المعلومات دي بس، جاوب باختصار:\n"
f"{context}\n\n"
f"السؤال: {question}"
)
}]
)
return response.content[0].text
print(ask_rag("كم يوم إجازة سنوية أستحقها؟"))
# الإجابة المتوقعة: 21 يوم إجازة سنوية مدفوعة الأجر.
أرقام حقيقية من تطبيق صغير
هذا الشرح مبني على فرضية إن عندك قاعدة معرفة بين 100 و 10 آلاف صفحة، وعدد أسئلة يومية ≤ 5000. لو فوق كده، الأرقام بتختلف:
- تكلفة الـ embeddings مرة واحدة: ~$0.13 لكل مليون توكن (OpenAI text-embedding-3-small).
- تكلفة Pinecone Starter: $0 لأول مليون متجه، بعدها ~$70 شهريًا.
- زمن الاستجابة الإضافي: 200 لـ 500 ms على البحث في الـ Vector DB.
- تقليل الـ hallucinations: من 27% لـ 8% حسب قياسات Anthropic على Contextual Retrieval.
الـ trade-offs بصراحة
كل قرار له ثمن. خلّي بالك من اللي بتكسبه واللي بتخسره:
- بتكسب: إجابات من بياناتك الفعلية، تحديث المعرفة بإضافة chunks بدون تدريب، انخفاض كبير في الـ hallucinations.
- بتخسر: زمن استجابة إضافي 200-500 ms، تكلفة بنية تحتية ~$30 لـ $100 شهريًا، ووقت كبير في تجهيز الـ chunks بشكل صح. chunk size غلط = نتايج وحشة جدًا.
متى لا تستخدم RAG
- لو معرفتك ثابتة وصغيرة (أقل من 10 صفحات) → حطها في system prompt مع Prompt Caching، أرخص وأسرع.
- لو المهمة تحليل معقّد مش استرجاع معلومة → fine-tuning أنسب من RAG.
- لو بياناتك بتتغيّر كل ثانية (real-time stock prices مثلاً) → RAG هيتأخر في الـ indexing، استخدم function calling مباشر للـ API.
- لو في requirement أن الموديل ميشوفش الـ context كله (privacy)، RAG مش مناسب لأن chunks بتروح للـ LLM.
الخطوة التالية
اعمل النهاردة proof of concept بـ 10 ملفات بس. استخدم LlamaIndex أو LangChain علشان تختصر الكود لـ 10 سطور بدل 30. لو لقيت الإجابات وحشة، 90% احتمال إن المشكلة في chunk size أو في embedding model عربي مش كويس، مش في الـ LLM. جرّب موديل intfloat/multilingual-e5-large فهو من أفضل الموديلات للعربية حاليًا.
المصادر
- Lewis, P. et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. arXiv:2005.11401.
- Anthropic Engineering Blog (2024). Introducing Contextual Retrieval.
- Pinecone Learning Center. What is Retrieval Augmented Generation (RAG)?
- OpenAI Pricing Page (2026). Embeddings models pricing.
- Hugging Face MTEB Leaderboard. Multilingual embedding models benchmark.