منهجية بناء أنظمة ذكاء اصطناعي تكيفية باستخدام مسارات DSPy الديناميكية

مقدمة

يهدف هذا البحث إلى تقديم منهجية لإنشاء برامج ذكاء اصطناعي لا تقتصر على اتباع تعليمات ثابتة، بل تمتلك القدرة على تكييف بنيتها وسلوكها ذاتيًا بناءً على البيانات التي تعالجها. سيجري تحليل مفصل لشيفرة برمجية تطبق استراتيجية تلخيص تعاودية (Recursive Summarization)، مع التركيز بشكل خاص على الآلية التي تُمكّن البرنامج من توليد جدول محتويات ديناميكيًا، ومن ثم إنشاء مُصنِّف فوري لتوزيع المعلومات ضمن هذا الجدول.

الإطار المفاهيمي: من البنى الثابتة إلى الديناميكية

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

في المقابل، تستخدم الشيفرة البرمجية قيد الدراسة استراتيجية “فرّق تسد” (Divide and Conquer) أكثر منهجية وفعالية، وتنفذ عبر الخطوات التالية:

  1. استخلاص الفحوى (Gist Extraction): في المرحلة الأولى، يُستخلص ملخص موجز من جملة واحدة لكل صفحة على حدة.
  2. بناء المخطط الهيكلي (Blueprint Creation): يحلل النظام جميع الملخصات المستخلصة، ثم يُكلِّف النموذج اللغوي باقتراح مجموعة من العناوين الرئيسية عالية المستوى (جدول محتويات) لتنظيم المحتوى.
  3. تصنيف الصفحات (Page Sorting): يُصنِّف النظام بعد ذلك كل صفحة أصلية تحت أحد العناوين التي أُنشئت حديثًا.
  4. التطبيق التعاودي (Recursion): تُكرَّر العملية برمتها على نحو تعاودي لكل عنوان، حيث تُطبَّق على مجموعة الصفحات التي صُنّفت تحته، مما يؤدي إلى إنشاء عناوين فرعية، وهكذا دواليك.
  5. الكتابة (Base Case Writing): عندما يضم قسم ما عددًا قليلاً من الصفحات (شرط التوقف)، تتوقف عملية إنشاء العناوين الجديدة، ويكتفي النظام بكتابة الملخص النهائي لذلك القسم المحدد.

تُعد هذه العملية ديناميكية لأن البرنامج لا يمتلك معرفة مسبقة بالموضوعات أو العناوين؛ بل يستنبطها مباشرة من البيانات نفسها.

التحليل التقني للمكونات الديناميكية

تتحقق هذه الوظيفية من خلال تفاعل مكونين برمجيين رئيسيين.

1. توليد العناوين الديناميكية (ProduceHeaders)

class ProduceHeaders(dspy.Signature):
    """
    إنتاج قائمة بالعناوين (جدول محتويات ذي مستوى أعلى) لهيكلة تقرير حول *جميع* محتويات القطع (chunks).
    يجب التأكد من أن كل قطعة تنتمي إلى قسم واحد فقط.
    """
    chunk_summaries: str = dspy.InputField()
    headers: list[str] = dspy.OutputField()

# ... داخل دالة massively_summarize ...
headers = produce_headers(toc_path=toc_path, chunk_summaries=chunk_summaries).headers

هذا الجزء، على بساطته، يتمتع بفعالية كبيرة. فالطلب هنا ليس مجرد كتابة نص نثري، بل إنتاج قائمة مهيكلة من نوع list[str]. هذه القائمة ليست ثابتة في الشيفرة (not hard-coded)؛ فإذا كانت البيانات المدخلة دوريات طبية، قد ينتج النظام عناوين مثل ['التشخيص', 'العلاج', 'مآل المرض']. أما إذا كانت تقارير مالية، فقد ينتج ['أرباح الربع الأول', 'توقعات السوق', 'التوجيهات المستقبلية']. وبهذا يتكيف البرنامج مع طبيعة البيانات.

2. آلية التصنيف الديناميكي المقيد باستخدام Literal

هذا هو الجزء الأكثر إبداعًا في الشيفرة. بعد الحصول على قائمة العناوين، تنشأ الحاجة إلى تصنيف القطع النصية (chunks) ضمنها. يتم ذلك عبر إنشاء توقيع DSPy (signature) جديد في أثناء وقت التشغيل (runtime) باستخدام سلسلة نصية منسقة (f-string).

# 'headers' هي القائمة المولَّدة، مثل: ['التشخيص', 'العلاج', 'مآل المرض']
classify = parallelize(dspy.ChainOfThought(f"toc_path: list[str], chunk -> topic: Literal{headers}"))

تؤدي هذه السلسلة النصية المنسقة إلى بناء توقيع ديناميكي يظهر لمكتبة DSPy على النحو التالي:

"toc_path: list[str], chunk -> topic: Literal['التشخيص', 'العلاج', 'مآل المرض']"

الأهمية المنهجية لهذه الآلية:

  • القدرة على التكيف (Adaptability): يُنشأ المُصنِّف خصيصًا ليناسب العناوين التي تم توليدها للتو. إنه مُصمم ليلائم البيانات قيد المعالجة.
  • الضبط والموثوقية (Constraint and Reliability): هذه هي الفائدة المحورية. فباستخدام Literal، يُفرض قيد صارم على مخرجات النموذج اللغوي. فلا يمكن للنموذج أن يبتكر ويُخرج موضوعًا بديلاً مثل “تاريخ المريض”. بل يجب عليه أن يختار إحدى السلاسل النصية المطابقة تمامًا من قائمة headers. وهذا يحوّل النموذج اللغوي إلى أداة تصنيف موثوقة تمامًا للخطوات اللاحقة في البرنامج.

في غياب Literal، قد يعيد النموذج اللغوي موضوعات مختلفة قليلاً، مما قد يؤدي إلى فشل البرنامج عند محاولة تجميع القطع، كما يتضح في الشيفرة التالية:

# يعتمد إنشاء هذا القاموس (dictionary) على إعادة المصنف لموضوع يطابق تمامًا أحد عناصر 'headers'
sections = {topic: [] for topic in headers}
for topic, chunk in zip(topics, chunks):
    # إذا لم يكن `topic.topic` موجودًا في `headers`، فسيتعطل هذا السطر من الشيفرة!
    sections[topic.topic].append(chunk)

اعتبارات منهجية ونقاط للنقاش

يفتح نمط “وَلِّد ثم صَنِّف” آفاقًا للنقاش والتحليل:

  • تتبع مسار التنفيذ: يمكن تحليل سلوك الخوارزمية عند إدخال n من العناصر. على سبيل المثال، عند إدخال 6 قطع نصية (great_chunks)، سيكون toc_path في الاستدعاء الأول هو المسار الجذري. أما العناوين المولدة فتعتمد على المحتوى، وستشكل toc_path للاستدعاءات التعاودية اللاحقة.
  • أثر تعديل شرط التوقف (Base Case): يتوقف التعاود حاليًا إذا كان len(chunks) < 5. إن تعديل هذا الرقم له أثر مباشر على بنية المستند النهائي؛ فتقليله إلى 3 سيؤدي إلى مستند أكثر تفصيلاً وحبيبية (granularity)، ولكنه قد يكون أكثر تجزئة. في المقابل، زيادته إلى 10 ستنتج أقسامًا أكثر تماسكًا ولكن أقل تفصيلاً.
  • توسيع نطاق الاستخدام: يمكن تطبيق نمط “وَلِّد وصَنِّف” الديناميكي في سياقات أخرى متعددة. على سبيل المثال، في مجال دعم العملاء، يمكن استخدامه عبر:
    • التوليد: قراءة 100 تذكرة دعم حديثة وتوليد قائمة بالفئات المحتملة (مثل Literal['مشكلة في الفوترة', 'خلل فني', 'طلب ميزة جديدة']).
    • التصنيف: استخدام المصنف الديناميكي لتوجيه جميع التذاكر الواردة تلقائيًا إلى القسم المختص.

الشيفرة البرمجية الكاملة

# الصورة 1 - أصناف DSPy
class ProduceGist(dspy.Signature):
    """إنشاء خلاصة من جملة أو جملتين حول محتوى هذه القطعة، لنتمكن من تصنيفها."""
    
    toc_path: list[str] = dspy.InputField(desc="المسار الذي قطعته هذه القطعة حتى الآن في جدول المحتويات")
    chunk: str = dspy.InputField()
    gist: str = dspy.OutputField()

class ProduceHeaders(dspy.Signature):
    """
    إنتاج قائمة بالعناوين (جدول محتويات ذي مستوى أعلى) لهيكلة تقرير حول *جميع* محتويات القطع (chunks).
    يجب التأكد من أن كل قطعة تنتمي إلى قسم واحد فقط.
    """
    
    toc_path: list[str] = dspy.InputField()
    chunk_summaries: str = dspy.InputField()
    headers: list[str] = dspy.OutputField()

class WriteSection(dspy.Signature):
    """
    صياغة قسم بنسق ماركداون، استنادًا إلى مسار في جدول المحتويات ينتهي بالعنوان الخاص بهذا القسم.
    يجب أن يبدأ المحتوى مباشرة تحت ذلك العنوان: استخدم عناوين فرعية بعمق +1 على الأقل بالنسبة لمسار جدول المحتويات.
    يجب أن يُشتق محتوى قسمك بالكامل من قائمة القطع المُعطاة. ويجب أن يكون هذا المحتوى كاملاً ولكن
    موجزًا للغاية، مع استنساخ كل المعرفة الضرورية من القطع وحذف التكرارات أو التفاصيل غير ذات الصلة.
    """
    
    toc_path: list[str] = dspy.InputField()
    content_chunks = dspy.InputField()
    section_content = dspy.OutputField()

# الصورة 2 - الدالة الرئيسية
def massively_summarize(
    toc_path: list[str],
    chunks: list[str],
):
    if len(chunks) < 5 or len(toc_path) >= 3:
        content = dspy.ChainOfThought(WriteSection)(toc_path=toc_path, content_chunks=chunks).section_content
        return f"{toc_path[-1]}\n\n{content}"
    
    produce_gist = parallelize(dspy.ChainOfThought(ProduceGist))
    chunk_summaries = produce_gist([dspy.Example(toc_path=toc_path, chunk=chunk) for chunk in chunks])
    chunk_summaries = [summary.gist for summary in chunk_summaries]
    
    produce_headers = dspy.ChainOfThought(ProduceHeaders)
    headers = produce_headers(toc_path=toc_path, chunk_summaries=chunk_summaries).headers
    
    classify = parallelize(dspy.ChainOfThought(f"toc_path: list[str], chunk -> topic: Literal{headers}"))
    topics = classify([dspy.Example(toc_path=toc_path, chunk=chunk) for chunk in chunks])
    
    sections = {topic: [] for topic in headers}
    for topic, chunk in zip(topics, chunks):
        sections[topic.topic].append(chunk)
    
    parallel_massively_summarize = parallelize(massively_summarize)
    summarized_sections = parallel_massively_summarize(
        [
            dspy.Example(toc_path=toc_path + [topic], chunks=section_chunks)
            for topic, section_chunks in sections.items()
        ]
    )
    
    return toc_path[-1] + "\n\n".join(summarized_sections)

# استدعاء الدالة
massively_summarize(
    toc_path=["# مرجع DSPy"],
    chunks=great_chunks,
)

عشرة تطبيقات عملية للمنهجية الديناميكية المقترحة

  1. أتمتة تصنيف تذاكر الدعم الفني 🎫
    • سياق التطبيق: مواجهة مركز دعم لفيض من تذاكر الدعم بعد إطلاق برمجية جديدة، حيث تكون طبيعة المشكلات غير معروفة مسبقًا.
    • الآلية الديناميكية: يقوم النظام بتحليل عينة من التذاكر الحديثة (مثلاً 500 تذكرة) لتوليد قائمة Literal بالفئات الناشئة للمشكلات، مثل ['فشل تسجيل الدخول بعد التحديث', 'تعطل تطبيق الجوال على iOS 18', 'خطأ في احتساب الفاتورة']. بعد ذلك، ينشئ مصنفًا فوريًا يستخدم هذه الفئات لوسم وتوجيه جميع التذاكر الواردة.
    • الميزة الجوهرية: قدرة النظام على تحديد مشكلة جديدة وغير متوقعة والتكيف معها تلقائيًا، دون الحاجة إلى تعريف بشري مسبق لتلك الفئة، مما يؤدي إلى إنشاء منطق فرز ذاتي بناءً على الأزمة الحالية.
  2. التنظيم الموضوعي للمحتوى الإخباري 📰
    • سياق التطبيق: الحاجة إلى إنشاء موجز إخباري يومي يجمع المقالات وفقًا للأحداث المتطورة، بدلاً من الفئات العامة.
    • الآلية الديناميكية: يستوعب النظام مجموعة من المقالات الإخبارية، ويولد قائمة Literal بالعناوين المستنبطة من الأحداث الفعلية، مثل ['إعلان الاحتياطي الفيدرالي لسعر الفائدة', 'إطلاق مهمة ألفا قنطورس', 'جهود احتواء حرائق الغابات في كاليفورنيا'].
    • الميزة الجوهرية: إنتاج موجز إخباري يمثل سردًا للأحداث الرئيسية لليوم، مكتشفة ومنظمة تلقائيًا، بدلاً من كونه تجميعًا باهتًا للموضوعات.
  3. تحليل الاستبيانات ذات الإجابات المفتوحة 📊
    • سياق التطبيق: تحليل آلاف الردود النصية الحرة على سؤال مثل “ما الذي يمكننا تحسينه؟”.
    • الآلية الديناميكية: يحلل النظام فحوى جميع الردود ويولد قائمة Literal بأهم محاور الملاحظات، مثل: ['بطء استجابة خدمة العملاء', 'صعوبة تصفح الموقع', 'الرغبة في خيارات ألوان إضافية للمنتج']. ثم يصنف كل رد ضمن هذه الفئات الناشئة.
    • الميزة الجوهرية: تحويل البيانات النصية غير المهيكلة إلى تحليل كمي للمشكلات النوعية، مما ينتج قائمة إجراءات واضحة ومرتبة حسب الأولوية دون تحيزات مسبقة.
  4. نظام استخبارات السوق فائق اليقظة 📈
    • سياق التطبيق: الحاجة إلى فهم النقاشات والمخاوف الرئيسية ضمن سيل من الأخبار المالية وتقارير الأرباح وتحليلات الخبراء.
    • الآلية الديناميكية: يعالج النظام المستندات المالية ليوم واحد ويولد قائمة Literal بمحركات السوق الرئيسية قيد النقاش، مثل ['اختناقات سلاسل توريد أشباه الموصلات', 'أثر لوائح الطاقة الجديدة', 'تحول إنفاق المستهلكين نحو الخدمات'].
    • الميزة الجوهرية: تمكين المحللين من رؤية “السردية وراء الأرقام” والتركيز على العوامل المحركة للسوق اليوم، بدلاً من الاعتماد على موضوعات ثابتة ومحددة مسبقًا.
  5. الكشف الإلكتروني القانوني (E-Discovery) ⚖️
    • سياق التطبيق: مراجعة محامين لـ 50,000 مستند في دعوى قضائية، بحثًا عن أدلة ذات صلة بمسائل القضية الرئيسية.
    • الآلية الديناميكية: بعد تحليل عينة من المستندات، يولد النظام قائمة Literal من وسوم التصنيف الخاصة بالقضية، مثل ['العلم بالعيوب قبل الإطلاق', 'المراسلات المتعلقة بتجاوز تكاليف المشروع', 'اتصالات سرية بين المحامي والموكل'].
    • الميزة الجوهرية: تصميم وسوم التصنيف خصيصًا لتلبية احتياجات القضية الحالية، مما يجعل المراجعة البشرية اللاحقة أسرع وأكثر تركيزًا بأضعاف.
  6. رسم خرائط الأدبيات العلمية 🔬
    • سياق التطبيق: رغبة باحث في فهم المنهجيات الأساسية المستخدمة لدراسة بروتين جديد بسرعة.
    • الآلية الديناميكية: يقرأ النظام 200 ملخص بحثي حول الموضوع ويولد قائمة Literal بالأساليب التجريبية التي يجدها، مثل: ['تحرير الجينات بتقنية كريسبر-كاس9', 'علم البلورات بالأشعة السينية', 'دراسات النماذج الحية في الفئران', 'طي البروتين الحاسوبي'].
    • الميزة الجوهرية: تزويد الباحث بخريطة فورية للمجال البحثي قائمة على البيانات، مما يسمح له بتحديد المنهجيات السائدة، والأهم من ذلك، تلك التي قد تكون أقل استكشافًا.
  7. إعادة هيكلة الشيفرة البرمجية (Code Refactoring) 💻
    • سياق التطبيق: معالجة مطور للديون التقنية في قاعدة شيفرة برمجية قديمة ومعقدة.
    • الآلية الديناميكية: يحلل النظام جميع الدوال والوحدات البرمجية ويولد قائمة Literal بـ “الروائح الكودية” (code smells) الأكثر شيوعًا والخاصة بالمشروع، مثل ['دوال ذات تعقيد دوراني عالٍ', 'وحدات مرتبطة بإحكام بواجهة المستخدم', 'أنماط استعلام متكررة عن قاعدة البيانات'].
    • الميزة الجوهرية: إنشاء قائمة مهام مخصصة تمامًا وذات أولوية لإعادة الهيكلة، بناءً على المشكلات الفعلية الموجودة في الشيفرة، وليس على قائمة عامة.
  8. التنظيم الديناميكي للبريد الإلكتروني 📧
    • سياق التطبيق: إدارة صندوق بريد وارد غير منظم يحتوي على رسائل من مشاريع وجهات اتصال متعددة.
    • الآلية الديناميكية: يحلل النظام آخر 200 رسالة غير مقروءة ويولد قائمة Literal بالمشاريع والمهام النشطة الحالية، مثل ['إطلاق مشروع "أوديسي" للربع الثالث', 'متابعة عاجلة مع شركة أكْمي', 'مراجعة الميزانية النهائية'].
    • الميزة الجوهرية: إعادة التنظيم الآني لصندوق الوارد وفقًا لأولويات العمل الحالية، مما يحوله إلى لوحة معلومات فعالة وقابلة للتنفيذ.
  9. توليد خطط التعلم الشخصية 🎓
    • سياق التطبيق: تحليل ملاحظات ومقالات طالب في موضوع واسع مثل “الإمبراطورية الرومانية”.
    • الآلية الديناميكية: يحلل النظام عمل الطالب ويولد قائمة Literal بالمواضيع الفرعية التي يتفاعل معها أكثر (أو أقل)، مثل ['الإنجازات الهندسية الرومانية', 'الحروب البونيقية', 'الاضطراب السياسي في أواخر الجمهورية'].
    • الميزة الجوهرية: إنشاء خطة دراسية مخصصة، مسترشدة بعمل الطالب نفسه، مما يعزز اهتماماته ويعالج نقاط ضعفه المحددة.
  10. الإشراف التكيفي على المحتوى 🛡️
    • سياق التطبيق: انتشار أشكال جديدة وضارة من المحتوى (مثل “ميم” أو عملية احتيال) على منصة ما، والتي لا ترصدها قواعد الإشراف القديمة.
    • الآلية الديناميكية: يحلل النظام مجموعة من المنشورات التي أبلغ عنها المستخدمون مؤخرًا ويولد قائمة Literal بأنواع التهديدات الجديدة والناشئة: ['عملية تصيد "Mirage" الجديدة', 'الترويج لتحدي "Glimmer" الضار', 'تضليل سياسي منسق'].
    • الميزة الجوهرية: تمكين نظام الإشراف من تعلم رؤية التهديدات الجديدة في وقت شبه حقيقي، وإنشاء مخطط تصنيف خاص به لمكافحة الإساءات التي لم تكن موجودة حتى قبل ساعات.