Блог

Збій через брак пам'яті, захований у мітці прогресу

Одного вечора наприкінці вересня агент ШІ в робочому просторі одного з користувачів аварійно зупинився з помилкою нестачі пам'яті посеред ходу. Очевидні підозри, забагато субагентів, що працюють одночасно, або контекст, який надто виріс, виявилися хибними. Справжньою причиною була мітка статусу: поки модель передавала велику shell-команду по кілька символів, ми повторно надсилали всю команду на цей момент як мітку прогресу з кожним фрагментом. Одна команда завбільшки 124 КБ перетворилася приблизно на 41 000 подій і близько 690 МБ рядків у черзі.

Як агент передає свою роботу

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

Модель передає дані невеликими шматками. З моделлю, яку ми використовували, ці шматки часто були завдовжки три символи.

Перші гіпотези були хибними

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

  • Паралельні субагенти? У ході було лише два, кожен займав близько 1,5 МБ стану. Недостатньо.
  • Збережені трасування? Наше трасування зберігало дерево запусків у пам'яті, але воно було набагато меншим за купу в момент збою.

Обидві історії були правдоподібними і їх було легко прийняти. Жодна не відтворювала збій. Урок, який ми постійно знову засвоюємо: гіпотеза не є причиною, доки вона не відтворює збій.

Відтворення по-справжньому

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

Це спрацювало. Купа зростала, і процес загинув із тією самою помилкою.

Механізм був простим, щойно ми могли його спостерігати. Поки модель писала велику команду (у цьому випадку heredoc, що записував файл 124 КБ), наш код стрімінгу оновлював мітку інструмента з кожним шматком. Мітка містила не нові три символи, а всю команду на цей момент. Тож події росли: 3 символи, потім 6, потім 9, … аж до 124 КБ, близько 41 000 разів. Сокет не встигав відправляти їх так швидко, як вони створювалися, тож вони накопичувалися в його буфері запису рядками, приблизно 690 МБ.

Виправлення

  • Обмежити мітку. Мітка статусу має лише показувати, що відбувається. Тепер її обмежено 200 символами, а частоту повторного сканування часткової команди ми зменшили.
  • Прибрати квадратичну конкатенацію. Склеювання потокових фрагментів повторною конкатенацією рядків дає O(n²) для великих виводів. Ми перейшли на підхід із фрагментами, що додає дані за лінійний час.

Потім ми пошукали все інше, що могло рости без межі під потоком виводу, і обмежили це:

  • Живий вивід команд, який показується в чаті, групується і зберігається лише останні 8 000 символів.
  • Окремі рядки подій обмежені 4 МБ.
  • Буфер повтору, яким браузер надолужує пропущене після перепідключення, обмежений 8 МБ на проєкт.
  • Старі контрольні точки обрізаються, поки йде хід, зберігаючи найновіший стан і опорні точки, потрібні попереднім ходам.

Тестування потоків чесно

Дві речі ускладнили тестування більше, ніж мало бути:

  1. Справжні моделі не співпрацюють. Якщо попросити модель вивести величезний файл, вона зазвичай відмовиться, підсумує або запише його розумніше. Щоб тестувати потоки, потрібна скриптована модель, яка робить саме те, що їй сказали, працюючи через справжній код агента.
  2. Скрипти мають поводитися як моделі. Наша перша скриптована модель використовувала той самий ідентифікатор відповіді на кожне повідомлення, тож фреймворк агента сприймав кожну відповідь як заміну попередньої і завершував ходи раніше. Це виглядало як помилка оновлення інтерфейсу. Насправді це тестова обв'язка брехала нам. Нам також довелося відтворювати реальний ліміт контексту моделі в скрипті, інакше цифри пам'яті були б нереалістичними.

Що ми з цього взяли

  • Потокові інтерфейси примножують дрібні помилки. Усе, що надсилається «на кожен фрагмент», надсилається десятки тисяч разів. Надсилайте дельти або обмежуйте обсяг корисного навантаження.
  • Обмежуйте кожен буфер, що перетинає повільну межу. Сокети, журнали повтору та контрольні точки потребують стелі.
  • Відтворюйте перед виправленням. Наші перші два пояснення звучали переконливо і були хибними.

Якщо нещодавно в чаті Mythex ви бачили дуже довгий файл, який з'явився без зупинки агента, ось частково чому.

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 简体中文 繁體中文(香港) 繁體中文(台灣)