المدوّنة

إبقاء جولات الوكيل كثيفة الصور ضمن الذاكرة

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

كيف يرى الوكيل الصور

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

الـجولة هي كل ما يفعله الوكيل استجابةً لرسالة واحدة منك. وخلال الجولة يستدعي الوكيل النموذج مراراً: يفكّر، ويشغّل أداة، ويرى النتيجة، ثم يفكّر من جديد. كل استدعاء من هذه يرسل المحادثة حتى تلك اللحظة، بما فيها صور الجولة، مشفّرة كنص (بترميز base64، وهذا يجعلها أكبر بنحو الثلث).

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

السبب الأول: كل استدعاء أعاد إرسال الصور بحجمها الكامل

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

ولم يكن إرسال الحجم الكامل يحقق أي فائدة. النموذج يصغّر الصور بنفسه إلى نحو 1,300 بكسل على الضلع الأطول، فالبكسلات الإضافية لا تكلّف سوى الذاكرة ووقت الرفع.

الحل: صغّر مرة واحدة، أرسل صغيراً

  • تُحوَّل الصور التي يتجاوز حجمها 400 كيلوبايت إلى JPEG بضلع أطول لا يتجاوز 1,568 بكسل قبل إرسالها. أما الصور الأصغر فتُرسل كما هي.
  • يستخدم التحويل ImageMagick، المتوفر في كل بيئة Mythex، ويعمل مرة واحدة لكل ملف. الجولة التي تعرض المسحات نفسها في كل استدعاء تعيد استخدام النسخة المصغّرة. يُفهرس التخزين المؤقت بمسار الملف وحجمه وتاريخ تعديله، فالملف المعدَّل يُحوَّل من جديد، ولهذا التخزين حد حجم خاص به حتى لا يصبح هو نفسه ما يملأ الذاكرة.
  • تنخفض ميزانية الصور في استدعاء نموذج واحد من 16 ميغابايت إلى 6 ميغابايت.

أصبحت المسحات الست نفسها تكلّف 4.4 ميغابايت في كل استدعاء بدلاً من 19.7 ميغابايت.

السبب الثاني: عميل النموذج لم يُطلق أي طلب

لم يكن حجم كل طلب هو المشكلة وحده. كانت الذاكرة تنمو أيضاً استدعاءً بعد استدعاء. في بيئة الاختبار (staging) لدينا، احتفظت الجولة نفسها بـ369 ميغابايت من الذاكرة الحية حتى بعد تجميع كامل للمهملات، أي بعد أن يكون كل ما لا يُستخدم قد حُرّر. وأظهرت عينات الكومة أن كل النمو كان في الجزء من مكتبة عميل النموذج الذي يرمّز أجسام الطلبات.

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

وهكذا بقي كل طلب في الجولة متصلاً بإشارة الجولة طوال مدتها: المستمع، الذي يحمل المتحكم الخاص بالطلب، الذي يحمل الطلب، الذي يحمل جسم الطلب كاملاً بصوره.

الحل: إشارة واحدة لكل طلب

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

تغطي الاختبارات الأجزاء الثلاثة:

  • بعد 12 استدعاءً، لا يبقى أي مستمع على إشارة الجولة. قبل الإصلاح كانت 12.
  • عبر 15 طلباً بحجم 8 ميغابايت لكل منها، تبقى الذاكرة مستقرة. قبل الإصلاح كانت تنمو بـ128 ميغابايت.
  • ما زال الضغط على إيقاف يُلغي طلباً في منتصف تدفقه.

السبب الثالث: التتبّع كان يحتفظ بمدخلات كل استدعاء

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

الحل: تفريغ الصور بعد عودة الاستدعاء

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

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

يشغّل اختبار رسم الوكيل البياني تحت بث الأحداث نفسه، مع صورة بحجم 4 ميغابايت في كل استدعاء. بدون الإصلاح نمت الذاكرة بـ77 ميغابايت عبر 16 استدعاءً. ومعه تبقى الذاكرة مستقرة.

ما استخلصناه

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

هذه ثاني قصة ذاكرة تتعلق بالوكيل في وقت قصير؛ والأولى كانت تسمية تقدّم أُعيد إرسالها 41,000 مرة. إذا أردت معرفة ما هو الوكيل وكيف يعمل، فراجع دليلنا عن وكلاء الذكاء الاصطناعي ووثائق المحادثة.

Mythex · Pricing · ابنِ أي شيء بالذكاء الاصطناعي · قوالب المواقع والتطبيقات · مقارنات Mythex · مصطلحات بناء التطبيقات بالذكاء الاصطناعي · أدوات مجانية لبناء التطبيقات بالذكاء الاصطناعي · English

English አማርኛ Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)