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

يا جماعة الخير، السلام عليكم ورحمة الله.

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

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

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

المشكلة الحقيقية: النماذج اللغوية تعيش في فقاعة زمنية

قبل ما ندخل في تفاصيل الحل، خلينا نفهم أصل المشكلة. النماذج اللغوية الكبيرة (LLMs) مثل GPT-4 أو Llama 3، هي عقول رقمية جبارة، لكنها مثل أي عقل، معرفتها محدودة بالبيانات التي تدربت عليها.

  • معرفة مجمدة (Frozen Knowledge): يتم تدريب هذه النماذج على كميات هائلة من البيانات من الإنترنت والكتب حتى تاريخ معين (مثلاً، سبتمبر 2021 لبعض إصدارات GPT). أي شيء يحدث بعد هذا التاريخ هو بالنسبة لها أرض مجهولة.
  • غياب السياق الخاص (Lack of Specific Context): النموذج لا يعرف شيئًا عن مستندات شركتك الداخلية، أو قاعدة بيانات منتجاتك، أو رسائل بريدك الإلكتروني. هذه بيانات خاصة ليست جزءًا من تدريبه العام.

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

المنقذ RAG: جسر بين الماضي والحاضر

هنا يأتي دور “التوليد المعزز بالاسترجاع” أو Retrieval-Augmented Generation (RAG). الفكرة عبقرية في بساطتها. بدلاً من إعادة تدريب النموذج بالكامل (وهو أمر مكلف جدًا ويستغرق شهورًا)، نقوم بتزويده بالمعلومات الصحيحة والمحدثة “لحظة بلحظة” عند طرح السؤال.

تخيل الأمر كأنه امتحان كتاب مفتوح (Open-book exam). النموذج هو الطالب الذكي جدًا، وبياناتك الخاصة (المستندات، قواعد البيانات) هي الكتاب المسموح له بالاطلاع عليه قبل الإجابة.

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

يمكن تقسيم عملية RAG إلى مرحلتين رئيسيتين: مرحلة الإعداد (التكشيف) ومرحلة الاستعلام (الإجابة).

المرحلة الأولى: بناء قاعدة المعرفة (Indexing)

هذه المرحلة نقوم بها مرة واحدة (أو كلما تغيرت بياناتنا)، وهي بمثابة تجهيز “المكتبة” التي سيقرأ منها النموذج.

  1. تقطيع البيانات (Chunking): نقوم بأخذ مستنداتنا الكبيرة (ملفات PDF، Word، صفحات ويب) وتقسيمها إلى أجزاء أو “قطع” صغيرة ومنطقية. هذا مهم لأننا لا نريد إغراق النموذج بمستند كامل من 50 صفحة للإجابة على سؤال بسيط.
  2. إنشاء المتجهات (Embeddings): هذه هي الخطوة السحرية. نستخدم نموذجًا متخصصًا لتحويل كل “قطعة” نصية إلى تمثيل رياضي رقمي يسمى “متجه” أو Vector. هذا المتجه يلتقط المعنى الدلالي للنص. النصوص ذات المعاني المتشابهة يكون لها متجهات متقاربة في الفضاء الرياضي.
  3. التخزين في قاعدة بيانات متجهة (Vector Database): نقوم بتخزين كل هذه المتجهات النصية في قاعدة بيانات متخصصة تسمى Vector Database (مثل Pinecone, ChromaDB, Weaviate). وظيفتها هي البحث بسرعة فائقة عن المتجهات الأكثر تشابهًا مع متجه معين.

المرحلة الثانية: دورة حياة الاستعلام (Query Lifecycle)

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

  1. استعلام المستخدم: المستخدم يكتب سؤاله، مثلاً: “ما هي سياسة العمل عن بعد الجديدة؟”.
  2. تحويل السؤال إلى متجه: نقوم بتحويل سؤال المستخدم إلى متجه بنفس الطريقة التي حولنا بها قطع المستندات.
  3. الاسترجاع (Retrieve): نأخذ متجه السؤال ونبحث به في قاعدة البيانات المتجهة عن أكثر القطع النصية (Chunks) تشابهًا في المعنى. قاعدة البيانات سترجع لنا، على سبيل المثال, أفضل 5 قطع نصية تتحدث عن سياسات العمل.
  4. التعزيز (Augment): الآن نأخذ هذه القطع النصية المسترجعة ونقوم ببناء “موجه” (Prompt) جديد ومحسن. يبدو الموجه الجديد كالتالي:

    “أنت مساعد خبير. أجب على سؤال المستخدم التالي بناءً على السياق المرفق فقط. إذا كانت الإجابة غير موجودة في السياق، قل بوضوح ‘لا أملك معلومات كافية للإجابة’.

    السياق:
    […نص القطعة الأولى عن العمل عن بعد…]
    […نص القطعة الثانية عن ساعات العمل المرنة…]

    سؤال المستخدم:
    ما هي سياسة العمل عن بعد الجديدة؟”

  5. التوليد (Generate): نرسل هذا الموجه المعزز إلى النموذج اللغوي الكبير. الآن، النموذج لديه كل المعلومات الصحيحة والمحدثة أمامه مباشرة. سيقوم بتوليد إجابة دقيقة ومبنية على الحقائق التي قدمناها له، وليس على ذاكرته القديمة.

وهكذا، حولنا النموذج من “مهلوس” إلى باحث دقيق ومساعد فعال. ✅

مثال عملي بالكود: لنوسخ أيدينا قليلاً

الحكي النظري جميل، لكن خلينا نشوف مثال عملي بسيط باستخدام لغة Python ومكتبة LangChain الشهيرة، التي تبسط عملية بناء تطبيقات RAG.

في هذا المثال، سنفترض أن لدينا ملف نصي بسيط `policy.txt` يحتوي على سياسة الشركة.


# policy.txt
# سياسة الإجازات لعام 2024
# يحق لكل موظف بدوام كامل الحصول على 21 يوم إجازة سنوية مدفوعة الأجر.
# يمكن ترحيل 5 أيام كحد أقصى إلى العام التالي.
# يجب تقديم طلبات الإجازة قبل أسبوعين على الأقل.

# --- الكود بلغة بايثون ---

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

from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, OpenAI
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA

# 1. تحميل وتقطيع المستند
loader = TextLoader("policy.txt")
documents = loader.load()

text_splitter = CharacterTextSplitter(chunk_size=300, chunk_overlap=0)
texts = text_splitter.split_documents(documents)

# 2. إنشاء المتجهات وتخزينها في قاعدة بيانات متجهة (هنا نستخدم ChromaDB كملف محلي)
# تحتاج إلى مفتاح API من OpenAI
embeddings = OpenAIEmbeddings(openai_api_key="YOUR_OPENAI_API_KEY")
vector_db = Chroma.from_documents(texts, embeddings)

# 3. إعداد سلسلة الاسترجاع والإجابة
# هنا نطلب منه استخدام قاعدة البيانات المتجهة كمسترجع للمعلومات
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(openai_api_key="YOUR_OPENAI_API_KEY"),
    chain_type="stuff", # "stuff" تعني وضع كل القطع المسترجعة في الموجه
    retriever=vector_db.as_retriever()
)

# 4. طرح الأسئلة!
question1 = "كم عدد أيام الإجازة السنوية؟"
answer1 = qa_chain.invoke(question1)
print(f"سؤال: {question1}")
print(f"جواب: {answer1['result']}")

question2 = "هل يمكن ترحيل الإجازات؟"
answer2 = qa_chain.invoke(question2)
print(f"سؤال: {question2}")
print(f"جواب: {answer2['result']}")

# لو سألنا سؤال خارج السياق
question3 = "ما هو لون شعار الشركة؟"
answer3 = qa_chain.invoke(question3)
print(f"سؤال: {question3}")
print(f"جواب: {answer3['result']}") # على الأغلب سيقول أنه لا يعرف

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

نصائح من خبرة أبو عمر

بعد شهور من العمل على أنظمة RAG، تعلمت بعض الدروس بالطريقة الصعبة. إليكم بعض النصائح العملية:

  • فن التقطيع (Chunking): حجم القطع النصية وتداخلها (overlap) يؤثر بشكل كبير على جودة النتائج. قطع صغيرة جدًا قد تفقد السياق، وقطع كبيرة جدًا قد تشتت النموذج. جرب أحجامًا مختلفة (مثلاً 500 حرف مع تداخل 50 حرف) حتى تجد الأفضل لبياناتك.
  • المسترجع هو الملك (Retriever is King): جودة الإجابة النهائية تعتمد 90% على جودة ما تم استرجاعه. قبل أن تلوم النموذج اللغوي، اختبر مرحلة الاسترجاع وحدها. هل عند البحث عن “سياسة الإجازات”، يتم بالفعل استرجاع القطع النصية الصحيحة؟ إذا لا، فالمشكلة هنا.
  • هندسة الموجهات لا تزال مهمة: الطريقة التي تصيغ بها الموجه المعزز (Augmented Prompt) مهمة جدًا. إضافة تعليمات واضحة مثل “أجب من السياق فقط” تمنع النموذج من الاعتماد على ذاكرته القديمة.
  • لا تنس البيانات الوصفية (Metadata): عند تخزين المتجهات، قم بتخزين بيانات وصفية معها، مثل اسم الملف ورقم الصفحة. هذا يسمح لك لاحقًا بعرض المصادر التي اعتمد عليها النموذج في إجابته، مما يزيد من ثقة المستخدم.

الخلاصة: RAG ليس حلاً سحريًا، بل هو الأداة الصحيحة

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

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

فلا تخف من “هلوسة” النماذج، بل تعلم كيف تمنحها “كتابًا مفتوحًا” لتصبح أكثر ذكاءً وفائدة. ابدأ صغيرًا، جرب، واجعل بياناتك تتحدث. 💡

أبو عمر

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

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

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

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

آخر المدونات

خوارزميات

كانت قاعدة بياناتنا تستنزفها الأشباح: كيف أنقذنا ‘مرشح بلوم’ (Bloom Filter) من جحيم الاستعلامات؟

أشارككم قصة حقيقية من قلب المعركة التقنية، كيف كانت استعلامات عن بيانات غير موجودة "كالأشباح" تخنق قاعدة بياناتنا، وكيف كانت خوارزمية احتمالية بسيطة تدعى "مرشح...

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

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

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

20 مايو، 2026 قراءة المزيد
برمجة وقواعد بيانات

كانت تطبيقاتنا تمطر قاعدة البيانات بالاستعلامات: كيف أنقذنا ‘التحميل الجشع’ (Eager Loading) من جحيم مشكلة N+1؟

في هذه المقالة، أشارككم قصة حقيقية عن كيفية تسبب مشكلة N+1 بكارثة أداء في أحد مشاريعنا، وكيف كان "التحميل الجشع" (Eager Loading) هو طوق النجاة....

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

خدماتنا كانت تتحدث بلغة JSON بطيئة: كيف أنقذنا gRPC من جحيم الاتصال غير الفعال بين الخدمات المصغرة؟

في هذه المقالة، يشارك أبو عمر تجربته الشخصية في الانتقال من REST/JSON إلى gRPC لتحسين أداء الاتصال بين الخدمات المصغرة. استكشف معنا المشاكل الكامنة في...

19 مايو، 2026 قراءة المزيد
الحوسبة السحابية

كانت فاتورتنا السحابية لغزاً شهرياً: كيف أنقذتنا ‘علامات تخصيص التكلفة’ من جحيم الإنفاق المجهول؟

هل تواجهون فاتورة سحابية متضخمة وغامضة كل شهر؟ في هذه المقالة، أشارككم تجربتي كـ "أبو عمر" في ترويض وحش التكاليف المجهولة باستخدام أداة بسيطة وقوية:...

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

سيرتي الذاتية في سلة المهملات الرقمية: كيف هزمتُ روبوتات التوظيف (ATS) بهندسة الكلمات المفتاحية

كانت طلباتي الوظيفية تذهب إلى ثقب أسود رقمي دون أي رد. في هذه المقالة، أسرد لكم قصتي مع أنظمة تتبع المتقدمين (ATS) وكيف أنقذتني هندسة...

19 مايو، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

كانت طلبات المستخدمين تُجمّد تطبيقنا: كيف أنقذتنا ‘طوابير الرسائل’ (Message Queues) من جحيم المعالجة المتزامنة؟

أشارككم قصة حقيقية عن اليوم الذي كاد فيه تطبيقنا أن ينهار تحت ضغط المستخدمين، وكيف كانت "طوابير الرسائل" (Message Queues) هي طوق النجاة. اكتشفوا معنا...

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