انتقل إلى المحتوى الرئيسي

الوحدة 7 — الذاكرة المشتركة وتمرير السياق

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

memory=True: التفعيل الأوّليّ

في Crew, يكفي حقل واحد لتفعيل نظام ذاكرة كامل:

equipe = Crew(
agents=[analyste, redacteur, relecteur, responsable],
tasks=[...],
process=Process.sequential,
memory=True,
embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}},
)

embedder يُعرّف نموذج التضمين المُستعمَل لبناء الذاكرة الدلاليّة. الافتراض معقول (OpenAI)، لكن يمكن استبداله بنموذج محلّيّ (ollama) للسرّيّة.

الطبقات الثلاث للذاكرة

CrewAI ينشئ داخليًّا ثلاث مخازن مستقلّة عند memory=True:

  • الذاكرة القصيرة (ShortTermMemory): تحفظ نتائج المهامّ الحديثة في نفس التنفيذ. تُقدَّم للوكلاء التاليين كسياق. تُمسَح عند انتهاء kickoff().
  • الذاكرة الطويلة (LongTermMemory): تحفظ ملخّصات المهامّ عبر تنفيذات متعدّدة، في قاعدة SQLite محلّيّة افتراضيًّا. تتراكم بمرور الوقت، وتفيد في مسارات مكرّرة (وثائق أسبوعيّة لنفس المنتج).
  • ذاكرة الكيانات (EntityMemory): تستخرج تلقائيًّا الكيانات المذكورة (أسماء وظائف، مصطلحات تقنيّة، أسماء منتجات) وتربطها بسياق تعريفها. تُستعمَل لاحقًا للحفاظ على اتّساق التسميات.

ما يمرّ بين المهامّ فعلًا

سؤال يخلط أغلب المطوّرين: هل السياق ينتقل عبر context=[...] أم عبر memory=True؟ الجواب: الاثنان معًا، ولكن مختلفَان.

  • context=[tache_precedente]: ينقل كامل المخرَج للمهمّة المذكورة إلى تعليمة النظام للمهمّة الحاليّة. مباشر، معروف الحجم، قابل للتحكّم.
  • memory=True: تُبنى ذاكرة دلاليّة، ويُختار منها الأكثر صلة بالمهمّة الحاليّة عبر البحث التضمينيّ. الحجم متغيّر، والاختيار غير قابل للتنبّؤ بدقّة.

القاعدة الآمنة: استعمل context للاعتماديات الصريحة المعروفة، واستعمل memory=True للسياقات الطويلة الأمد التي لا تريد سردها كاملة.

tache_redaction = Task(
description="اكتب الوثيقة من قائمة الوظائف المُحلَّلة",
expected_output="ملفّ Markdown من عشر صفحات",
agent=redacteur,
context=[tache_analyse], # صريح: كامل المخرَج ينتقل
)
# مع memory=True، الوكيل يستطيع أيضًا استرجاع تعريفات مصطلحات
# مذكورة قبل ثلاثة أسابيع في تنفيذ سابق.

حجم السياق التراكميّ

الفخّ الحرفيّ: كلّ مهمّة تُضيف مخرَجها للذاكرة، والمهمّة التالية تحصل على مخرَج المهمّة السابقة بالإضافة إلى استرجاعات من الذاكرة الطويلة. بعد أربع مهامّ، السياق قد يصل إلى 15 ألف رمز بلا أن نلاحظ.

على gpt-4o بنافذة 128 ألف رمز، هذا ليس مشكلة. على gpt-4o-mini بميزانيّة، يبدأ ذلك في رفع الفاتورة بشكل ملحوظ. قياس فعليّ على وثيقتنا:

الإعدادمجموع رموز الدخلالكلفة (gpt-4o)
بدون ذاكرة، context صريح11 ألف0.32 د.أ
مع memory=True (تنفيذ أوّل)14 ألف0.41 د.أ
مع memory=True (تنفيذ عاشر)22 ألف0.64 د.أ

الذاكرة الطويلة تنمو مع كلّ تنفيذ، والاسترجاعات تصير أطول. القاعدة: راقب نمو الذاكرة الطويلة (long_term_memory.db)، ونظّفها دوريًّا إن كنت تُشغّل الفريق كثيرًا.

تعطيل الذاكرة على مهمّة محدّدة

بعض المهامّ لا تحتاج ذاكرة (مثلًا: تحقّق نحويّ سطحيّ). CrewAI لا يعرض تعطيلًا لكلّ مهمّة، لكن يمكن كسر السلسلة بترك context=[] وتخفيف تعليمة النظام لتُخبر الوكيل ألاّ يعتمد على ذاكرة سابقة. البديل: تشغيل الفريق بـmemory=False وحفظ ذاكرة يدويًّا فقط عند الحاجة.

نموذج التضمين: الخيار الصحيح

text-embedding-3-small (OpenAI) يُعطي جودة ممتازة بكلفة منخفضة، ويكفي في 90 ٪ من الحالات. لبيانات حسّاسة، نستعمل نموذج تضمين محلّيًّا عبر Ollama:

embedder={"provider": "ollama", "config": {"model": "nomic-embed-text"}}

الجودة أقلّ قليلًا، والسرعة أبطأ (على معالج رسوميّات متواضع)، لكنّ البيانات لا تغادر جهازك. مقايضة كلاسيكيّة.

ذاكرة الكيانات: الفائدة الخفيّة

EntityMemory تستخرج تلقائيًّا الكيانات المذكورة في المخرَجات. حين يذكر المحلِّل «وظيفة إدارة الاشتراكات المتكرّرة»، الكيان يُخزَّن مع سياقه. حين يبدأ المحرِّر الكتابة، ذاكرة الكيانات تُذكّره بأنّ هذه الوظيفة موجودة بالفعل ولا يجب أن يخترع اسمًا آخر.

هذه الآليّة تحلّ فخًّا شائعًا: تعدّد الأسماء للشيء نفسه («الاشتراكات المتكرّرة»، «الفوترة الدوريّة»، «التجديد التلقائيّ»). ذاكرة الكيانات تُوحّد التسمية عبر المهامّ.

الخيط الأحمر بعد الوحدة 7

نُشغّل الآن الفريق بـmemory=True، ونلاحظ في الآثار كيف يعود المحرِّر أحيانًا إلى معلومة استخرجها المحلِّل قبل جولتَين. الوثيقة الناتجة أكثر تماسكًا في التسميات، ونحن نعرف الآن أن نُوازن بين context الصريح (للاعتماديّات الأساسيّة) والذاكرة المستقلّة (للسياق الطويل).

قاعدة قرار

حاول أوّلًا بلا ذاكرة وcontext صريح. لن تُضيف memory=True إلاّ حين ترى بوضوح أنّ الفريق يعيد اختراع معلومة موجودة، أو يفقد اتّساق التسميات.

الخلاصة

  • memory=True يفعّل ثلاث طبقات: قصيرة (نفس التنفيذ)، طويلة (عبر التنفيذات)، وكيانات (مصطلحات).
  • context=[...] صريح يفيد للاعتماديّات المعروفة؛ الذاكرة الدلاليّة تفيد للسياقات الطويلة الأمد.
  • كلّ طبقة ذاكرة تُضخّم السياق التراكميّ؛ راقب الكلفة، ونظّف long_term_memory.db دوريًّا.
  • ذاكرة الكيانات تحلّ مشكلة تعدّد أسماء الشيء نفسه بين وكلاء الفريق.