Blog

Menținerea turelor lungi ale agentului în fereastra de context

Un model poate citi doar atât deodată — fereastra sa de context. Agentul Mythex face muncă de lungă durată: citește multe fișiere, rulează comenzi, dă sarcini delimitate subagenților. Am găsit trei moduri în care munca lungă se strica: subagenții creșteau până când modelul refuza fiecare cerere, un subagent se oprea devreme pentru că credea că nu mai are loc, iar numărarea tokenilor noastră era grav greșită pentru textele în rusă, chineză și japoneză. Iată ce am schimbat.

Câțiva termeni întâi

  • Tokenii sunt bucățile pe care le citește un model. Limitele și costurile se numără în ele, nu în caractere sau cuvinte.
  • Fereastra de context este cel mai mult pe care îl poate citi un model într-o singură cerere. Noi mai stabilim și un buget propriu, mai mic, pentru fiecare cerere, ca să rămână costurile și viteza rezonabile.
  • Rezultatele instrumentelor sunt ce primește agentul înapoi de la instrumentele sale: conținutul unui fișier citit, rezultatul unei comenzi rulate. În munca lungă, acestea reprezintă cea mai mare parte din ce se trimite.
  • Un subagent este un ajutor pe care agentul principal îl pornește pentru o sarcină independentă, de exemplu „verifică aceste capitole față de notițe”. Primește o singură instrucțiune, apoi lucrează singur prin multe apeluri de instrumente.

Problema 1: subagenții creșteau până când modelul îi refuza

La fiecare pas, agentul trimite modelului conversația de până atunci. Când aceasta devenea prea mare, codul nostru o tăia — dar doar la începutul unui mesaj al utilizatorului, astfel încât un apel de instrument și rezultatul său să nu fie niciodată despărțite. Păstra primul mesaj, adăuga o notă care spunea că din conversația anterioară s-a tăiat și păstra cele mai noi ture complete care încăpeau.

Un subagent are exact un singur mesaj de utilizator: instrucțiunea sa. Nu exista unde să tăiem. Așa că trimitea întregul istoric la fiecare pas, crescând de fiecare dată, până când cererea devenea mai mare decât o acceptă modelul — aproximativ un milion de tokeni. Într-un test cu 8 astfel de subagenți, toți cei 8 au fost refuzați.

Soluția: șterge mai întâi rezultatele vechi ale instrumentelor

Cererile se încadrează acum în buget în trei pași, încercându-l pe fiecare doar dacă pasul anterior nu a fost suficient:

  1. Șterge cele mai vechi rezultate ale instrumentelor. Conținutul lor este înlocuit cu o notă scurtă: rezultatul a fost șters ca să păstreze conversația în limitele contextului modelului, iar agentul poate rula din nou instrumentul dacă are nevoie. Un fișier citit în urmă cu o oră este de obicei cel mai mare și cel mai puțin util lucru din cerere, iar fișierul este în continuare acolo ca să-l citești din nou. Cele mai noi rezultate rămân întregi.
  2. Păstrează ture complete ale utilizatorului. Ca înainte: primul mesaj, o notă și cele mai noi ture complete care încap.
  3. Păstrează runde complete de instrumente. În interiorul unei ture lungi — singurul tip pe care îl are un subagent — păstrează primul mesaj, o notă și cele mai noi runde complete de „apelează un instrument, primește rezultatul”.

Aceasta modelează doar ce se trimite. Istoricul salvat al agentului păstrează totul. În același test, 0 din 8 au fost refuzați și toți cei 8 au terminat.

Ștergere în loturi, ca memoria cache să funcționeze

Furnizorii de modele pot refolosi munca de la începutul unei cereri dacă este identică cu ultima — un cache de prefix. Dacă am fi șters încă un rezultat la fiecare apel, începutul cererii s-ar schimba la fiecare apel, iar cache-ul nu ar mai ajuta niciodată.

Așa că cele mai vechi rezultate sunt șterse câte patru, nu câte unul. Partea ștearsă rămâne astfel aceeași peste mai multe apeluri. Un rezultat care nu este mult mai mare decât nota este lăsat neatins: ștergerea lui ar economisi aproape nimic și totuși ar schimba începutul cererii. Cât rămâne întreg se decide după dimensiune, nu după număr: cele mai noi rezultate care încap într-un sfert din buget rămân, iar cel puțin unul rămâne mereu. O versiune anterioară păstra fix șase întregi, ceea ce era corect pentru ieșirile scurte ale comenzilor, dar, cu citiri lungi de fișiere, lăsa cea mai mare parte a bugetului rezultatelor vechi.

Refuzurile spun acum de ce

O cerere pe care modelul o respinge ca invalidă nu mai este reîncercată; trimiterea aceleiași cereri din nou primește același răspuns. Dacă conversația este prea lungă pentru model, persoana vede: „Conversația a devenit prea lungă pentru ca modelul s-o citească dintr-o dată. Începe un chat nou pentru pasul următor — tot ce s-a construit până acum rămâne.” Aceasta este o decizie a persoanei, nu o defecțiune, deci nu ne trimite alertă.

Problema 2: agentul se oprea ca să „economisească spațiu”

Un subagent rugat să citească 40 de capitole lungi s-a oprit după 2, spunând că vrea să economisească spațiu. Folosise aproximativ 100.000 de tokeni dintr-un buget de 400.000.

Nu avea de unde să știe că rezultatele vechi vor fi acum șterse pentru el. Așa că i-am spus. Instrucțiunile agentului spun acum că, atunci când o conversație depășește ce poate primi modelul, cele mai vechi rezultate ale instrumentelor sunt șterse, iar cele mai noi rămân întregi — deci nu opri o sarcină lungă ca să economisești spațiu; continuă, și citește din nou un fișier dacă ai nevoie de ce a fost șters.

O soluție pe care modelul nu o vede nu este o soluție din punctul lui de vedere. Mecanismul ajută doar dacă agentul are încredere în el.

Problema 3: numărarea tokenilor ca și cum totul ar fi în engleză

Estimam tokenii fără să rulăm un tokenizer, ca numărul de caractere împărțit la patru. Este o regulă empirică rezonabilă pentru engleză. Nu este valabilă pentru alte scripturi: rusa are aproximativ 2,2 caractere pe token, iar chineza sau japoneza aproximativ unul.

Așa că un subagent care citea capitole în rusă a trimis o cerere de aproximativ 640.000 de tokeni, în timp ce estimarea noastră spunea că este sub bugetul de 400.000. Estimarea putea la fel de ușor să împingă o cerere peste limita strictă a modelului.

Estimarea numără acum după script: ASCII simplu la patru caractere pe token, chineza, japoneza și coreeana la unu, iar tot restul — chirilică, greacă, arabă, litere cu diacritice, emoji — la doi. Este gândită să greșească în sus. Pentru un capitol în rusă, estimează acum 43.423 de tokeni, față de aproximativ 44.600 măsurați; înainte spunea 25.023. Deoarece un mesaj nu se mai schimbă odată scris, estimarea lui este calculată o dată și reținută, în loc să fie recalculată la fiecare pas.

Ce am învățat

  • Taie acolo unde se află de fapt dimensiunea. În munca agentului, aceasta sunt rezultatele instrumentelor, nu mesajele utilizatorului.
  • Spune agentului despre plasele sale de siguranță. Altfel planifică în jurul unor limite care nu mai se aplică.
  • „Caractere ÷ 4” este o presupunere pentru engleză. Orice număra tokeni pentru utilizatori multilingvi trebuie să numere după script sau să folosească un tokenizer real.
  • Ai grijă la cache. O cerere care se schimbă la început la fiecare apel costă mai mult și rulează mai lent.

Dacă îți construiești funcții AI în propria aplicație, ghidurile noastre despre ce este un LLM și cum folosești API-urile LLM acoperă de la început ferestrele de context și tokenii. Mai multe despre cum funcționează subagenții în Mythex găsești în documentația subagenților.

Mythex · Pricing · Construiește orice cu AI · Șabloane pentru site-uri și aplicații · Mythex comparat · Glosar pentru crearea de aplicații cu AI · Instrumente gratuite pentru crearea de aplicații cu AI · 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) Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)