نظرة عامة

تنتشر في مجتمعات المطورين نصيحة تقول: “صمِّم الحلقة قبل أن تُشغِّلها.” الفكرة في جوهرها بسيطة: الحلقة سيئة التصميم تحرق الرموز وتُسلِّم نتائج لا نفع منها. كتابة توجيه جيد لمرة واحدة شيء، وتصميم نظام يُغذِّي ذلك التوجيه لوكيل بصورة متكررة شيء مختلف تماماً.

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

تدير ThakiCloud عشرات الحلقات غير المراقبة ومهام الوكلاء المتكررة في منصة SaaS للذكاء الاصطناعي والتعلم الآلي على Kubernetes. في هذه العملية واجهنا حادثة بلغت تكلفتها 700 دولار في يوم واحد، وحوَّلنا كل ما تعلَّمناه منها مباشرة إلى حواجز أمان تعمل في بيئة الإنتاج اليوم. هذا الموضوع ليس توجهاً نظرياً بالنسبة لنا؛ إنه تحدٍّ تشغيلي نواجهه كل يوم. يستعرض هذا المقال ما يجب تصميمه قبل تشغيل الحلقة وكيف طبَّقنا هذه الدروس على منصة حقيقية.

ما هي هندسة الحلقات

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

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

افتراض آخر ضروري: يجب أن تعرف الحلقة كيف تتقارب أو تتوقف. حلقة بلا شرط انتهاء ليست أتمتة؛ إنها تسرُّب. نصف تصميم الحلقة هو تعريف “متى تتوقف.”

أربعة أشياء تُصمَّم قبل التشغيل

البدء بحلقة بلا تصميم هو النمط الأكثر شيوعاً للفشل. تحديد الأمور الأربعة التالية بصراحة قبل التشغيل يمنع معظم تسرُّب الرموز وانهيار الجودة.

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

ثانياً: اكتب ملف الذاكرة قبل تشغيل الحلقة. احتفظ بملف markdown واحد أو لوحة تسجِّل ما أُنجز وما هو التالي وما جُرِّب وفشل. هذا الملف هو العمود الفقري للحلقة. إذا قرأ الوكيل هذا الملف وحدَّثه في كل تكرار، لن تضيع الحالة حتى مع امتداد السياق.

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

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

[ 1. تعريف الهدف ]  شرط انتهاء قابل للتحقق (مثال: اجتياز الاختبارات)
        |
        v
[ 2. ملف الذاكرة ]  العمود الفقري: منجَز / تالٍ / جُرِّب وفشل
        |
        v
[ 3. تشغيل الحلقة ] --- إيجاد عمل -> إرسال الوكيل -> نتيجة ---+
        ^                                                        |
        |                                                        v
[ 4. فصل المُتحقِّق ]  وكيل إنتاج ≠ وكيل حكم -------> [ اجتياز البوابة؟ ]
        |                                                        |
        |  فشل -> التكرار التالي                                 | نجاح
        +--------------------------------------------------------+
        |
        v
[ 5. الحد الأقصى ]  أقصى تكرار · ميزانية الرموز · الإغلاق -> توقف

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

تكلفتان: الرموز والانتباه

تصل فاتورة الحلقة بعملتين: الرموز وانتباه الإنسان. تشغيل واحد غير مراقب قد يحرق ملايين الرموز، والحالة الوحيدة التي يُبرِّر فيها ذلك هي حين تشتري تلك الرموز شيئاً أكثر قيمة من تكلفتها.

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

لذا فإن أول سؤال يجب طرحه عند تصميم الحلقة هو: “هل يحتاج هذا فعلاً إلى حكم النموذج في كل نبضة؟” إذا كانت الإجابة لا، شغِّل تلك الحلقة بسكريبت ومجدوِّل بلا نموذج، واستدعِ النموذج فقط حين يُحفِّز ذلك إنسان أو حدث. إذا كان النموذج ضرورياً حقاً في كل تكرار، استخدم مستوى نموذج أدنى واحفظ الحالة في ملف واجعل كل إيقاظ يبدأ بأقل قدر من السياق.

ما تعلَّمته ThakiCloud من حادثة الـ 700 دولار

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

حوَّلنا ما تعلمناه مباشرة إلى حواجز أمان. أولاً: أخرجنا المراقبة المتكررة من الحلقة الساخنة للنموذج ونقلناها إلى مجدوِّل (cron, launchd). مراقبو الأسعار ومقارنات الحالة يعملون الآن كسكريبتات بلا نموذج، ولا يُرسلون إشعاراً لقناة التقارير إلا عند اكتشاف شيء غير معتاد. تكلفة النموذج لهذه الأعمال أصبحت صفراً.

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

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

اختيار الأداة: فرِّق بين الهدف والحلقة والجدول

أكثر ما نؤكد عليه عند تصميم الحلقات هو أنه حين يأتي طلب “كرِّر / آلِّم / استمر”، ابدأ باختيار الأداة المناسبة. الثلاثة آليات مختلفة.

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

تجاهل هذه الفروق يُفضي إلى حوادث. تراكم مراقبة 24 ساعة في حلقة بفاصل زمني يُفجِّر التكاليف. وضع التكرار في أوقات محددة ضمن وضع الهدف يتركه بلا معيار تقارب فيتخبَّط. لذا قبل البدء نطلب إجابة لـ: “هل هذا هدف أم حلقة أم جدول؟”

التطبيق على منصة ThakiCloud للذكاء الاصطناعي والتعلم الآلي على K8s

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

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

من منظور المنصة، هذا قدرة تنافسية. في بنية تُصفِّف أعباء GPU عبر Kueue على Kubernetes وتعزل خدمة النماذج لكل مستأجر، القدرة على فرض تكاليف الحلقات وشروط انتهائها في الكود هي الأساس الذي يُمكِّن العملاء في بيئاتهم الداخلية من تشغيل الوكلاء بأمان. الوكيل المستقل الذي لا تُسيطر على تكاليفه مثير للإعجاب في العروض التوضيحية ومصدر خطر في الإنتاج. ما نبيعه هو التصميم التشغيلي الذي يحوِّل ذلك الخطر إلى حواجز أمان.

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

القيود والاعتراضات

هندسة الحلقات ليست حلاً شاملاً. أقوى اعتراض هو أن ليس كل مهمة مسألة حلقة. إدخال سؤال آني أو تعديل ملف واحد قسراً في حلقة يُضيف تكاليف تصميم دون أي مكسب. الحلقات ذات قيمة فقط للعمل المتكرر والقابل للتحقق.

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

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

في نهاية المطاف، جوهر هندسة الحلقات ليس توسيع الاستقلالية بل رسم حدودها بوضوح. الانضباط في تحديد ما تُفوِّضه وأين تتوقف وبماذا تتحقق قبل التشغيل هو ما يُميِّز الحلقة التي لا تحرق الرموز عن تلك التي تتحول إلى عبء.

المصادر