يا جماعة الخير، السلام عليكم ورحمة الله.
بتذكر قبل فترة، كنا شغالين على مشروع لشركة محترمة، طلبوا منا نعملهم “مساعد ذكي” (Chatbot) يجاوب على أسئلة العملاء عن منتجاتهم وسياساتهم الداخلية. تحمسنا كثير، واستخدمنا واحد من أقوى النماذج اللغوية الكبيرة (LLM) وقتها. في البداية، الأمور كانت تبشر بالخير، النموذج كان لسانه “حلو” وبيعرف يحكي، لكن المصيبة بلشت تبين بعد كم يوم من الاختبار.
مرة عميل بيسأل عن سياسة الإرجاع لمنتج معين، والـ Chatbot بكل ثقة “بيفتي” من عنده وبحكيله: “طبعاً بتقدر ترجعه خلال 90 يوم وتحصل على كامل المبلغ نقداً!”. والمشكلة إنه سياسة الشركة الحقيقية هي 14 يوم فقط وللاستبدال مش للإرجاع النقدي. تخيلوا حجم الكارثة لو هالنظام طلع للعلن! صار النموذج “يهلوس” (Hallucinate) ويخترع معلومات من وحي الخيال، كأنه قاعد معنا على قهوة وبسولف من راسه. وقتها ضربت كف بكف وحكيت: “شو هالحكي الفاضي! هيك رح نخرب بيوت العالم!”.
هون كانت نقطة التحول. كان لازم نلاقي طريقة نلجم فيها هالجواد الجامح، نخليه يستعمل ذكاءه بس يلتزم بالحقائق والمعلومات اللي بنعطيه إياها. وهون دخل على الخط المنقذ: تقنية “التوليد المعزز بالاسترجاع” أو زي ما بنحب نسميها بالانجليزي، RAG.
ما هي “الهلوسة” في عالم الذكاء الاصطناعي؟ (وشو دخلها بالكنافة؟)
قبل ما نغوص في الحل، خلينا نفهم المشكلة. “الهلوسة” (Hallucination) في عالم الذكاء الاصطناعي هي لما النموذج اللغوي يولد معلومات تبدو منطقية ومقنعة، لكنها في الحقيقة خاطئة تماماً أو لا أساس لها من الصحة في المصدر المعطى.
تخيل معي إنك سألت حدا مش متذكر منيح طريقة عمل الكنافة النابلسية. بدل ما يحكيلك “والله ناسي”، ببلش يخترع من عنده: “أول إشي بتجيب العجينة وبتحط عليها شوكولاتة وكاتشب…”. الكلام مرتب وصياغته حلوة، بس النتيجة كارثية! هذا بالضبط اللي بتعمله النماذج اللغوية أحياناً. هي مصممة عشان تكمل النص وتولد كلام، فإذا ما عندها المعلومة الدقيقة، “بتألف” أقرب إشي منطقي بالنسبة إلها.
لماذا تهلوس النماذج اللغوية؟ (المشكلة مش من عندك)
السبب بسيط ومنطقي جداً. النماذج اللغوية الكبيرة، مثل GPT-4 وغيره، تم تدريبها على كمية هائلة من بيانات الإنترنت لغاية تاريخ معين. يعني معرفتها “مجمدة” في الزمن. هي ما بتعرف شو صار مبارح، وما عندها أي وصول لمعلوماتك الخاصة أو بيانات شركتك الداخلية.
فلما تسألها عن سياسة الإرجاع في شركتك (اللي مش موجودة على الإنترنت العام)، هي بتحاول تخمن أفضل إجابة بناءً على آلاف سياسات الإرجاع اللي قرأتها أثناء التدريب. والنتيجة؟ تخبيص وهلوسة.
الحل المنقذ: التوليد المعزز بالاسترجاع (RAG)
هنا يأتي دور الـ RAG ليقول للنموذج اللغوي: “على رسلك يا صاحبي! قبل ما تجاوب، تفضل هي شوية مستندات الها علاقة بالسؤال، اقرأها وبعدين جاوب”.
ببساطة، RAG هو أسلوب بيجمع بين قوتين: قوة النموذج اللغوي الهائلة في الفهم والتوليد، وقوة قواعد البيانات في البحث واسترجاع المعلومات الدقيقة. العملية بتمر بمرحلتين أساسيتين:
المرحلة الأولى: الفهرسة (ترتيب الدكان)
قبل ما نفتح الدكان للزباين (المستخدمين)، لازم نرتب البضاعة (المعلومات) على الرفوف بطريقة تسهل الوصول إليها. هاي المرحلة بنعملها مرة واحدة أو كل ما تتحدث بياناتنا.
- تحميل وتقسيم المستندات (Loading & Chunking): بنجيب كل مصادر المعرفة تبعتنا (ملفات PDF، صفحات وورد، محتوى موقع إلكتروني، إلخ) وبنقسمها لقطع صغيرة (Chunks). ليش؟ عشان النموذج يركز على الأجزاء ذات الصلة فقط، وعشان ما نتجاوز حدود الذاكرة (Context Window) تبعته.
- إنشاء التضمينات (Embeddings): هاي هي الخطوة السحرية. بناخذ كل قطعة نصية صغيرة وبنحولها لسلسلة من الأرقام اسمها “متجه” أو (Vector). هاي الأرقام بتمثل “معنى” النص. النصوص اللي الها معاني متقاربة، بتكون أرقامها (متجهاتها) قريبة من بعض في الفضاء الرياضي. تخيلها كإحداثيات على خريطة للمعاني.
- تخزين المتجهات: بنخزن هاي المتجهات مع النصوص الأصلية في قاعدة بيانات متخصصة اسمها “قاعدة بيانات المتجهات” (Vector Database). من أشهر الأمثلة عليها: Pinecone, ChromaDB, FAISS. هاي القاعدة مصممة خصيصاً للبحث السريع عن المتجهات المتقاربة.
المرحلة الثانية: الاسترجاع والتوليد (وقت الجد)
هاي المرحلة بتصير في كل مرة المستخدم بيسأل سؤال.
- سؤال المستخدم: المستخدم بيكتب سؤاله، مثلاً: “ما هي سياسة الإرجاع للمنتجات الإلكترونية؟”.
- تحويل السؤال لمتجه: بنستخدم نفس نموذج التضمين (Embedding model) عشان نحول سؤال المستخدم هو كمان لمتجه رقمي.
- البحث عن التشابه: بنروح على قاعدة بيانات المتجهات وبنحكيلها: “يا معلمة، أعطيني أكثر 3 أو 5 قطع نصية (Chunks) متجهاتهم قريبة من متجه السؤال هاد”. هاي هي عملية “الاسترجاع” (Retrieval).
- تعزيز السياق: الآن صار عنا سؤال المستخدم الأصلي + أهم القطع النصية اللي استرجعناها من مستنداتنا. بنحطهم كلهم في “سياق” (Context) واحد مرتب.
- التوليد: بنرسل هالسياق المعزز للنموذج اللغوي الكبير (LLM) وبنحكيله: “لو سمحت، جاوب على هذا السؤال فقط باستخدام المعلومات الموجودة في هذا السياق”.
وبهيك، بدل ما النموذج “يهلوس”، هو الآن بيقوم بعملية تلخيص واستنتاج بناءً على معلومات دقيقة وموثوقة إحنا زودناه فيها. صار زي الموظف الخبير اللي بيفتح ملف العميل قبل ما يجاوبه.
مثال عملي: لنبني نظام RAG بسيط مع Python
الحكي سهل، خلينا نشوف الأفعال. هي مثال بسيط جداً باستخدام مكتبة LangChain الشهيرة عشان نورجيكم المبدأ. رح نحتاج نثبت بعض المكتبات أول:
pip install langchain openai chromadb tiktoken
الآن، لنفترض عنا ملف نصي اسمه policy.txt فيه هاي الجملة:
سياسة الإرجاع في شركتنا هي 14 يوماً من تاريخ الشراء، بشرط أن يكون المنتج في حالته الأصلية. الإرجاع النقدي غير متاح، ولكن يمكن استبدال المنتج بقسيمة شراء.
وهذا هو الكود اللي بيطبق نظام RAG بسيط:
# أولاً: استيراد المكتبات اللازمة
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# ملاحظة: تأكد من وضع مفتاح OpenAI API الخاص بك في متغيرات البيئة
# export OPENAI_API_KEY="..."
# 1. تحميل وتقسيم المستند
loader = TextLoader("./policy.txt", encoding="utf-8")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=300, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
# 2. إنشاء التضمينات وتخزينها في قاعدة بيانات متجهات (ChromaDB في الذاكرة)
embeddings = OpenAIEmbeddings()
vector_store = Chroma.from_documents(texts, embeddings)
# 3. إعداد سلسلة الاسترجاع والسؤال
# هنا ننشئ "السلسلة" التي تربط كل الخطوات ببعضها
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff", # "stuff" هو أبسط نوع، يضع كل السياق في الطلب
retriever=vector_store.as_retriever()
)
# 4. طرح السؤال!
query = "هل يمكنني استعادة نقودي عند إرجاع منتج؟"
response = qa_chain.run(query)
print(response)
# المتوقع أن تكون الإجابة: "الإرجاع النقدي غير متاح، ولكن يمكن استبدال المنتج بقسيمة شراء."
شفتوا كيف؟ الكود بيعمل كل الخطوات اللي حكينا عنها: بيقرأ الملف، بيقسمه، بيعمله embeddings، بيخزنه، وبعدين بيستخدمه عشان يجاوب على سؤالنا بدقة.
نصائح من “الختيار” أبو عمر
بعد ما اشتغلنا على عشرات المشاريع باستخدام RAG، تعلمت كم شغلة على الطريق بحب أشارككم فيها:
- حجم القطعة (Chunk Size) فن مش علم: إذا كانت القطع صغيرة جداً، ممكن يضيع السياق. إذا كانت كبيرة جداً، ممكن يكون فيها معلومات كثيرة غير مهمة وتشتت النموذج. جرب أحجام مختلفة وشوف شو الأنسب لبياناتك. ابدأ بـ 500-1000 حرف مع تداخل (overlap) حوالي 10-20%.
- اختيار نموذج التضمين مهم: مش كل نماذج الـ Embeddings زي بعض. في نماذج أفضل للغات معينة أو لمجالات تقنية متخصصة. ابحث عن نماذج تدعم اللغة العربية بشكل جيد إذا كان محتواك عربي.
- لا تنسَ البيانات الوصفية (Metadata): لما تخزن القطع النصية في قاعدة البيانات، خزن معها معلومات إضافية مثل اسم الملف الأصلي، رقم الصفحة، أو تاريخ الإنشاء. هذا بساعدك بعدين عشان تذكر المصدر في إجابتك (Citations)، وهذا بيزيد الثقة بشكل كبير.
- التقييم هو كل شيء: كيف بتعرف إنه نظامك بتحسن؟ لازم تبني مجموعة أسئلة وأجوبة نموذجية (Golden dataset) وتقيّم أداء نظامك عليها باستمرار. هل يسترجع المستندات الصحيحة؟ هل الإجابة النهائية دقيقة؟
الخلاصة والزبدة
تقنية الـ RAG مش مجرد مصطلح تقني جديد، هي نقلة نوعية في كيفية تعاملنا مع النماذج اللغوية. هي الجسر اللي بيوصل بين عالم الذكاء الاصطناعي التوليدي الواسع، وعالم بياناتنا الخاصة والدقيقة. بفضلها، قدرنا نحول نماذجنا من “مبدعين مهلوسين” إلى “خبراء ملتزمين بالحقائق”.
نصيحتي الأخيرة لكل مطور أو مهتم بهذا المجال: لا تخاف من المصطلحات. ابدأ ببساطة. خذ ملف نصي واحد، طبق عليه المثال اللي حطيناه، وجرب بنفسك. لما تشوف النموذج بجاوب على سؤالك من معلوماتك الخاصة بدقة 100%، رح تشعر بلحظة سحرية. يلا يا شباب، ورجونا إبداعاتكم! 🚀