الوحدة 7 — بناء التعليمة النهائية والاستشهاد بالمصادر
الآن بحوزتنا أفضل خمسة مقاطع لكلّ سؤال. نبقى مع المشكلة الحقيقية: كيف نُصاغ التعليمة النهائية بحيث تُنتج إجابة مؤسّسية موثوقة؟ الجواب ليس فنّيًا بحتًا: هذه اللحظة هي التي يظهر فيها الفارق بين مساعد يُوثَق به ومساعد يخترع.
بنية التعليمة النهائية
تعليمة RAG جيّدة لها بنية ثابتة تتألّف من أربعة أجزاء متمايزة:
- تعليمة النظام (
system prompt): الدور، النبرة، القواعد الحاسمة. - السياق (
context): المقاطع المُسترجَعة بصياغة قابلة للاستشهاد. - سؤال المستخدم كما ورد.
- تذكير التنسيق: طول الإجابة، وضرورة الاستشهاد، وقاعدة الامتناع.
بنية عملية:
SYSTEM = """أنت مساعد داخلي لموظّفي المؤسّسة.
أجب باللغة العربية الفصحى، بأسلوب واضح ومقتضب.
تُجيب حصريًّا اعتمادًا على المقاطع المرفقة أدناه.
إن لم يكن الجواب موجودًا فيها، فقل صراحةً «لا يوجد في المستندات المتوفّرة»
واقترح إعادة صياغة السؤال أو التواصل مع الشخص المسؤول.
اذكر لكلّ معلومة رقم المقطع المصدر بين قوسين مربّعين، مثل [1] أو [3]."""
def build_prompt(question, passages):
context_parts = []
for i, p in enumerate(passages, start=1):
context_parts.append(
f"[{i}] المصدر: {p.metadata['source']}, ص {p.metadata['page']}\n"
f"{p.text}"
)
context = "\n\n---\n\n".join(context_parts)
return [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"المقاطع:\n\n{context}\n\nالسؤال: {question}"},
]
ترتيب المقاطع: احترس من «الضائع في المنتصف»
بحث معروف («Lost in the middle»): النماذج تعطي وزنًا أكبر لأوائل السياق وأواخره وتُهمل نسبيًّا ما يقع في المنتصف. النتيجة العملية: إن كان المقطع الأهمّ في الموضع الثالث من خمسة، فقد يفوت النموذج ولا يستشهد به.
الاستراتيجية العملية: رتّب المقاطع بحيث يكون الأكثر صلة في البداية أو النهاية. ترتيب مقبول:
def reorder_lost_in_middle(passages_sorted_by_score):
"""يضع الأعلى صلةً في الطرفين، والأقلّ في الوسط."""
n = len(passages_sorted_by_score)
reordered = [None] * n
left, right = 0, n - 1
for i, p in enumerate(passages_sorted_by_score):
if i % 2 == 0:
reordered[left] = p
left += 1
else:
reordered[right] = p
right -= 1
return reordered
تعليمة الامتناع: أقوى قواعد الأمان
تعليمة الامتناع هي التي تفصل بين مساعد يهلوس ومساعد يُوثَق به. القاعدة صريحة: إن لم يكن الجواب في المقاطع، فلا تخترعه. اختبار مباشر: اسأل النظام سؤالًا لا يوجد جوابه في مستنداتك، وتحقّق من أنّه يعترف بالجهل بدل الاختراع.
صياغات مقارنة:
سيّئة: «أجب عن السؤال باستعمال الم قاطع.» النموذج يجيب حتّى بلا معلومة، إذ ليس ممنوعًا عليه اللجوء إلى معرفته الداخلية.
متوسّطة: «إن لم تجد الجواب في المقاطع، لا تجب.» غامضة: قد يقرّر أنّ الجواب «قريب» ويجيب.
جيّدة: «تُجيب حصريًّا اعتمادًا على المقاطع المرفقة. إن لم يكن الجواب موجودًا فيها، فقل صراحةً "لا يوجد في المستندات المتوفّرة".» تحدّد سلوكًا واضحًا وقابلًا للاختبار.
الاستشهاد القابل للتحقّق
الاستشهاد ليس زخرفة: هو آلية الأمانة. عبارة «حسب اللائحة الداخلية...» بلا مرجع لا يمكن أن يتحقّق منها المستخدم. تنسيقان عمليّان:
تنسيق مضمَّن بأرقام مربّعة، وربطها في الواجهة بروابط قابلة للنقر:
إشعار الاستقالة مدّته شهر واحد لموظّفي الفئة أ [1]، وشهران لفئة الإطارات [2].
تنسيق منفصل يذكر المصادر في نهاية الإجابة:
إجابة: مدّة إشعار الاستقالة شهر واحد للفئة أ، وشهران لفئة الإطارات.
المصادر:
- [1]
reglement-interieur.pdf، ص 12، «المادّة 14»- [2]
procedure-cadres.pdf، ص 5، «المادّة 3»
الأوّل أكثر إحكامًا للأسئلة القصيرة، والثاني أوضح للأسئلة الطويلة ذات عدّة معلومات.
تحقّق الاستشهاد
النموذج قد يستشهد بمصدر لا يحوي المعلومة الفعلية. تحقّق الاستشهاد خطوة برمجية بعد التوليد: نتأكّد أنّ كلّ رقم مصدر مذكور يحوي فعلًا كلمات مفتاحية من الجملة التي يستشهد بها.
import re
def verify_citations(answer, passages):
"""يعيد قائمة الاستشهادات التي لا تدعم النصّ المُسبِق لها."""
invalid = []
for match in re.finditer(r"\[(\d+)\]", answer):
idx = int(match.group(1)) - 1
if idx < 0 or idx >= len(passages):
invalid.append(("رقم خارج المجال", match.group(0)))
continue
# جملة تسبق الاستشهاد مباشرةً (تقريب مبسَّط)
sentence = answer[max(0, match.start()-200):match.start()]
key_words = set(re.findall(r"\w{4,}", sentence.lower()))
passage_words = set(re.findall(r"\w{4,}", passages[idx].text.lower()))
overlap = len(key_words & passage_words) / max(len(key_words), 1)
if overlap < 0.15:
invalid.append(("تقاطع منخفض جدًّا", match.group(0)))
return invalid
اكتشاف استشهاد كاذب فرصة لإعادة تشغيل التعليمة بتذكير أشدّ، أو لعرض إجابة النموذج مع تنبيه للمستخدم.
تناقض بين المصادر
يحدث كثيرًا: مذكّرة 2022 تقول شيئًا، ومذكّرة 2024 تقول شيئًا مختلفًا. النموذج غير المُوجَّه سيُدمج الاثنين ويعطي إجابة مرتبكة.
استراتيجيات:
- تفضيل الأحدث: استعمل حقل
updated_atفي ما وراء البيانات لإعطاء المقاطع الأحدث ترجيحًا أعلى، أو لعرضها أوّلًا. - إعلان التناقض صراحةً: أضف إلى التعليمة قاعدة «إن اختلفت المصادر، أشِر إلى ذلك واذكر تاريخ كلّ منها».
- حذف المتقادم: إن كنت تعرف أنّ مذكّرة 2022 مُلغاة، أَخرِجها من الفهرس. بسيط وأقوى من كلّ تعليمة تعقيد.
طول الإجابة وأسلوبها
نبرة المساعد المستندي يجب أن تكون مباشرة ومختصرة، بلا حشو. جملة مقدّمة كـ«شكرًا على سؤالك، هذا موضوع مهمّ...» تُستهلك رموزًا بلا فائدة وتُبعد الإجابة.
قاعدة عملية في التعليمة: «جواب من ثلاث إلى ست جمل ما لم يستلزم السؤال قائمة أو جدولًا». يُجبر النموذج على الاقتضاب دون منعه من التوسّع عند الحاجة.
قوالب سياقية
بعض التطبيقات تحتاج قوالب استجابة ثابتة: للبحث عن إجراء، عرض «العنوان، الخطوات، المسؤول، المستندات المرجعية». يُصاغ هذا في تعليمة النظام:
SYSTEM_PROCEDURE = """... قواعد عامّة ...
حين يُسأل عن إجراء، أعد الجواب بهذا الشكل بالضبط:
**العنوان**: ...
**المسؤول**: ...
**الخطوات**:
1. ...
2. ...
**المستندات المرجعية**: [1], [2]"""
القوالب تُسهّل عرض الإجابة في الواجهة، وتُقلّل تباين النموذج بين استفسار وآخر.
النماذج الحديثة تدعم تخزين تعليمة النظام مؤقّتًا (prompt caching)، فيصير سعرها بضعة سنتات لكلّ مليون رمز بدل عدّة دولارات. إعادة كتابة نفس التعليمة في كلّ استدعاء دون تفعيل التخزين المؤقّت تُضاعف الفاتورة الشهرية بلا فائدة.
اسأل نظامك عشرة أسئلة ليست في المستندات على الإطلاق (اختراع محض). كم منها يُجيبه بلا حياء بدل الاعتراف بالجهل؟ إن كان الرقم يفوق الصفر، فقاعدة الامتناع في التعليمة ضعيفة أو أنّ الاسترجاع يعيد مقاطع بعيدة الصلة كأنّها قريبة. عالج قبل أيّ إطلاق.
في الخلاصة
- التعليمة النهائية بنية رباعية: نظام، سياق، سؤال، تذكير؛ كلّ جزء له وظيفة محدَّدة.
- رتّب المقاطع بحيث يكون الأهمّ في البداية أو النهاية لتفادي ظاهرة «الضائع في المنتصف».
- قاعدة الامتناع الواضحة والقابلة للاختبار هي الفارق الحقيقي بين مساعد موثوق ومهلوس.
- الاستشهاد بالمصادر آلية أمانة، ويحسن التحقّق منها برمجيًّا بعد التوليد؛ التناقض بين المصادر يُعالج بالتفضيل الزمني أو بالإعلان الصريح.
الوحدة التالية: تقييم النظام على الأمانة والملاءمة والتغطية، وبناء مجموعة من الأسئلة الموصوفة تُتيح قياس الأثر عند كلّ تعديل بدل الاعتماد على الانطباع.