كيف أنقذنا نماذجنا اللغوية من هلوساتها باستخدام RAG: قصة من الخنادق البرمجية

يا جماعة الخير، السلام عليكم ورحمة الله. اسمي أبو عمر، مبرمج فلسطيني قضيت سنين عمري بين الأكواد والخوارزميات، وشفت العجب العجاب في عالم الذكاء الاصطناعي. اسمحولي اليوم أحكيلكم قصة صارت معي قبل فترة، قصة عن الإحباط والهلوسة والأمل اللي إجا على شكل ثلاث حروف: RAG.

كنا شغالين على مشروع طموح: بناء مساعد ذكي لمتجر إلكتروني كبير يبيع منتجات حرفية وتراثية. الفكرة كانت بسيطة، العميل يسأل عن أي منتج، والمساعد الذكي (اللي مبني على نموذج لغوي كبير – LLM) يجاوبه فوراً. في البداية، الأمور كانت “عال العال”. النموذج كان لطيفاً، كلامه منمق، وقدرته على توليد النصوص كانت مبهرة.

لكن المصيبة بدأت تظهر بعد أيام قليلة من الاختبار. سأل أحد المستخدمين: “ما هي سياسة الإرجاع للمنتجات المطرزة يدوياً؟”. جواب النموذج كان كارثياً: “يمكنكم إرجاع المنتجات المطرزة خلال 90 يوماً واسترداد كامل المبلغ مع هدية مجانية كاعتذار!”. طبعاً، سياسة الشركة الحقيقية هي 14 يوم فقط وبشروط معينة. وقتها حسيت الدنيا بتلف فيي، المدير “ولّعت معاه” وقال لي: “يا أبو عمر، شو هالحكي الفاضي؟ هادا رح يخرب بيتنا!”.

لم تكن هذه هي المشكلة الوحيدة. النموذج بدأ “يهلوس” (Hallucinate)، يخترع تفاصيل عن الحرفيين، يصف مواداً غير مستخدمة في المنتجات، بل وحتى أنه أعطى سعر منتج بـ 10 دولارات بينما سعره الحقيقي 150 دولاراً. كنا في جحيم من المعلومات الخاطئة، والنموذج اللي كان المفروض يكون مساعد ذكي، تحول لكابوس مُكلِف. وقتها، عرفت إن الاعتماد على “ذاكرة” النموذج وحدها هو وصفة للفشل. وهنا بدأت رحلتي مع المنقذ: RAG.

ما هي مشكلة النماذج اللغوية الكبيرة (LLMs) أصلاً؟

قبل ما ندخل في الحل، خلينا نفهم أصل المشكلة. النماذج اللغوية الكبيرة مثل سلسلة GPT وغيرها، هي رائعة جداً، لكن عندها مشكلتين أساسيتين:

  1. مشكلة الهلوسة (Hallucination): النموذج لا “يعرف” الحقيقة، بل هو بارع جداً في التنبؤ بالكلمة التالية في تسلسل الكلمات بناءً على البيانات الهائلة التي تدرب عليها. عندما لا يجد معلومة دقيقة في “ذاكرته” التدريبية، فإنه قد يخترع إجابة تبدو منطقية لغوياً ولكنها خاطئة تماماً واقعياً.
  2. مشكلة انقطاع المعرفة (Knowledge Cutoff): تدريب هذه النماذج عملية مكلفة ومعقدة، لذلك معرفتها تتوقف عند تاريخ معين (مثلاً، معرفة GPT-4 تتوقف عند نقطة معينة في الزمن). أي شيء يحدث بعد هذا التاريخ، أو أي معلومة خاصة بشركتك (مثل منتجاتك الجديدة أو سياساتك الداخلية)، هو ببساطة لا يعرف عنها شيئاً.

كنا نحاول حل هذه المشكلة عبر “هندسة الموجهات” (Prompt Engineering)، حيث كنا نكتب تعليمات معقدة جداً للنموذج مثل “أجب فقط بناءً على معرفتك الموثوقة ولا تخترع معلومات”. لكن هذا كان مثل محاولة إغلاق ثقب في سد بإصبعك، لم يكن حلاً جذرياً.

المنقذ: التوليد المعزز بالاسترجاع (RAG)

RAG هي اختصار لـ Retrieval-Augmented Generation. الفكرة عبقرية وبسيطة في نفس الوقت. بدلاً من أن نسأل النموذج اللغوي مباشرة ونعتمد على ذاكرته المحدودة والمحتمل أن تكون قديمة، نقوم بعملية من خطوتين:

  1. الاسترجاع (Retrieval): أولاً، نبحث في قاعدة بيانات خاصة بنا (تحتوي على وثائقنا، ملفاتنا، معلومات منتجاتنا، سياساتنا، إلخ) عن المعلومات الأكثر صلة بسؤال المستخدم.
  2. التوليد (Generation): ثانياً، نأخذ هذه المعلومات التي استرجعناها ونعطيها للنموذج اللغوي مع السؤال الأصلي، ونقول له: “يا محترم، استخدم هذه المعلومات فقط للإجابة على هذا السؤال”.

ببساطة، RAG يحوّل النموذج اللغوي من طالب يؤدي امتحاناً معتمداً على ذاكرته فقط، إلى طالب يؤدي نفس الامتحان ولكن مع “كتاب مفتوح” (Open Book) يحتوي على جميع الإجابات الصحيحة والمحدثة.

كيف يعمل RAG خطوة بخطوة؟

التطبيق العملي لـ RAG يتكون من مرحلتين رئيسيتين: مرحلة التجهيز (مرة واحدة)، ومرحلة الاستعلام (تتكرر مع كل سؤال).

المرحلة الأولى: تجهيز قاعدة المعرفة (Indexing)

هذه المرحلة نقوم بها مرة واحدة أو كلما أردنا تحديث معلوماتنا. الهدف هو تحويل وثائقنا (ملفات PDF، صفحات ويب، ملفات نصية) إلى صيغة قابلة للبحث السريع.

  1. تحميل البيانات (Loading): نقوم بتحميل جميع المستندات التي نريد أن “يتعلم” منها النموذج.
  2. التقطيع (Chunking): نقوم بتقطيع هذه المستندات الكبيرة إلى قطع صغيرة (chunks). هذا مهم جداً لأننا نريد أن نعطي النموذج فقط الأجزاء الأكثر صلة، وليس مستنداً كاملاً من 50 صفحة.
  3. التضمين (Embedding): هذه هي الخطوة السحرية. نستخدم نموذج تضمين (Embedding Model) لتحويل كل قطعة نصية إلى متجه رقمي (vector). يمكنك تخيل هذا المتجه كإحداثيات على خريطة ضخمة، حيث تكون النصوص ذات المعاني المتشابهة قريبة من بعضها البعض.
  4. التخزين (Storing): نقوم بتخزين هذه المتجهات النصية في قاعدة بيانات متخصصة تسمى “قاعدة بيانات المتجهات” (Vector Database) مثل ChromaDB, Pinecone, أو FAISS. هذه القاعدة هي مكتبتنا الرقمية التي سنبحث فيها.

المرحلة الثانية: الاسترجاع والتوليد (Retrieval & Generation)

هذه المرحلة تحدث في كل مرة يطرح فيها المستخدم سؤالاً.

  1. يصل سؤال المستخدم (مثلاً: “ما هي سياسة الإرجاع؟”).
  2. نقوم بتحويل هذا السؤال أيضاً إلى متجه رقمي باستخدام نفس نموذج التضمين.
  3. نستخدم هذا المتجه للبحث في قاعدة بيانات المتجهات عن القطع النصية (chunks) التي تتشابه معها (الأقرب إليها على الخريطة). هذه هي عملية “البحث الدلالي” (Semantic Search).
  4. نأخذ أفضل 3-5 قطع نصية تم استرجاعها.
  5. نقوم بإنشاء “موجه” (prompt) جديد يجمع بين السؤال الأصلي وهذه القطع المسترجعة. قد يبدو الموجه هكذا:


    السياق: [هنا نضع القطع النصية المسترجعة التي تحتوي على سياسة الإرجاع الحقيقية]

    السؤال: [هنا نضع سؤال المستخدم الأصلي]

    التعليمات: بناءً على السياق أعلاه فقط، أجب على السؤال.
  6. نرسل هذا الموجه المعزز إلى النموذج اللغوي الكبير.
  7. النموذج الآن لديه كل ما يحتاجه ليجيب بشكل دقيق وصحيح، فيقول: “بناءً على سياساتنا، يمكن إرجاع المنتجات خلال 14 يوماً من تاريخ الشراء بشرط أن تكون في حالتها الأصلية.”

وهكذا، قضينا على الهلوسة! أصبح النموذج مقيداً بالمعلومات الحقيقية التي زودناه بها.

لنضع أيدينا في الكود: مثال عملي باستخدام Python

الكلام النظري جميل، لكن “الشغل الصح” يظهر بالكود. إليكم مثال بسيط جداً باستخدام مكتبة LangChain الشهيرة مع OpenAI و ChromaDB كقاعدة بيانات متجهات تعمل في الذاكرة.


# أولاً، قم بتثبيت المكتبات اللازمة
# pip install langchain openai chromadb tiktoken

import os
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA

# ضع مفتاح OpenAI الخاص بك هنا
os.environ["OPENAI_API_KEY"] = "sk-..."

# --- 1. مرحلة التجهيز (Indexing) ---

# لنفترض أن هذا هو محتوى ملف سياسة الشركة
document_text = """
سياسة الإرجاع والاستبدال في متجر 'تراثنا'
- يمكن للعملاء إرجاع المنتجات خلال 14 يوماً من تاريخ استلام الطلب.
- يجب أن يكون المنتج في حالته الأصلية وغير مستخدم ومع العبوة الأصلية.
- المنتجات المطرزة يدوياً بشكل خاص حسب طلب العميل غير قابلة للإرجاع.
- لت initiating a return, please contact customer service at support@turathuna.com.
- تكاليف الشحن للإرجاع تقع على عاتق العميل.
"""

# تقطيع النص إلى قطع صغيرة
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
texts = text_splitter.split_text(document_text)

# إنشاء نموذج التضمين (Embeddings)
embeddings = OpenAIEmbeddings()

# إنشاء قاعدة بيانات المتجهات وتخزين القطع النصية فيها
# Chroma.from_texts ستقوم بعملية التضمين والتخزين معاً
vector_db = Chroma.from_texts(texts, embeddings)

# --- 2. مرحلة الاستعلام (Querying) ---

# إعداد النموذج اللغوي الكبير
llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo")

# إعداد "سلسلة" RAG. هذه السلسلة تربط كل شيء معاً:
# - llm: النموذج الذي سيولّد الإجابة
# - chain_type="stuff": الطريقة التي سيتم بها تجميع القطع في الموجه
# - retriever: الكائن المسؤول عن البحث في قاعدة البيانات (vector_db)
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vector_db.as_retriever()
)

# الآن، لنسأل نفس السؤال الذي سبب لنا المشكلة
query = "كم يوماً لدي لإرجاع منتج مطرز؟"
response = qa_chain.run(query)

print("السؤال:", query)
print("الإجابة الصحيحة من RAG:", response)

# لنجرب سؤالاً آخر
query_2 = "هل يمكنني إرجاع فستان تم تطريزه خصيصاً لي؟"
response_2 = qa_chain.run(query_2)

print("nالسؤال:", query_2)
print("الإجابة الصحيحة من RAG:", response_2)

عند تشغيل هذا الكود، سترى أن الإجابات دقيقة تماماً وتعتمد حصراً على النص الذي زودناه به، لا مجال للهلوسة أو اختراع سياسة 90 يوماً المجنونة تلك!

نصائح من خبرة أبو عمر لتحقيق أفضل النتائج مع RAG

بعد العمل على عدة مشاريع باستخدام RAG، جمعت لكم بعض النصائح العملية من أرض الواقع:

  • استراتيجية التقطيع (Chunking Strategy): حجم القطعة (chunk size) وتداخلها (overlap) يؤثران بشكل كبير على الجودة. لا يوجد رقم سحري واحد، عليك التجربة. ابدأ بـ `chunk_size=1000` و `chunk_overlap=100` كنقطة انطلاق جيدة. التقطيع المتكرر (Recursive Character Splitter) ممتاز لأنه يحاول الحفاظ على الفقرات والجمل متماسكة.
  • جودة البيانات هي الأساس: تذكروا يا جماعة، “garbage in, garbage out”. إذا كانت مستنداتك الأصلية فوضوية أو تحتوي على معلومات خاطئة، فإن RAG سيقدم إجابات خاطئة ولكن بثقة! نظّف بياناتك أولاً.
  • استخدم بيانات وصفية (Metadata): عند تخزين القطع، أضف معها بيانات وصفية مثل (اسم الملف المصدر، رقم الصفحة، تاريخ الإنشاء). هذا يساعدك لاحقاً على تتبع مصدر المعلومة وعرضه للمستخدم، مما يزيد من الشفافية والثقة.
  • فكر في البحث الهجين (Hybrid Search): البحث الدلالي (Semantic) رائع لفهم المعنى، لكن أحياناً البحث التقليدي بالكلمات المفتاحية (Keyword Search) يكون أفضل للمصطلحات الدقيقة أو أسماء المنتجات. الجمع بينهما في نظام “بحث هجين” يعطي أفضل النتائج.
  • إعادة الترتيب (Re-ranking): بدلاً من أخذ أفضل 5 قطع مباشرة من قاعدة البيانات، يمكنك استرجاع أفضل 20 قطعة، ثم استخدام نموذج أصغر وأسرع (أو خوارزمية أخرى) لإعادة ترتيبها واختيار أفضل 3-5 قطع لإرسالها للنموذج اللغوي الكبير. هذا يحسن الدقة ويقلل من “الضوضاء”.

الخلاصة: RAG ليس عصا سحرية، ولكنه أفضل أداة في جعبتنا حالياً 🚀

في النهاية يا إخوان، RAG لم يحل كل مشاكل الذكاء الاصطناعي، ولكنه قدم حلاً عملياً وفعالاً لواحدة من أكبر مشاكله: الثقة والدقة. لقد حوّل النماذج اللغوية من “عارف بكل شيء” قد يكذب، إلى “مساعد خبير” يبني إجاباته على حقائق موثقة يمكننا التحكم بها وتحديثها بسهولة.

بالنسبة لمشروعي، بعد تطبيق RAG، تحول المساعد الذكي من مصدر قلق إلى أداة قوية جداً زادت من رضا العملاء وقللت العبء على فريق خدمة العملاء. لقد أنقذنا من جحيم المعلومات الخاطئة وفتح لنا الباب لبناء تطبيقات ذكاء اصطناعي أكثر أماناً وفائدة.

نصيحتي لكم: لا تخافوا من هلوسة النماذج، بل تعلموا كيف تروضونها. RAG هو اللجام الذي تحتاجه لتوجيه هذه القوة الهائلة. شدّوا حيلكم، تعلموا، وجربوا… فالمستقبل الذي نبنيه يعتمد على قدرتنا على استخدام هذه الأدوات بحكمة ومسؤولية. يلا، بالتوفيق! 💪

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

​معمارية البرمجيات

كانت ذاكرة فريقنا هي الوثيقة الوحيدة: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم التغييرات المرعبة؟

أشارككم قصة من قلب المعركة البرمجية، كيف كاد مشروعنا أن ينهار بسبب قرار قديم لم يتذكره أحد. وكيف أصبحت "سجلات القرارات المعمارية" (ADRs) هي ذاكرتنا...

5 مايو، 2026 قراءة المزيد
تسويق رقمي

كانت ميزانيتنا التسويقية تحترق: كيف أنقذتنا ‘نماذج الإحالة’ من جحيم تخمين العائد على الاستثمار؟

أتذكر جيداً تلك الاجتماعات المحمومة، حيث كانت الأرقام تتراقص على الشاشة والميزانية التسويقية تتآكل دون أن نعرف أين يذهب كل دولار. في هذه المقالة، أشارككم...

5 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كانت تفاعلات المستخدم صامتة وميتة: كيف أنقذتنا ‘التفاعلات الدقيقة’ (Microinteractions) من جحيم التجربة المربكة؟

تطبيقنا كان يعمل، لكنه كان بلا روح. في هذه المقالة، أسرد لكم قصة كيف حولنا تجربة مستخدم مربكة وميتة إلى تجربة ممتعة وحيوية باستخدام قوة...

5 مايو، 2026 قراءة المزيد
الشبكات والـ APIs

كانت الشبكة السيئة تضاعف طلبات الشراء: كيف أنقذنا مفهوم “العطالة” (Idempotency) من جحيم الكوارث المالية؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، حيث كادت شبكة إنترنت سيئة أن تسبب كارثة مالية لعملائنا. سنغوص في مفهوم "العطالة" (Idempotency) وكيف يمكن لتطبيقه...

5 مايو، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

كانت سيرتي الذاتية تصرخ في الفراغ: كيف أنقذت ‘العلامة التجارية الشخصية المتخصصة’ طلبي من الثقب الأسود لأنظمة ATS؟

كنت أرسل عشرات السير الذاتية دون أي رد، وكأنها تتبخر في الهواء. في هذه المقالة، أسرد لكم قصتي مع أنظمة تتبع المتقدمين (ATS) وكيف كان...

5 مايو، 2026 قراءة المزيد
البودكاست