Блог

Грешката с липсваща памет, скрита в етикет за напредък

Една вечер в края на септември AI агентът в работното пространство на един потребител се срина с грешка out-of-memory по средата на ход. Очевидните заподозрени — твърде много подагенти, работещи едновременно, или контекст, който е пораснал твърде голям — бяха грешни. Истинската причина беше етикет за статус: докато моделът стриймваше голяма shell команда по няколко символа наведнъж, ние изпращахме наново цялата команда до този момент като етикет за напредък при всяко парче. Една команда от 124 KB се превърна в около 41 000 събития и приблизително 690 MB изчакващи в опашка низове.

Как агентът стриймва работата си

Когато строите в Mythex, агентът работи в частния облачен пясъчник на проекта ви. Докато моделът пише, изходът му се стриймва обратно към браузъра ви: текстът се появява дума по дума, а когато изпълни инструмент — например shell команда, която записва файл — виждате етикет за него, който се обновява на живо, за да знаете какво прави.

Моделът стриймва на малки парчета. При модела, който ползвахме, тези парчета често бяха само три символа дълги.

Първите хипотези бяха грешни

Сривът приличаше на проблем с мащабирането, затова започнахме оттам.

  • Паралелни подагенти? Ходът бе използвал само двама, всеки с около 1,5 MB състояние. Недостатъчно.
  • Задържани трасировки? Нашето проследяване пазеше дърво на изпълнението в паметта, но то не беше близо до размера на heap-а при срива.

И двете бяха правдоподобни истории и двете бяха евтини за вярване. Нито една не възпроизвеждаше срива. Урокът, който продължаваме да научаваме отново: хипотезата не е причина, докато не възпроизведе провала.

Възпроизвеждане наистина

Създадохме временен пясъчник със същите лимити на паметта като продукцията и фалшив модел, който стриймваше голям файл на реалистични три-символни парчета. Направихме и четящата страна на сокета бавна, като реална мрежа.

Това свърши работа. Heap-ът нарасна и процесът умря със същата грешка.

Механизмът беше прост, след като можехме да го гледаме. Докато моделът пишеше голяма команда — в случая heredoc, който записваше файл от 124 KB — нашият стрийминг код обновяваше етикета на инструмента при всяко парче. Етикетът не беше новите три символа; беше цялата команда до момента. Така събитията растяха: 3 символа, после 6, после 9, … до 124 KB, около 41 000 пъти. Сокетът не можеше да изпраща толкова бързо, колкото се произвеждаха, и те се трупаха в буфера му за писане като низове — около 690 MB от тях.

Поправката

  • Ограничете етикета. Етикетът за статус трябва само да казва какво се случва. Вече е ограничен до 200 символа, а частичната команда се сканира отново по-рядко.
  • Спрете квадратичното конкатениране. Слепването на стриймнатите парчета с повторно string конкатениране е O(n²) за големи изходи. Преминахме към подход на парчета, който добавя в линейно време.

После потърсихме всичко друго, което може да расте безкрайно при поток от изход, и го ограничихме:

  • Живият изход на команда, показван в чата, се групира и се пази последните 8000 символа.
  • Отделните редове на събития са ограничени до 4 MB.
  • Буферът за повторно възпроизвеждане, който браузър ползва, за да се догони след повторно свързване, е ограничен до 8 MB на проект.
  • Старите контролни точки се изчистват, докато ходът върви, като се пази най-новото състояние и опорните точки, от които се нуждаят по-ранните ходове.

Тестване на потоци честно

Две неща направиха тестването по-трудно, отколкото трябваше да е:

  1. Реалните модели не сътрудничат. Помолете модел да изведе огромен файл и той обикновено откаже, ще обобщи или ще го запише по-разумно. За да тествате потоци, ви трябва скриптиран модел, който прави точно каквото му кажете, работещ през реалния агентен код.
  2. Скриптовете трябва да се държат като модели. Първият ни скриптиран модел ползваше един и същ ID на отговор при всеки отговор, така че агентната рамка третираше всеки отговор като замяна на предишния и приключваше ходовете рано. Изглеждаше като бъг в обновяването на UI. Не беше — беше тестовата среда, която ни лъжеше. Трябваше също да наложим реалния лимит на контекста на модела в скрипта, иначе числата за памет бяха нереалистични.

Какво взехме от това

  • Стрийминговите UI-и умножават малките грешки. Всичко, което изпращате „на парче“, се изпраща десетки хиляди пъти. Изпращайте разлики или ограничавайте полезния товар.
  • Ограничавайте всеки буфер, който минава през бавна граница. Сокетите, логовете за повторно възпроизвеждане и контролните точки имат нужда от таван.
  • Възпроизвеждайте, преди да поправяте. Първите ни две обяснения звучаха вярно и бяха грешни.

Ако сте виждали наскоро много дълъг файл да се появява в чата на 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 简体中文 繁體中文(香港) 繁體中文(台灣)