Blog

Sådan holder vi billedtunge agent-forløb inden for hukommelsen

Et agent-forløb i produktion løb tør for hukommelse ved 952 MB, mens det klippede produkter ud af seks katalogscanninger og kiggede på sine udklip. Der var ikke ét læk — der var tre. Hvert kald til modellen sendte forløbets billeder igen i fuld størrelse; biblioteket vi bruger til at kalde modellen, holdt hver forespørgsel i live, indtil forløbet var slut; og agent-frameworkets tracing gemte hvert kalds input, billeder inklusive, for hele forløbet. Vi rettede alle tre: billeder formindskes, før de sendes, og hvert kalds billeder frigives, så snart kaldet er færdigt.

Sådan ser agenten billeder

Når du bygger på Mythex, arbejder agenten inde i dit projekts cloud-sandbox. Den kan kigge på billeder — et skærmbillede du vedhæfter, et mockup, en fil i dit projekt eller et billede, den lige selv har produceret — ved at sende dem til modellen sammen med samtalen.

Et forløb er alt, agenten gør som svar på én besked fra dig. Inden for et forløb kalder agenten modellen mange gange: tænker, kører et værktøj, kigger på resultatet, tænker igen. Hvert af disse kald sender samtalen indtil videre, og den inkluderer forløbets billeder, kodet som tekst (base64, som gør dem omkring en tredjedel større).

Forløbet, der styrtede, gjorde noget fornuftigt. Det tog seks katalogscanninger, cirka 2,4 MB hver, klippede enkelte produkter ud af dem og blev ved med at læse sine udklip tilbage for at kontrollere dem. Det er mange modelkald, hver med flere store billeder.

Årsag 1: hvert kald sendte billeder i fuld størrelse igen

Hvert modelkald genopbyggede sin forespørgselskrop med forløbets billeder i fuld størrelse — cirka 20 MB base64 pr. kald. Kroppen bygges som én streng i agentens hukommelse, så hvert kald allokerede endnu cirka 20 MB.

At sende i fuld størrelse gav heller ikke noget. Modellen skalerer selv billeder ned til cirka 1.300 pixels på den lange side, så de ekstra pixels koster kun hukommelse og uploadtid.

Rettelsen: formindsk én gang, send småt

  • Billeder over 400 KB konverteres nu til en JPEG på højst 1.568 pixels på den lange side, før de sendes. Mindre billeder sendes, som de er.
  • Konverteringen bruger ImageMagick, som følger med i hver Mythex-sandbox, og køres én gang pr. fil. Et forløb, der viser de samme scanninger i hvert kald, genbruger den formindskede kopi. Cachen er nøglet på filens sti, størrelse og ændringstidspunkt, så en redigeret fil konverteres igen, og den har sin egen størrelsesgrænse, så den ikke selv kan blive det, der fylder hukommelsen.
  • Budgettet for billeder i ét modelkald falder fra 16 MB til 6 MB.

De samme seks scanninger koster nu 4,4 MB pr. kald i stedet for 19,7 MB.

Årsag 2: modelklienten slap aldrig en forespørgsel

Størrelsen på hver forespørgsel var kun en del af det. Hukommelsen voksede også kald efter kald. På vores staging-miljø holdt samme slags forløb 369 MB levende hukommelse, selv efter en fuld garbage collection — det punkt, hvor alt, der ikke kan nås, er frigivet. Heap-sampling placerede al væksten i den del af modelklientbiblioteket, der koder forespørgselskroppe.

Årsagen var en abort-lytter. Når du trykker Stop, udløses forløbets abort-signal, og hver forespørgsel, der lytter på det, annulleres. Vi gav ét signal for hele forløbet til hver forespørgsel. Klientbiblioteket tilføjer en „abort“-lytter til det signal, det får — og fjerner den aldrig.

Så hver forespørgsel i et forløb forblev tilgængelig fra forløbets signal, så længe forløbet varede: lytteren, som holdt forespørgslens controller, som holdt forespørgslen, som holdt hele forespørgselskroppen med dens billeder.

Rettelsen: ét signal pr. forespørgsel

Hver forespørgsel får nu sit eget signal. Det er kun koblet til forløbets signal, mens den pågældende forespørgsel kører — for et streamet svar, indtil det sidste stykke er læst — og afkobles straks efter. Stop rammer stadig den forespørgsel, der er i gang, men forløbets signal holder kun én lytter ad gangen.

Testene dækker alle tre dele af det:

  • Efter 12 kald er der ingen lyttere tilbage på forløbets signal. Før rettelsen var der 12.
  • Over 15 forespørgsler på 8 MB hver forbliver hukommelsen flad. Før voksede den med 128 MB.
  • Tryk på Stop afbryder stadig en forespørgsel midt i dens stream.

Årsag 3: tracing gemte hvert kalds input

Et heap-snapshot viste en tredje holder: cirka 6 MB pr. modelkald. Denne kom fra agent-frameworkets event-streaming. Den registrerer hvert modelkald i et forløb som et barn af forløbet, input inkluderet, indtil forløbet slutter. Hvert billede, der var vedhæftet hvert kald, blev i hukommelsen sammen med det.

Rettelsen: tøm billederne, når kaldet er returneret

Billeder bliver kun vedhæftet til beskederne, der er bygget til et bestemt modelkald. De gemmes aldrig i samtalens gemte tilstand. Så når et kald er returneret, er det sikkert at tømme billeddataene i disse beskeder. Tracen beholder en tekstoptegnelse af kaldet; pixels forsvinder.

Ét detalje var vigtigt: billederne skal tømmes på stedet. Traceren kan nå de samme billeddata via mere end én reference på en besked, så hvis vi byttede ud med en ny, tom liste, ville originalen — pixels og alt — stadig være tilgængelig. Den gemte samtaletilstand ændres aldrig.

En test kører agentens graf under den samme event-streaming med et 4 MB billede på hvert kald. Uden rettelsen voksede hukommelsen med 77 MB over 16 kald. Med den forbliver hukommelsen flad.

Hvad vi tog med

  • Hukommelsesproblemer kan komme i lag. Tre adskilte årsager holdt hver billeder for længe, og alle tre skulle væk, før forløbet holdt sig inden for hukommelsen.
  • Alt, du giver til et bibliotek, kan blive gemt. Et signal og en trace overlevede begge de kald, de var givet til. Når hukommelsen vokser pr. kald, så kig på hvilke langlevende objekter kaldet rører ved.
  • Send ikke det, modtageren smider væk. Pixels, modellen alligevel ville kassere, kostede os hukommelse ved hvert kald.
  • Test hukommelsen direkte. Hver rettelse kom med en test, der måler heap-vækst eller antal lyttere, så en regression viser sig som et tal, ikke et nedbrud.

Dette er den anden hukommelseshistorie om agentens output på kort tid; den første var en fremdriftsetiket, der blev sat i kø 41.000 gange. Hvis du vil vide mere om, hvad agenten er, og hvordan den virker, se vores guide til AI-agenter og chat-dokumentationen.

Mythex · Pricing · Byg hvad som helst med AI · Skabeloner til websites og apps · Mythex sammenlignet · Ordliste for app-bygning med AI · Gratis værktøjer til app-bygning med AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština 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 简体中文 繁體中文(香港) 繁體中文(台灣)