Skip to main content

كل شيء في طلب واحد

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

كيف يعمل

في كل دور، يُجمّع الوكيل مصفوفة الرسائل الكاملة من الصفر:
  1. القشرة الجبهية الأمامية (Prefrontal) تبني موجّه نظام رشيقًا: الهوية، وحقائق الجهاز، وعقد التشغيل، وخلاصة التفضيلات المتعلَّمة، وفهرس القدرات بسطر واحد لكل قدرة، وخريطة الذاكرة — خريطة لما هو موجود ويمكن استرجاعه، وليس المحتوى نفسه أبدًا. لا إغراق للذاكرة، ولا سجل حلقات، ولا نصوص مهارات، ولا كتالوجات أدوات: يسترجع النموذج ما يحتاجه الدور عبر الأدوات (memory_search وtool_search).
  2. الوكيل يُلحق إعادة تشغيل المحادثة. في معظم المحادثات يكون ذلك السجل الكامل حرفيًا. وبعد نحو 120 ألف حرف من النمو، تُطوى الأدوار الأقدم في ملخص متجدد مُخزَّن وتُعاد على هيئة ذلك الملخص بالإضافة إلى آخر 8 رسائل حرفيًا — فيبقى الطلب مكتفيًا بذاته دون إعادة إرسال كل بايت جرى تبادله يومًا. راجع دورة حياة السياق.
  3. المهاد (Thalamus) يوجّه الطلب إلى المزود النشط، الذي يحوّل الرسائل إلى التنسيق الأصلي للمزود ويرسل طلب HTTP واحدًا.
يستقبل المزود كل ما يحتاجه دفعة واحدة — موجّه النظام، والأدوات، وإعادة تشغيل المحادثة. ليس لديه أي ذاكرة عن الاستدعاءات السابقة.

داخل دور واحد

يُنفّذ الوكيل حلقة استخدام الأدوات: استدعاء النموذج، تنفيذ الأدوات، إلحاق النتائج، ثم استدعاء النموذج مجددًا. كل تكرار يُرسل مصفوفة الرسائل المتنامية مرة أخرى إلى المزود:
يرى المزود سياقًا أكبر مع كل تكرار، لكنه لا يحتفظ بأي حالة بينها. موجّه النظام ومخططات الأدوات يُثبَّتان عند بداية الدور ويبقيان ثابتين على مستوى البايت عبر التكرارات؛ أما عدادات الحلقة الحية فتركب ذيلًا متقلبًا صغيرًا في نهاية المصفوفة الصادرة تمامًا، بعد كل نقاط توقف التخزين المؤقت، فلا تُزعزع البادئة المخزَّنة أبدًا.

تنسيق الطلب الخاص بكل مزود

يستقبل كل مزود المحتوى المنطقي ذاته، محوّلًا إلى واجهة برمجة التطبيقات الأصلية الخاصة به: التحويل غير مرئي لبقية النظام. يأخذ المهاد تنسيقًا قانونيًا واحدًا ويُنتج طلبًا خاصًا بالمزود.

التخزين المؤقت للموجّهات (Prompt Caching)

قد يبدو إرسال الحمولة الكاملة في كل استدعاء مكلفًا. لكنه ليس كذلك — بفضل التخزين المؤقت للموجّهات، ولأن بادئة موجّه وولفيش ثابتة على مستوى البايت بحكم البناء: تتجدد خريطة الذاكرة مرة واحدة لكل يوم تقويمي، وتفعيل الأدوات على مستوى المحادثة (تحميل محادثة أخرى لقدرةٍ ما لا يمس بادئة هذه المحادثة أبدًا)، وتُعرَض عدادات كل تكرار بعد نقاط توقف التخزين المؤقت. وبالقياس عبر 50 محادثة، تبلغ نسبة تطابق مخزن المزوّد نحو 99%.

Anthropic

يستخدم مزود Anthropic التخزين المؤقت للموجّهات مع ثلاث نقاط cache_control:
  1. موجّه النظام — سياق القشرة الجبهية الرشيق، ثابت على مستوى البايت عبر الأدوار
  2. تعريفات الأدوات — مستقرة خلال المحادثة
  3. بادئة سجل المحادثة — دور المستخدم قبل الأخير، الذي يُحدّد الحد الفاصل بين السجل المستقر والتبادل الأخير
عند الاستدعاء الأول، تكتب Anthropic البادئة إلى مخزن مؤقت على الخادم (مدة بقاء 5 دقائق تُجدَّد مع كل استخدام). تقرأ الاستدعاءات التالية من المخزن بدلًا من إعادة المعالجة، مما يقلل تكلفة رموز الإدخال بنحو 90% وزمن أول رمز بنحو 80% على الجزء المخزَّن. المخزن مؤقت ومجهول الهوية — لا يحتوي على هوية جلسة وينتهي تلقائيًا إذا أصبحت المحادثة خاملة.

OpenAI

تطبّق OpenAI تخزينها المؤقت التلقائي للبادئات بشفافية (خصم 50% على الإدخال عند تطابق المخزن). لا حاجة إلى تفعيله.

DeepSeek

يطبّق DeepSeek تخزينه المؤقت الخاص للبادئات مع خصم 75% على الإدخال عند تطابق المخزن، مما يجعله أكثر المزودين فعالية من حيث التكلفة للمحادثات الطويلة وسير العمل الوكيلي متعدد الخطوات.

Ollama

يعمل Ollama محليًا ولا يحتوي على طبقة تخزين مؤقت.

لماذا عديم الحالة

تعتمد ثلاث خصائص على التصميم عديم الحالة، وفقدان أي منها سيُضرّ بالبنية.

تبديل النماذج

يستدعي المهاد أيّ نموذج دماغ اخترته — DeepSeek أو Anthropic أو OpenAI أو Ollama — ولا يوجد تدرّج تلقائي بينها. لكن لأن التطبيق يمتلك مصفوفة الرسائل الكاملة، فإن تبديل نموذج دماغك في منتصف المحادثة يعمل ببساطة: يحصل النموذج الجديد على السياق الكامل في دوره التالي مباشرةً، دون خيط يُهاجَر. (يعتمد وضع سير العمل على الخاصية نفسها — يُسلَّم كل وكيل سياقًا كاملًا مكتفيًا بذاته، على أيّ نموذج اختاره له القائد.) أما واجهات برمجة التطبيقات القائمة على الخيوط فتجعل ذلك مستحيلًا.

الخصوصية

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

التحكم في السياق

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

الاستمرارية على جانب التطبيق فقط

تُحفظ المحادثات محليًا في ~/.wolffish/workspace/brain/conversations/ بصيغة ملفات JSON تحتوي على سجل الرسائل الكامل، ومقاطع التدفق، وتوقيتات الأدوات، والمرفقات. تحمل كل رسالة معرّفًا ثابتًا id، ويمرّ كل كاتب عبر دمج مفتاحه هذا المعرّف — فنسختا المحادثة الواحدة (رسالة قناة تحطّ بينما الخيط نفسه يدير دورًا في التطبيق) تتصالحان رسالةً رسالة بدل أن يفوز آخر من حفظ، ولا يمكن لنسخة قديمة أن تُنقص النص أبدًا. يعيش الملخص المتجدد في الملف نفسه ({summary, summarizedThroughMessage, summarizedThroughMessageId}) كعدسة وقت قراءة — صيغة المعرّف تثبّت حدّ الملخص إلى رسالة بعينها فلا يزحزحه دمج، والرسائل الأصلية لا تُعدَّل ولا تُحذَف أبدًا، وتعرض صفحة السجل (History) دائمًا النص الكامل دون مساس. هذا محلي بالكامل — لا يرى المزودون أبدًا معرّف محادثة ولا يستأنفون من حالة مخزَّنة. التطبيق هو مصدر الحقيقة. والمزودون مجرد حوسبة عديمة الحالة.