كيفية بناء نظام RAG في 10 أسطر من Python دون استخدام الإطارات

افتح قوة RAG (Retrieval Augmented Generation) باستخدام هذا الدليل البرمجي لـ Python المكون من 10 أسطر. استكشف استرجاع المعلومات ، وابن نظام المستندات الخاص بك ، واستفد من LLMs للحصول على استجابات قوية - كل ذلك دون الاعتماد على أطر عمل معقدة. قم بتحسين محتواك لتحسين محركات البحث والمشاركة.

١٧ فبراير ٢٠٢٥

party-gif

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

فهم مفهوم التوليد المعزز بالاسترجاع (RAG)

استرجاع التوليد المعزز (RAG) هي تقنية تستخدم لاسترجاع المعلومات من مستنداتك الخاصة. وهي تتضمن عملية ذات خطوتين:

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

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

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

في حين أن هناك أطر عمل مثل Langchain و LlamaIndex التي تبسط تنفيذ خطوط أنابيب RAG، يمكن بناء المكونات الأساسية باستخدام Python وطراز تضمين وLLM فقط. هذا النهج يوفر فهمًا أفضل للمفاهيم الأساسية ويسمح بمزيد من المرونة في تخصيص خط الأنابيب.

تعلم تقسيم المستندات إلى فقرات

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

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

الرمز لهذه الخطوة كما يلي:

# تقسيم المستند إلى فقرات
chunks = [paragraph.strip() for paragraph in text.split('\n') if paragraph.strip()]

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

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

تضمين المستندات والاستفسارات المستخدم باستخدام محولات الجملة

لتضمين قطع المستند واستفسار المستخدم، سنستخدم مكتبة Sentence Transformers. توفر هذه المكتبة نماذج مدربة مسبقًا والتي يمكن أن تولد تضمينات عالية الجودة للنص.

أولاً، نقوم بتحميل نموذج التضمين:

from sentence_transformers import SentenceTransformer
embedding_model = SentenceTransformer('all-mpnet-base-v2')

بعد ذلك، نحسب التضمينات لقطع المستند:

chunk_embeddings = embedding_model.encode(chunks, normalize_embeddings=True)

هنا، chunks هي قائمة بقطع النص من المستند. يضمن الخيار normalize_embeddings=True أن التضمينات تكون محددة، وهو أمر مهم لحساب التشابه لاحقًا.

للحصول على تضمين لاستفسار المستخدم، ببساطة نقوم بتشغيل:

query_embedding = embedding_model.encode([user_query], normalize_embeddings=True)[0]

الآن، لدينا تضمينات لقطع المستند واستفسار المستخدم، والتي يمكننا استخدامها لخطوة الاسترجاع.

استرجاع الأجزاء ذات الصلة بناءً على التشابه الجيبي التربيعي

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

  1. احسب تضمين استفسار المستخدم باستخدام نفس نموذج التضمين كقطع المستند.
  2. احسب حاصل الضرب النقطي بين تضمين الاستفسار وكل من تضمينات قطع المستند. هذا يعطينا درجات التشابه الجيبي التمام.
  3. رتب قطع المستند بناءً على درجات التشابه الجيبي التمام واختر أعلى K قطعة ذات صلة.
  4. استرجع محتوى النص للقطع المحددة لاستخدامها كسياق لنموذج اللغة.

الخطوات الرئيسية هي:

  1. احسب تضمين الاستفسار
  2. احسب درجات التشابه الجيبي التمام
  3. رتب واختر أعلى K قطعة
  4. استرجع محتوى نص القطعة

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

تعزيز استفسار المستخدم بالأجزاء المسترجعة وتوليد الاستجابة باستخدام OpenAI GPT-4

لتوليد استجابة باستخدام القطع المسترجعة واستفسار المستخدم، نقوم أولاً بإنشاء مطالبة تتضمن القطع ذات الصلة واستفسار المستخدم. ثم نستخدم نموذج OpenAI GPT-4 لتوليد استجابة بناءً على هذه المطالبة.

هنا الرمز:

# احصل على استفسار المستخدم
user_query = "ما هي عاصمة فرنسا؟"

# استرجع أكثر القطع ذات الصلة بناءً على استفسار المستخدم
top_chunk_ids = [6, 8, 5]
top_chunks = [chunks[i] for i in top_chunk_ids]

# إنشاء المطالبة
prompt = "استخدم السياق التالي للإجابة على السؤال في النهاية. إذا لم تعرف الإجابة، فقل أنك لا تعرف ولا تحاول إنشاء إجابة.\n\nالسياق:\n"
for chunk in top_chunks:
    prompt += chunk + "\n\n"
prompt += f"\nالسؤال: {user_query}"

# توليد الاستجابة باستخدام OpenAI GPT-4
response = openai_client.chat.create(
    model="gpt-4",
    messages=[
        {"role": "user", "content": prompt}
    ],
    max_tokens=1024,
    n=1,
    stop=None,
    temperature=0.7,
).choices[0].message.content

print(response)

في هذا الرمز، نقوم أولاً باسترجاع أكثر القطع ذات الصلة بناءً على استفسار المستخدم من خلال العثور على أعلى 3 قطع مع أعلى درجات تشابه. ثم نقوم بإنشاء مطالبة تتضمن هذه القطع واستفسار المستخدم. أخيرًا، نستخدم نموذج OpenAI GPT-4 لتوليد استجابة بناءً على هذه المطالبة.

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

الخاتمة

في هذا الدرس، تعلمنا كيفية بناء نظام دردشة كامل مع نظام استرجاع المستندات باستخدام 10 أسطر فقط من رمز Python. غطينا المكونات الرئيسية لخط أنابيب التوليد المعزز بالاسترجاع (RAG)، بما في ذلك إنشاء قاعدة المعرفة، وتقسيم المستند، والتضمين، والاسترجاع، والتوليد باستخدام نموذج لغة كبير.

أهم النقاط المستفادة هي:

  1. يمكنك تنفيذ خط أنابيب RAG أساسي دون الحاجة إلى أطر عمل معقدة مثل Langchain أو LlamaIndex. Python النقي وبضع مكتبات كافية.
  2. تقسيم المستندات الخاصة بك على أساس الهيكل (على سبيل المثال، الفقرات) هو استراتيجية بسيطة ولكن فعالة في معظم الحالات الاستخدام.
  3. تضمين قطع المستند واستفسار المستخدم، ثم حساب درجات التشابه، يسمح لك باسترجاع أكثر المعلومات ذات الصلة لتعزيز استفسار المستخدم.
  4. دمج القطع المسترجعة مع استفسار المستخدم وإرسالها إلى نموذج لغة كبير يمكّن توليد استجابة ذات صلة ومفيدة.

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

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

التعليمات