Muistin loppumisen virhe edistymisnäytön tekstissä
Eräänä syyskuun iltana agentti käyttäjän työtilassa kaatui muistin loppumiseen kesken vuoron. Ilmeiset epäillyt, eli liian monta aliagenttia yhtä aikaa tai liian suureksi kasvanut konteksti, olivat molemmat vääriä. Todellinen syy oli tilarivi: kun malli suoratoisti suurta shell-komentoa muutaman merkin kerrallaan, lähetimme koko komennon tähän mennessä uudelleen edistymisnimikkeenä jokaisen palan kohdalla. Yksi 124 kt:n komento muuttui noin 41 000 tapahtumaksi ja noin 690 megatavuksi jonotettuja merkkijonoja.
Miten agentti suoratoistaa työnsä
Kun rakennat Mythexissä, agentti toimii projektisi yksityisessä pilvisandboxissa. Kun malli kirjoittaa, sen tuotos virtaa takaisin selaimeesi: teksti ilmestyy sana kerrallaan, ja kun se ajaa työkalun, esimerkiksi shell-komennon, joka kirjoittaa tiedoston, näet nimikkeen, joka päivittyy reaaliaikaisesti, jotta tiedät, mitä se tekee.
Malli suoratoistaa pieninä paloina. Käyttämällämme mallilla palat olivat usein vain kolmen merkin pituisia.
Ensimmäiset oletukset olivat vääriä
Kaatuminen näytti skaalautumisongelmalta, joten aloitimme sieltä.
- Rinnakkaiset aliagentit? Vuorossa oli käytetty vain kahta, joista kummallakin oli noin 1,5 MB tilaa. Se ei riitä.
- Säilytetyt jäljet? Jäljityksemme piti puun ajoista muistissa, mutta se ei ollut lähelläkään kaatumishetken keon kokoa.
Molemmat tarinat olivat uskottavia, ja molempia oli helppo uskoa. Kumpikaan ei toistanut kaatumista. Opimme uudelleen ja uudelleen saman asian: oletus ei ole syy, ennen kuin se toistaa vian.
Toistaminen oikeasti
Rakensimme väliaikaisen sandboxin, jolla oli samat muistirajat kuin tuotannossa, ja väärennetyn mallin, joka suoratoisti suuren tiedoston realistisina kolmen merkin paloina. Teimme myös vastapuolen lukijasta hitaan, kuten oikea verkko.
Se toimi. Keko kasvoi, ja prosessi kuoli samalla virheellä.
Mekanismi oli yksinkertainen, kun näimme sen. Kun malli kirjoitti suurta komentoa, tässä tapauksessa heredoc, joka kirjoitti 124 kt:n tiedoston, suoratoistokoodimme päivitti työkalun nimikkeen jokaisen palan kohdalla. Nimike ei ollut uusi kolme merkkiä, vaan koko komento tähän mennessä. Tapahtumat kasvoivat: 3 merkkiä, sitten 6, sitten 9 … aina 124 kt:hen asti, noin 41 000 kertaa. Socket ei pystynyt lähettämään niitä yhtä nopeasti kuin niitä tuotettiin, joten ne kasautuivat sen kirjoituspuskuriin merkkijonoina, noin 690 megatavua.
Korjaus
- Rajoita nimike. Tilanimikkeen tehtävä on kertoa, mitä tapahtuu. Se on nyt rajattu 200 merkkiin, ja osittaisen komennon uudelleenskannausta rajoitetaan.
- Lopeta neliöllinen ketjutus. Suoratoistettujen palojen liittäminen toistuvalla merkkijonoyhdistämisellä on O(n²) suurille tuotoksille. Siirryimme palapohjaiseen tapaan, joka lisää lineaarisessa ajassa.
Sitten etsimme kaikkea muuta, mikä voisi kasvaa rajatta tulvivan tuotoksen seurauksena, ja rajasimme sen:
- Chatissa näkyvä suora komennon tuloste kerätään erissä ja pidetään viimeisissä 8 000 merkissä.
- Yksittäiset tapahtumarivit on rajattu 4 megatavuun.
- Toistopuskuri, jota selain käyttää kuromaan kiinni yhteyden katkeamisen jälkeen, on rajattu 8 megatavuun projektia kohden.
- Vanhat tarkistuspisteet karsitaan vuoron edetessä, säilyttäen uusimman tilan ja aiempien vuorojen tarvitsemat ankkurit.
Tulvien testaaminen rehellisesti
Kaksi asiaa teki tästä vaikeampaa testata kuin piti:
- Oikeat mallit eivät yhteistyöhaluisia. Pyydä mallia tulostamaan valtava tiedosto, ja se yleensä kieltäytyy, tiivistää sen tai kirjoittaa sen järkevämmin. Tulvien testaamiseen tarvitaan skriptattu malli, joka tekee täsmälleen sen, mitä sille kerrotaan, ja ajaa oikean agenttikoodin läpi.
- Skriptien täytyy käyttäytyä kuten malleilla. Ensimmäinen skriptattu mallimme käytti jokaisessa vastauksessa samaa vastaus-ID:tä, joten agenttikehys käsitteli jokaisen vastauksen edellisen korvaajana ja lopetti vuorot ennenaikaisesti. Se näytti käyttöliittymän virkistysvirheeltä. Se ei ollut sitä. Testiympäristö valehteli meille. Meidän piti myös pakottaa mallin todellinen kontekstiraja skriptiin, muuten muistiluvut olivat epärealistisia.
Mitä tästä opimme
- Suoratoistavat käyttöliittymät moninkertaistavat pienet virheet. Kaikki, mikä lähetetään "palaa kohden", lähetetään kymmeniä tuhansia kertoja. Lähetä deltoja tai rajoita hyötykuorma.
- Rajaa jokainen puskuri, joka ylittää hitaan rajan. Socketit, toistolokit ja tarkistuspisteet tarvitsevat katon.
- Toista ennen korjaamista. Kaksi ensimmäistä selitystämme kuulostivat oikeilta ja olivat vääriä.
Jos olet viime aikoina nähnyt Mythexin chatissa hyvin pitkän tiedoston ilmestyvän pysähtymättä, tämä on osa syytä.