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

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

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

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

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

ما هي “الهلوسة” في عالم الذكاء الاصطناعي؟

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

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

محاولاتنا الأولى الفاشلة: الضبط الدقيق (Fine-Tuning) ليس الحل دائمًا

أول ردة فعل طبيعية لأي مبرمج لما يواجه هالمشكلة هي: “خلينا نعمل Fine-Tuning للنموذج”. وهذا بالضبط اللي عملناه. جمعنا كل مستندات الشركة، الأسئلة الشائعة، والأدلة الفنية، وقمنا بعملية ضبط دقيق للنموذج الأساسي على بياناتنا الخاصة.

النتيجة؟ تحسنت الأمور قليلًا. صار النموذج يتكلم بـ “لهجة” الشركة ويعرف أسماء المنتجات. لكن الهلوسة لم تختفِ، بل صارت أخطر! أصبح النموذج يهلوس بمعلومات تبدو وكأنها من صلب منتجاتنا، مما زاد من صعوبة اكتشاف الخطأ. اكتشفنا أن الضبط الدقيق له حدوده:

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

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

هنا دخل RAG على الخط. الفكرة اللي بيقوم عليها RAG عبقرية في بساطتها. بدلًا من أن نطلب من النموذج أن يكون “موسوعة حافظة كل شيء عن ظهر قلب”، قررنا أن نعامله كـ “باحث ذكي” ونعطيه “امتحان كتاب مفتوح” (Open-Book Exam).

باختصار، نظام RAG لا يعتمد على ذاكرة النموذج الداخلية فقط، بل يقوم بخطوتين أساسيتين قبل توليد أي جواب:

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

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

المرحلة الأولى: الاسترجاع – كيف نجد الإبرة في كومة القش؟

هذه هي المرحلة الأهم. جودة الإجابة النهائية تعتمد 90% على جودة المعلومات اللي بنسترجعها. العملية تتم كالتالي:

  1. تجهيز قاعدة المعرفة (Indexing):
    • التقسيم (Chunking): نقوم بتقسيم مستنداتنا الكبيرة (PDFs, Word documents, etc.) إلى قطع صغيرة ومنطقية (Chunks). هذا مهم جدًا، لأننا لا نريد إعطاء النموذج كتابًا كاملًا ليقرأه في كل مرة.
    • التضمين (Embedding): نحول كل قطعة نصية إلى تمثيل رقمي يسمى “Vector” باستخدام نموذج تضمين (Embedding Model). هذا الفيكتور هو بمثابة “بصمة” رياضية لمعنى النص.
    • التخزين (Storing): نخزن هذه الفيكتورات مع النصوص الأصلية في قاعدة بيانات متخصصة تسمى “Vector Database” (مثل Pinecone, ChromaDB, FAISS). هذه القاعدة تسمح بالبحث عن التشابه في المعنى بسرعة فائقة.
  2. عملية البحث (Retrieval):
    • عندما يطرح المستخدم سؤالًا، نقوم بتحويل سؤاله أيضًا إلى “فيكتور” بنفس الطريقة.
    • نستخدم فيكتور السؤال للبحث في قاعدة البيانات عن الفيكتورات (أي قطع النصوص) الأكثر تشابهًا معه في المعنى.
    • النتيجة هي مجموعة من النصوص الصغيرة والمحددة التي نعتقد أنها تحتوي على إجابة سؤال المستخدم.

المرحلة الثانية: التوليد – “تفضل يا معلم، هذه هي المعلومات”

الآن بعد أن حصلنا على السياق (Context) ذي الصلة من المرحلة الأولى، تصبح الأمور أسهل بكثير. نقوم ببناء “موجه” (Prompt) ذكي للنموذج اللغوي الكبير. هذا الموجه يحتوي على ثلاثة أجزاء رئيسية:

  1. تعليمات واضحة للنموذج.
  2. السياق ذو الصلة الذي استرجعناه.
  3. سؤال المستخدم الأصلي.

مثال على موجه RAG:

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

السياق:

“[هنا نضع قطعة النص الأولى التي استرجعناها…]”

“[وهنا قطعة النص الثانية…]”

سؤال المستخدم:

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

الإجابة:

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

مثال عملي بسيط باستخدام Python و LangChain

حتى لا يكون الكلام نظريًا فقط، إليك مثال مبسط جدًا يوضح الفكرة باستخدام مكتبة LangChain الشهيرة.


# أولاً، نقوم بتثبيت المكتبات اللازمة
# pip install langchain langchain-openai langchain-community faiss-cpu

from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate

# 1. تحميل وتجهيز البيانات
# لغرض التبسيط، سنضع معلوماتنا في ملف نصي
with open("my_data.txt", "w") as f:
    f.write("اسم منتجنا هو 'برق' وهو متوافق مع نظام التشغيل ويندوز 11 فقط.n")
    f.write("منتج 'برق' لا يدعم نظام التشغيل لينكس حاليًا.n")
    f.write("لتثبيت منتج 'برق'، قم بتشغيل ملف setup.exe واتبع التعليمات.n")

loader = TextLoader("my_data.txt")
documents = loader.load()

# 2. تقسيم النصوص إلى قطع (Chunking)
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

# 3. إنشاء التضمينات (Embeddings) وقاعدة البيانات المتجهة (Vector Store)
# سنستخدم OpenAI لنموذج التضمين و FAISS كقاعدة بيانات في الذاكرة
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_documents(docs, embeddings)

# 4. إنشاء المسترجع (Retriever)
retriever = vector_store.as_retriever()

# 5. بناء الموجه (Prompt) وسلسلة RAG
llm = ChatOpenAI()

prompt = ChatPromptTemplate.from_template("""
Answer the user's question based only on the following context:

{context}

Question: {input}
""")

document_chain = create_stuff_documents_chain(llm, prompt)
retrieval_chain = create_retrieval_chain(retriever, document_chain)

# 6. طرح سؤال والحصول على إجابة مؤرضة
question = "هل منتج برق يعمل على لينكس؟"
response = retrieval_chain.invoke({"input": question})

print(response["answer"])
# الإجابة المتوقعة: منتج 'برق' لا يدعم نظام التشغيل لينكس حاليًا.

question_2 = "هل منتج برق يعمل على ويندوز 10؟"
response_2 = retrieval_chain.invoke({"input": question_2})
print(response_2["answer"])
# الإجابة المتوقعة: السياق لا يحتوي على معلومات كافية للإجابة، ولكن بناءً على المعلومات المتاحة، هو متوافق مع ويندوز 11 فقط.

نصائح من مطبخ أبو عمر: كيف تطبخ RAG على أصوله؟

بعد تجارب كثيرة و”عجن وخبز” في هذا المجال، إليكم بعض النصائح العملية:

  • فن التقسيم (Chunking): لا تستهين بهذه الخطوة. حجم القطعة (Chunk size) وتداخلها (Overlap) يؤثر بشكل كبير على جودة الاسترجاع. جرب أحجامًا مختلفة، وفكر في التقسيم بناءً على العناوين أو الفقرات بدلًا من عدد الأحرف الثابت.
  • المسترجع هو القلب: “زبالة داخلة، زبالة طالعة” (Garbage in, garbage out). إذا كان المسترجع يجلب معلومات غير دقيقة، فأفضل نموذج لغوي في العالم لن يستطيع إنقاذك. جرب تقنيات استرجاع متقدمة مثل (Multi-Query Retriever) الذي يولد أسئلة مشابهة لسؤال المستخدم للبحث بشكل أفضل.
  • اختر نموذج التضمين المناسب: ليست كل نماذج التضمين (Embedding Models) متشابهة. بعضها أفضل للنصوص القصيرة، وبعضها للمجالات المتخصصة. ابحث عن نماذج تدعم اللغة العربية بشكل جيد وقم باختبارها.
  • RAG + Fine-Tuning = قوة ضاربة: يمكنك استخدام الضبط الدقيق لجعل النموذج أفضل في “اتباع التعليمات” أو “تلخيص السياق المعطى له”، ثم تستخدمه كجزء من نظام RAG. هذا يعطيك أفضل ما في العالمين: نموذج يفهم لهجتك ومصطلحاتك، وفي نفس الوقت مرتبط بمصدر حقيقي للمعلومات.

الخلاصة: RAG ليس مجرد تقنية، بل هو تغيير في العقلية 💡

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

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

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

أبو عمر

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

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

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

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

آخر المدونات

تجربة المستخدم والابداع البصري

كنا نبني جدرانًا رقمية: كيف فتحت لنا ‘إمكانية الوصول’ (Accessibility) أبوابًا لم نكن نراها؟

اعتقدنا أننا نبني تطبيقات رائعة، لكننا كنا في الحقيقة نبني جدرانًا رقمية. في هذه المقالة، يشارك أبو عمر كيف غيّر فهم 'إمكانية الوصول' (Accessibility) منظوره...

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

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

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

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

كانت بيئاتنا جزرًا من الفوضى: كيف أنقذتنا “البنية التحتية كشفرة” (IaC) من جحيم الانحراف التكويني؟

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

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

مقابلاتي التقنية كانت كارثة: كيف أنقذني ‘التفكير بصوت عالٍ’ من جحيم الفشل؟

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

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

كان مستخدمونا في الطرف الآخر من العالم ينتظرون إلى الأبد: كيف أنقذتنا شبكات توصيل المحتوى (CDN) من جحيم زمن الاستجابة المرتفع؟

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

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