Блог

Агентски ходове с много изображения, които се побират в паметта

Един агентски ход в продукция изчерпа паметта при 952 MB, докато изрязваше продукти от шест сканирания на каталог и разглеждаше изрязаните части. Нямаше едно изтичане — имаше три. Всяко извикване към модела изпращаше наново изображенията на хода в пълен размер; библиотеката, която използваме за извикване на модела, пазеше всяка заявка жива до края на хода; а трасирането на агентската рамка пазеше входовете на всяко извикване, включително изображенията, за целия ход. Поправихме и трите: изображенията се смаляват, преди да бъдат изпратени, а изображенията на всяко извикване се освобождават веднага щом то приключи.

Как агентът вижда изображенията

Когато създавате с Mythex, агентът работи в облачната sandbox среда на проекта ви. Той може да разглежда изображения — скрийншот, който прикачите, макет, файл в проекта ви или изображение, което сам току-що е създал — като ги изпраща към модела заедно с разговора.

Ход е всичко, което агентът прави в отговор на едно ваше съобщение. В рамките на хода агентът извиква модела много пъти: мисли, пуска инструмент, гледа резултата, мисли отново. Всяко от тези извиквания изпраща досегашния разговор, а това включва изображенията на хода, кодирани като текст (base64, което ги прави около една трета по-големи).

Ходът, който се срина, вършеше нещо разумно. Взе шест сканирания на каталог, около 2,4 MB всяко, изряза отделни продукти от тях и продължаваше да чете изрязаните части обратно, за да ги провери. Това са много извиквания към модела, всяко от които носи няколко големи изображения.

Причина 1: всяко извикване изпращаше наново изображенията в пълен размер

Всяко извикване към модела изграждаше отново тялото на заявката с изображенията на хода в пълен размер — около 20 MB base64 при всяко извикване. Тялото се изгражда като един низ в паметта на агента, така че всяко извикване заделяше още около 20 MB.

Изпращането в пълен размер дори не носеше полза. Моделът сам смалява изображенията до около 1300 пиксела по по-дългата страна, така че допълнителните пиксели само харчат памет и време за качване.

Решението: смаляване веднъж, изпращане малко

  • Изображенията над 400 KB се превръщат в JPEG с най-много 1568 пиксела по по-дългата страна, преди да бъдат изпратени. По-малките изображения се изпращат както са.
  • Превръщането използва ImageMagick, който е в всяка Mythex sandbox среда, и се изпълнява веднъж за всеки файл. Ход, който показва едни и същи сканирания при всяко извикване, използва смаленото копие повторно. Кешът е ключиран по пътя на файла, размера и времето на последна промяна, така че редактиран файл се превръща отново, а кешът има собствен таван на размера, за да не стане сам той причината паметта да се запълни.
  • Бюджетът за изображения в едно извикване към модела пада от 16 MB на 6 MB.

Същите шест сканирания сега струват 4,4 MB на извикване вместо 19,7 MB.

Причина 2: клиентът към модела никога не освобождаваше заявка

Размерът на всяка заявка беше само част от проблема. Паметта също растеше от извикване към извикване. В нашата staging среда същият вид ход държеше 369 MB жива памет дори след пълно събиране на боклука — момента, в който всичко недостижимо е освободено. Снимането на heap показа, че целият растеж е в частта от клиентската библиотека към модела, която кодира телата на заявките.

Причината беше слушател за прекъсване. Когато натиснете Stop, сигналът за прекъсване на хода се задейства и всяка заявка, която го слуша, се отменя. Ние подавахме този един сигнал за целия ход на всяка заявка. Клиентската библиотека добавя слушател „abort“ към всеки сигнал, който получи — и никога не го премахва.

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

Решението: един сигнал за всяка заявка

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

Тестовете покриват и трите части:

  • След 12 извиквания няма слушатели да останат върху сигнала на хода. Преди поправката имаше 12.
  • При 15 заявки по 8 MB всяка паметта остава права. Преди растеше с 128 MB.
  • Натискането на Stop все още прекъсва заявка по средата на нейния поток.

Причина 3: трасирането пазеше входовете на всяко извикване

Снимка на heap показа трети държател: около 6 MB, пазени на всяко извикване към модела. Това идваше от поточното предаване на събития на агентската рамка. Тя записва всяко извикване към модела в хода като дете на хода, включително входовете, докато ходът не завърши. Всяко изображение, прикачено към всяко извикване, оставаше в паметта заедно с него.

Решението: изчистване на изображенията веднага след връщане на извикването

Изображенията се прикрепят само към съобщенията, построени за конкретно извикване към модела. Никога не се съхраняват в запазеното състояние на разговора. Затова след като извикването върне резултат, е безопасно да се изтрие данните на изображенията в тези съобщения. Трасирането запазва текстов запис на извикването; пикселите се махат.

Една подробност беше решаваща: изображенията трябва да се изчистват на място. Трасьорът може да достигне същите данни на изображението през повече от една референция в съобщението, така че подмяната със нов, празен списък би оставила оригинала — с пикселите — все още достижим. Запазеното състояние на разговора никога не се променя.

Тест пуска графа на агента под същото поточно предаване на събития с изображение от 4 MB при всяко извикване. Без поправката паметта растеше с 77 MB за 16 извиквания. С нея паметта остава права.

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

  • Проблемите с паметта могат да идват на слоеве. Три отделни причини държаха изображения твърде дълго и трите трябваше да се махнат, за да остане ходът в рамките на паметта.
  • Всичко, което подадете на библиотека, може да бъде запазено. И сигналът, и трасирането надживяваха извикванията, на които бяха подадени. Когато паметта расте на извикване, гледайте кои дълготрайни обекти извикването докосва.
  • Не изпращайте това, което другата страна така или иначе изхвърля. Пикселите, които моделът би отхвърлил, ни струваха памет при всяко извикване.
  • Тествайте паметта директно. Всяка поправка дойде с тест, който измерва растеж на heap или броя на слушателите, така че регресията се вижда като число, а не като срив.

Това е втората история за паметта, свързана с агента, за кратко време; първата беше етикет за прогрес, изпратен 41 000 пъти. Ако искате да научите повече за това какво е агентът и как работи, вижте нашето ръководство за AI агенти и документацията за чата.

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