Блог

Як утримати ходи агента з великою кількістю зображень у межах пам'яті

Хід агента у продакшні вичерпав пам'ять на 952 МБ, коли він вирізав товари з шести сканів каталогу і переглядав свої вирізки. Це була не одна витік пам'яті, а три. Кожен виклик моделі повторно надсилав зображення ходу в повному розмірі; бібліотека, яку ми використовуємо для викликів моделі, зберігала кожен запит живим до завершення ходу; а трасування фреймворку агента зберігало вхідні дані кожного виклику, зображення включно, протягом усього ходу. Ми виправили всі три: зображення зменшуються перед відправкою, а зображення кожного виклику звільняються одразу після його завершення.

Як агент бачить зображення

Працюючи на Mythex, агент виконує роботу в хмарній пісочниці вашого проєкту. Він може дивитися на зображення — скриншот, який ви прикріпили, макет, файл у вашому проєкті або зображення, яке він щойно створив сам, — надсилаючи їх моделі разом із розмовою.

Хід — це все, що агент робить у відповідь на одне ваше повідомлення. У межах ходу агент багато разів звертається до моделі: думає, запускає інструмент, дивиться на результат, думає знову. Кожен такий виклик надсилає розмову, що накопичилася, а це включає зображення ходу, закодовані як текст (base64, що робить їх приблизно на третину більшими).

Хід, що впав, робив цілком розумну річ. Він взяв шість сканів каталогу, близько 2,4 МБ кожен, вирізав окремі товари з них і знову читав свої вирізки для перевірки. Це багато викликів моделі, кожен з яких містив кілька великих зображень.

Причина 1: кожен виклик повторно надсилав зображення в повному розмірі

Кожен виклик моделі перебудовував тіло запиту з зображеннями ходу в повному розмірі — близько 20 МБ base64 на виклик. Тіло будувалося як один рядок у пам'яті агента, тож кожен виклик виділяв ще близько 20 МБ.

Надсилання в повному розмірі навіть не давало нічого корисного. Модель сама зменшує зображення приблизно до 1300 пікселів по довшій стороні, тож зайві пікселі лише витрачали пам'ять і час на завантаження.

Виправлення: зменшити один раз, надсилати малим

  • Зображення понад 400 КБ тепер перетворюються на JPEG з максимумом 1568 пікселів по довшій стороні перед відправкою. Менші зображення надсилаються як є.
  • Перетворення виконує ImageMagick, який є в кожній пісочниці Mythex, і працює один раз на файл. Хід, що показує ті самі скани при кожному виклику, повторно використовує зменшену копію. Кеш прив'язаний до шляху файлу, розміру та часу зміни; змінений файл перетворюється знову, і кеш має власний ліміт розміру, щоб сам не став причиною вичерпання пам'яті.
  • Бюджет зображень в одному виклику моделі зменшено з 16 МБ до 6 МБ.

Ті самі шість сканів тепер коштують 4,4 МБ на виклик замість 19,7 МБ.

Причина 2: клієнт моделі ніколи не відпускав запит

Розмір кожного запиту був лише частиною проблеми. Пам'ять також зростала від виклику до виклику. У нашому staging-середовищі той самий тип ходу утримував 369 МБ живої пам'яті навіть після повного збирання сміття — моменту, коли все недосяжне вже звільнено. Вибірка купи показала, що все зростання припадає на ту частину бібліотеки клієнта моделі, яка кодує тіла запитів.

Причиною був слухач переривання. Коли ви натискаєте «Стоп», сигнал переривання ходу спрацьовує, і всі запити, що його слухають, скасовуються. Ми передавали один сигнал на весь хід кожному запиту. Клієнтська бібліотека додає слухач «abort» до будь-якого сигналу, який їй передали, і ніколи його не видаляє.

Тож кожен запит ходу залишався досяжним через сигнал ходу, поки хід тривав: слухач тримав контролер запиту, той тримав сам запит, а запит тримав увесь тіло з зображеннями.

Виправлення: один сигнал на запит

Тепер кожен запит отримує власний сигнал. Він зв'язується з сигналом ходу лише на час виконання цього запиту — для потокової відповіді до прочитання останнього фрагмента — і відв'язується одразу після. Стоп усе ще досягає запиту, що виконується, але сигнал ходу тримає лише один слухач одночасно.

Тести перевіряють усі три частини:

  • Після 12 викликів на сигналі ходу не залишається слухачів. До виправлення їх було 12.
  • Протягом 15 запитів по 8 МБ кожен пам'ять лишається стабільною. До виправлення вона зростала на 128 МБ.
  • Натискання «Стоп» і далі перериває запит посеред його потоку.

Причина 3: трасування зберігало вхідні дані кожного виклику

Снімок купи показав третього утримувача: близько 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 简体中文 繁體中文(香港) 繁體中文(台灣)