يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.
خلوني أحكيلكم قصة صارت معي قبل فترة، قصة علّمتني درس ما بنساه. كنا شغالين على مشروع كبير لشركة محاماة محترمة، والمطلوب كان بناء مساعد ذكي (Chatbot) يساعد المحامين الجدد في البحث ضمن أرشيف ضخم من القضايا والقوانين الداخلية للشركة. الأرشيف كان عبارة عن آلاف ملفات الـ PDF والـ Word، عالم ثاني.
بعد أسابيع من الشغل والتعب، أطلقنا النسخة التجريبية. النموذج اللغوي الكبير (LLM) اللي استخدمناه كان ذكي وبيفهم السياق بشكل ممتاز. في اجتماع العرض التقديمي، كان المدير التنفيذي للشركة موجود، ومتحمس يشوف “التحفة التكنولوجية” اللي عملناها. سأل سؤال بسيط عن قضية معينة من الأرشيف: “ما هي تفاصيل الحكم في قضية العميل ‘س’ ضد الشركة ‘ص’ لعام 2019؟”
وهون كانت الصدمة… المساعد الذكي جاوب بثقة مطلقة، وبلش يسرد تفاصيل وحيثيات حكم… من وحي الخيال! اختلق أرقام قضايا، وأسماء قضاة، وتواريخ، وكلها غلط بغلط. شعرت وقتها كأن الأرض انشقت وبلعتني. المدير نظر إليّ نظرة لن أنساها، وقال بلهجة حادة: “شو هاد يا أبو عمر؟ هاد مش مساعد، هاد مؤلف قصص خيالية!”.
هذا الموقف المحرج كان بداية رحلتي الحقيقية مع مشكلة “الهلوسة” (Hallucination) في نماذج الذكاء الاصطناعي، والبحث عن حل جذري أنقذنا من هذا الجحيم، وهو ما يعرف اليوم بالبحث المعزز بالتوليد أو “RAG”.
ما هي “الهلوسة” في عالم الذكاء الاصطناعي؟ وليش بتصير؟
قبل ما ندخل في الحل، خلينا نفهم المشكلة. “الهلوسة” هي لما النموذج اللغوي الكبير (LLM) يخترع معلومات ويقدمها على أنها حقيقة مؤكدة. هو لا يكذب عن قصد، لأنه أصلاً ما عنده “قصد” أو “وعي”.
السبب بسيط: النماذج اللغوية هي عبارة عن آلات إحصائية عملاقة للتنبؤ بالكلمة التالية. تم تدريبها على كميات هائلة من نصوص الإنترنت، ومهمتها هي توليد نص “يبدو” منطقياً ومقنعاً بناءً على الأنماط اللي تعلمتها. هي مثل الطالب اللي قرأ كل كتب المكتبة، بس وقت الامتحان ما معه ولا كتاب، فبيعتمد على ذاكرته. أحياناً ذاكرته بتخلطه، فبيبدأ “يألّف” إجابات تبدو صحيحة لكنها في الحقيقة غير دقيقة.
المشكلة أن تدريبها يتوقف عند نقطة معينة، فهي لا تعرف أي معلومة جديدة بعد تاريخ قطع تدريبها، ولا تستطيع الوصول إلى بياناتك الخاصة (مثل ملفات شركة المحاماة في قصتي). إذن، كيف نجعلها تجيب على أسئلتنا بناءً على مصادرنا الخاصة والموثوقة؟
الحل السحري: البحث المعزز بالتوليد (RAG) – كيف بيشتغل؟
هنا يأتي دور البطل: Retrieval-Augmented Generation (RAG). فكرته عبقرية في بساطتها: بدلاً من أن نطلب من النموذج الإجابة من “ذاكرته” الواسعة وغير الموثوقة، سنعطيه “كتاباً مفتوحاً” (Open Book) يحتوي على المعلومات الدقيقة التي نحتاجها، ونطلب منه أن يقرأ هذا الكتاب ويجيب على سؤالنا من خلاله فقط.
هذا “الكتاب المفتوح” هو بياناتك الخاصة (ملفات PDF، قواعد بيانات، مقالات موقعك، …إلخ). العملية تتم على ثلاث مراحل رئيسية:
المرحلة الأولى: التجهيز والفهرسة (Indexing)
هذه المرحلة تتم مرة واحدة في البداية (أو كلما تحدثت بياناتك). الهدف منها هو تحويل مستنداتك إلى صيغة يفهمها الكمبيوتر ويستطيع البحث فيها بسرعة.
- التقطيع (Chunking): نقوم بتقسيم مستنداتك الكبيرة إلى أجزاء أو “مَقاطع” صغيرة. ليش؟ لأن التعامل مع مقاطع صغيرة ومركزة أسهل وأكثر دقة عند البحث عن معلومة محددة.
- التضمين (Embeddings): هذه هي الخطوة السحرية. نستخدم نموذجاً متخصصاً لتحويل كل “مقطع” نصي إلى متجه رياضي (Vector)، وهو عبارة عن قائمة طويلة من الأرقام. هذه المتجهات تمثل “معنى” النص في فضاء رياضي. النصوص ذات المعاني المتقاربة تكون متجهاتها “قريبة” من بعضها في هذا الفضاء.
- التخزين (Storing): نقوم بتخزين هذه المتجهات مع النصوص الأصلية المقابلة لها في قاعدة بيانات متخصصة تسمى “قاعدة بيانات المتجهات” (Vector Database). من أشهر الأمثلة عليها: Pinecone, ChromaDB, FAISS.
باختصار، مرحلة الفهرسة تحول وثائقك من مجرد نصوص إلى مكتبة منظمة حسب المعنى، جاهزة للبحث الفوري.
المرحلة الثانية: البحث والاسترجاع (Retrieval)
هذه المرحلة تحدث في كل مرة يسأل فيها المستخدم سؤالاً.
- استعلام المستخدم (User Query): يأتي المستخدم ويسأل سؤالاً، مثلاً: “ما هي شروط الإجازة السنوية للموظفين؟”.
- تضمين الاستعلام: نقوم بتحويل سؤال المستخدم أيضاً إلى متجه (Embedding) باستخدام نفس النموذج الذي استخدمناه في المرحلة الأولى.
- البحث عن التشابه: نأخذ متجه السؤال ونبحث في قاعدة بيانات المتجهات عن المقاطع النصية التي تمتلك المتجهات الأكثر شبهاً وقرباً منه. هذه هي المقاطع الأكثر صلة بسؤال المستخدم.
النتيجة؟ نحصل على أفضل 3 أو 5 مقاطع من مستنداتنا الأصلية التي يُحتمل أنها تحتوي على إجابة السؤال.
المرحلة الثالثة: التعزيز والتوليد (Augmentation & Generation)
هنا نجمع كل شيء معاً.
- بناء السياق (Context Building): نأخذ المقاطع النصية التي استرجعناها في المرحلة السابقة.
- صياغة الطلب المعزز (Augmented Prompt): نقوم بإنشاء طلب (Prompt) جديد للنموذج اللغوي الكبير (LLM) بالصيغة التالية:
“بناءً على السياق التالي فقط: [هنا نضع المقاطع النصية المسترجعة]. أجب على السؤال التالي: [هنا نضع سؤال المستخدم الأصلي]. إذا كانت الإجابة غير موجودة في السياق، قل ‘لا أعرف الإجابة’.” - التوليد (Generation): نرسل هذا الطلب المعزز إلى الـ LLM، والذي سيقوم بدوره بتوليد إجابة دقيقة ومبنية حصراً على المعلومات التي زودناه بها، مما يمنع الهلوسة بشكل شبه كامل.
خلونا نشوف مثال عملي: بناء نظام RAG بسيط
الكلام النظري جميل، لكن “الإيد اللي في المي مش زي الإيد اللي في النار”. خلينا نطبق عملياً باستخدام لغة Python ومكتبة LangChain الشهيرة لتبسيط الأمور.
الخطوة 1: تجهيز البيئة والمكتبات
أولاً، تأكد من تثبيت المكتبات اللازمة. سأستخدم OpenAI كنوذج لغوي، و FAISS كقاعدة بيانات متجهات تعمل في الذاكرة (سهلة للمبتدئين).
pip install langchain openai faiss-cpu tiktoken
لا تنسَ وضع مفتاح API الخاص بـ OpenAI في متغيرات البيئة (Environment Variable) تحت اسم OPENAI_API_KEY.
الخطوة 2: تحميل وتجهيز البيانات
لنفترض أن لدينا مستنداً بسيطاً عن سياسة الشركة الداخلية. سنضعه كنص عادي في الكود مباشرة.
from langchain.text_splitter import RecursiveCharacterTextSplitter
# هذا هو مستندنا الذي نريد البحث فيه
company_policy_text = """
مرحباً بكم في سياسة شركتنا.
الإجازة السنوية للموظفين هي 21 يوماً مدفوعة الأجر بعد إتمام السنة الأولى.
يمكن تقديم طلبات الإجازة عبر بوابة الموظفين الإلكترونية.
يجب تقديم الطلب قبل 15 يوماً على الأقل من تاريخ بدء الإجازة.
ساعات العمل الرسمية من 9 صباحاً حتى 5 مساءً، من الأحد إلى الخميس.
العمل عن بعد متاح يومين في الأسبوع بالتنسيق مع المدير المباشر.
"""
# 1. التقطيع (Chunking)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # حجم كل مقطع
chunk_overlap=20 # تداخل بين المقاطع لضمان عدم فقدان السياق
)
docs = text_splitter.create_documents([company_policy_text])
print(f"تم تقطيع النص إلى {len(docs)} مقطع.")
الخطوة 3: إنشاء قاعدة بيانات المتجهات (Vector Store)
الآن سنحول هذه المقاطع إلى متجهات ونخزنها في FAISS.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# 2. التضمين والتخزين (Embedding & Storing)
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_documents(docs, embeddings)
print("تم إنشاء قاعدة بيانات المتجهات بنجاح!")
الخطوة 4: بناء سلسلة RAG والاستعلام
هذه هي المرحلة النهائية حيث نربط كل شيء معاً ونسأل سؤالنا.
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 3. بناء السلسلة (Chain)
llm = OpenAI(temperature=0) # temperature=0 لجعل الإجابات دقيقة وغير إبداعية
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # "stuff" تعني وضع كل المقاطع المسترجعة في السياق
retriever=vector_store.as_retriever()
)
# طرح سؤال
question = "كم عدد أيام الإجازة السنوية؟"
response = qa_chain.run(question)
print(f"السؤال: {question}")
print(f"الإجابة: {response}")
# طرح سؤال آخر
question_2 = "هل يمكنني العمل من المنزل؟"
response_2 = qa_chain.run(question_2)
print(f"nالسؤال: {question_2}")
print(f"الإجابة: {response_2}")
إذا قمت بتشغيل هذا الكود، ستجد أن الإجابات دقيقة جداً ومأخوذة مباشرة من النص الذي زودناه به. لو سألت النموذج نفس السؤال بدون RAG، قد يعطيك إجابة عامة (مثلاً “عادة ما تكون 30 يوماً حسب قانون العمل…”) أو قد يهلوس. لكن مع RAG، هو مجبر على الالتزام بالحقيقة الموجودة في مستنداتك.
نصائح من خبرة أبو عمر
- فن التقطيع (Chunking): حجم المقطع (chunk_size) والتداخل (chunk_overlap) يؤثران بشكل كبير على دقة النتائج. لا يوجد رقم سحري، عليك التجربة بناءً على طبيعة مستنداتك. ابدأ بقيم متوسطة (مثلاً 1000 للحجم و 100 للتداخل) ثم قم بالتعديل.
- جودة بياناتك هي كل شيء: تذكر مبدأ “Garbage in, garbage out”. إذا كانت مستنداتك الأصلية مليئة بالأخطاء أو المعلومات القديمة، فإن RAG سيعطيك إجابات خاطئة ولكن بثقة! نظّف وحَدّث مصادرك أولاً.
- اختر نموذج التضمين (Embedding Model) المناسب: هناك العديد من نماذج التضمين، بعضها أفضل للغات معينة أو لمجالات متخصصة (طبية، قانونية). استثمر بعض الوقت في البحث عن أفضل نموذج لحالتك.
- لا يقتصر RAG على الأسئلة والأجوبة: يمكنك استخدام نفس التقنية لتلخيص المستندات الطويلة بناءً على نقاط معينة، أو لكتابة محتوى جديد مستوحى من قاعدة بيانات معرفية محددة.
الخلاصة: RAG ليس عصا سحرية، ولكنه أقرب ما يكون! 🪄
تقنية البحث المعزز بالتوليد (RAG) غيرت قواعد اللعبة. لقد حولت النماذج اللغوية الكبيرة من مجرد “ببغاوات” ذكية تردد ما تعلمته، إلى “باحثين” خبراء يمكنهم استخدام وثائق محددة لتقديم إجابات دقيقة وموثوقة. هي الجسر الذي يربط بين القوة التوليدية الهائلة للـ LLMs وبين أرض الواقع المتمثلة في بياناتك الخاصة.
بالنسبة لي، بعد ذلك الموقف المحرج مع شركة المحاماة، قمنا بإعادة بناء النظام باستخدام RAG. في العرض التقديمي التالي، كان المساعد الذكي دقيقاً كالساعة، يجيب على أعقد الأسئلة القانونية بالرجوع إلى المادة والقضية الصحيحة. كانت لحظة فخر وانتصار لنا كفريق.
نصيحتي الأخيرة لك: لا تخف من التجربة. ابدأ بمشروع صغير، خذ مستنداً واحداً، طبق الخطوات التي ذكرناها، وشاهد السحر يحدث بنفسك. عالم الذكاء الاصطناعي يتطور بسرعة، و RAG هو أحد أهم الأدوات في صندوق عدة أي مطور اليوم.
يلا، ورجونا همتكم! 💪