Pagpapanatiling Nasa Memory ang mga Agent Turn na Maraming Larawan
Naubusan ng memory sa 952 MB ang isang agent turn sa production habang nagpuputol ng mga produkto mula sa anim na catalogue scan at tinitingnan ang mga pinutol nito. Hindi iisa ang leak. Tatlo sila. Bawat tawag sa model ay muling ipinadadala ang mga larawan ng turn sa buong laki; pinananatiling buhay ng library na ginagamit namin sa pagtawag sa model ang bawat request hanggang matapos ang turn; at ang tracing ng agent framework ay itinatago ang input ng bawat tawag, kasama ang mga larawan, sa buong turn. Inayos naming lahat ang tatlo: pinaliliit na ang mga larawan bago ipadala, at binibitawan na ang mga larawan ng bawat tawag sa sandaling matapos ito.
Paano nakikita ng agent ang mga larawan
Kapag gumagawa ka sa Mythex, gumagana ang agent sa cloud sandbox ng project mo. Kaya nitong tumingin sa mga larawan, gaya ng screenshot na ikinabit mo, mockup, file sa project mo, o larawang kakagawa lang nito, sa pamamagitan ng pagpapadala nito sa model kasama ng usapan.
Ang turn ay lahat ng ginagawa ng agent bilang tugon sa isang mensahe mo. Sa loob ng isang turn, maraming beses tumatawag ang agent sa model: mag-isip, magpatakbo ng tool, tingnan ang resulta, mag-isip ulit. Bawat tawag na iyon ay nagpapadala ng usapan hanggang sa puntong iyon, kasama ang mga larawan ng turn, na naka-encode bilang text (base64, na nagpapalaki sa mga ito nang mga isang-katlo).
Makatwiran ang ginagawa ng turn na nag-crash. Kumuha ito ng anim na catalogue scan, mga 2.4 MB bawat isa, nagpuputol ng indibidwal na produkto mula sa mga ito, at paulit-ulit na binabasa ang mga pinutol para i-check. Maraming tawag ito sa model, at bawat isa ay may dalang ilang malalaking larawan.
Sanhi 1: bawat tawag ay muling nagpapadala ng buong laki ng larawan
Bawat tawag sa model ay muling binubuo ang request body gamit ang mga larawan ng turn sa buong laki, mga 20 MB ng base64 bawat tawag. Ginagawa ang body bilang isang string sa memory ng agent, kaya bawat tawag ay naglalaan ng panibagong ~20 MB.
Hindi rin nakatulong ang pagpapadala ng buong laki. Ang model mismo ay pinaliliit ang mga larawan sa humigit-kumulang 1,300 pixel sa mas mahabang gilid, kaya ang dagdag na pixel ay nagdaragdag lang sa memory at oras ng upload.
Ang ayos: paliitin nang isang beses, ipadala nang maliit
- Ang mga larawang lampas sa 400 KB ay kino-convert na ngayon sa JPEG na pinakamalaki sa 1,568 pixel sa mahabang gilid bago ipadala. Ang mas maliliit na larawan ay ipinadadala gaya ng dati.
- Gumagamit ang conversion ng ImageMagick, na kasama sa bawat Mythex sandbox, at tumatakbo nang isang beses bawat file. Ang turn na nagpapakita ng parehong scan sa bawat tawag ay muling ginagamit ang napaliit na kopya. Ang cache na ito ay naka-key sa path, laki at oras ng pagbabago ng file, kaya muling kino-convert ang na-edit na file, at may sarili itong limit sa laki para hindi ito maging dahilan ng pagpuno ng memory.
- Bumababa ang budget para sa mga larawan sa isang model call mula 16 MB patungong 6 MB.
Ang parehong anim na scan ngayon ay nagkakahalaga ng 4.4 MB bawat tawag sa halip na 19.7 MB.
Sanhi 2: hindi binibitawan ng model client ang request
Hindi lang ang laki ng bawat request ang problema. Lumalaki din ang memory sa bawat tawag. Sa staging environment namin, ang parehong uri ng turn ay humahawak ng 369 MB ng live na memory kahit pagkatapos ng buong garbage collection, ang puntong nalilinis na ang anumang hindi na maabot. Ayon sa heap sampling, nasa bahagi ng model client library na nag-e-encode ng request body ang buong paglaki.
Ang sanhi ay isang abort listener. Kapag pinindot mo ang Stop, nagpapaputok ang abort signal ng turn, at kinakansela ang bawat request na nakikinig dito. Ipinapasa namin ang iisang signal na iyon sa bawat request. Naglalagay ang client library ng “abort” listener sa anumang signal na ibinigay dito, at hindi ito inaalis kailanman.
Kaya bawat request ng isang turn ay nanatiling maaabot mula sa signal ng turn, hangga't tumatagal ang turn: ang listener, na may hawak sa controller ng request, na may hawak sa request, na may hawak sa buong request body kasama ang mga larawan.
Ang ayos: isang signal bawat request
Bawat request ngayon ay may sariling signal. Naka-link ito sa signal ng turn habang tumatakbo lang ang request na iyon. Para sa streamed na response, hanggang mabasa ang huling chunk, at tinatanggal ang link kaagad pagkatapos. Naaabot pa rin ng Stop ang anumang request na nasa gitna ng pagpapatakbo, pero isang listener lang ang hawak ng signal ng turn sa bawat pagkakataon.
Sakop ng mga test ang tatlong bahaging iyon:
- Pagkatapos ng 12 tawag, walang listener na natitira sa signal ng turn. Bago ang ayos, mayroong 12.
- Sa 15 request na tig-8 MB, nananatiling pantay ang memory. Bago ang ayos, lumaki ito ng 128 MB.
- Naaabort pa rin ng Stop ang request sa gitna ng stream nito.
Sanhi 3: itinatago ng tracing ang input ng bawat tawag
Nagpakita ang heap snapshot ng ikatlong humahawak: mga 6 MB na itinatago bawat tawag sa model. Galing ito sa event streaming ng agent framework. Itinatala nito ang bawat tawag sa model sa isang turn bilang anak ng turn, kasama ang mga input, hanggang matapos ang turn. Nanatili sa memory ang bawat larawang nakakabit sa bawat tawag.
Ang ayos: burahin ang mga larawan kapag bumalik ang tawag
Ang mga larawan ay nakakabit lang sa mga mensaheng binuo para sa isang partikular na tawag sa model. Hindi sila kailanman sine-save sa naka-save na estado ng usapan. Kaya kapag bumalik na ang tawag, ligtas nang burahin ang image data sa mga mensaheng iyon. Nagtatago ang trace ng text na talaan ng tawag; nawawala ang mga pixel.
Mahalaga ang isang detalye: dapat burahin ang mga larawan mismo sa lugar. Maaabot ng tracer ang parehong image data sa pamamagitan ng higit sa isang reference sa isang mensahe, kaya kung papalitan ng bagong walang lamang listahan, mananatiling maaabot ang orihinal, kasama ang mga pixel. Hindi kailanman binabago ang naka-save na estado ng usapan.
Nagpapatakbo ang isang test ng graph ng agent sa ilalim ng parehong event streaming, na may 4 MB na larawan sa bawat tawag. Kung walang ayos, lumaki ang memory ng 77 MB sa loob ng 16 na tawag. Kapag may ayos, nananatiling pantay ito.
Ang natutunan namin
- Maaaring may patong-patong ang mga problema sa memory. Tatlong magkakahiwalay na sanhi ang bawat isa ay humahawak ng larawan nang masyadong matagal, at kailangang mawala ang tatlo bago manatili sa memory ang turn.
- Maaaring itago ang anumang ibinigay mo sa isang library. Ang signal at ang trace ay nabuhay nang lampas sa mga tawag na pinagbigyan nila. Kapag lumalaki ang memory kada tawag, tingnan kung anong matatagal na object ang hinahawakan ng tawag.
- Huwag ipadala ang ibinabasura ng kabilang panig. Ang mga pixel na itatapon din naman ng model ay nagkakahalaga sa amin ng memory sa bawat tawag.
- Subukan nang direkta ang memory. May kasamang test ang bawat ayos na sumusukat sa paglaki ng heap o bilang ng listener, kaya lumalabas ang regression bilang numero, hindi bilang crash.
Ikalawang kuwento na ito ng memory mula sa agent sa maikling panahon; ang una ay isang progress label na ipinadala muli nang 41,000 beses. Kung gusto mong malaman pa kung ano ang agent at paano ito gumagana, tingnan ang aming guide tungkol sa AI agents at ang chat docs.