Blog

Tenere i turni lunghi dell'agente dentro la finestra di contesto

Un modello può leggere solo una certa quantità alla volta — la sua finestra di contesto. Il tuo agente di Mythex svolge lavori lunghi: legge molti file, esegue comandi, affida compiti circoscritti a sotto-agenti. Abbiamo trovato tre modi in cui il lavoro lungo si rompeva: i sotto-agenti crescevano fino a far rifiutare ogni richiesta dal modello, un sotto-agente si fermava presto perché credeva di essere a corto di spazio, e il nostro conteggio dei token era molto sbagliato per il testo in russo, cinese e giapponese. Ecco cosa abbiamo cambiato.

Alcuni termini prima di tutto

  • I token sono i pezzi che un modello legge. Limiti e costi si contano in token, non in caratteri o parole.
  • La finestra di contesto è la quantità massima che un modello può leggere in una singola richiesta. Impostiamo anche un nostro budget più basso per ogni richiesta, così costi e velocità restano ragionevoli.
  • I risultati degli strumenti sono ciò che l'agente riceve dai propri strumenti: il contenuto di un file letto, l'output di un comando eseguito. Nei lavori lunghi sono la maggior parte di ciò che viene inviato.
  • Un sotto-agente è un aiutante che l'agente principale avvia per un compito autonomo, per esempio "controlla questi capitoli rispetto alle note". Riceve una sola istruzione, poi lavora da solo attraverso molte chiamate di strumenti.

Problema 1: i sotto-agenti crescevano fino a essere rifiutati dal modello

A ogni passo, l'agente invia al modello la conversazione finora. Quando diventava troppo grande, il nostro codice la tagliava — ma solo all'inizio di un messaggio utente, così una chiamata di strumento e il suo risultato non venivano mai separati. Teneva il primo messaggio, aggiungeva una nota che diceva che la conversazione precedente era stata tagliata, e conservava i turni più recenti interi che ci stavano.

Un sotto-agente ha esattamente un messaggio utente: la sua istruzione. Non c'era un punto dove tagliare. Quindi inviava l'intera cronologia a ogni passo, crescendo ogni volta, finché la richiesta non superava ciò che il modello accetta — circa un milione di token. In un test con 8 di questi sotto-agenti, tutti e 8 sono stati rifiutati.

La soluzione: cancellare prima i vecchi risultati degli strumenti

Le richieste ora rientrano nel budget in tre passaggi, provando ciascuno solo se il precedente non è bastato:

  1. Cancellare i risultati di strumenti più vecchi. Il loro contenuto viene sostituito con una breve nota: il risultato è stato cancellato per tenere la conversazione entro il contesto del modello, e l'agente può rieseguire lo strumento se ne ha bisogno. Un file letto un'ora fa è di solito la cosa più grande e meno utile nella richiesta, e il file è ancora lì da rileggere. I risultati più recenti restano interi.
  2. Mantenere interi i turni utente. Come prima: il primo messaggio, una nota e i turni completi più recenti che ci stanno.
  3. Mantenere interi i round di strumenti. All'interno di un lungo turno — l'unico tipo che un sotto-agente ha — mantieni il primo messaggio, una nota e i round più recenti completi di "chiama uno strumento, ricevi il suo risultato".

Questo modifica solo ciò che viene inviato. La cronologia salvata dell'agente conserva tutto. Nello stesso test, 0 su 8 sono stati rifiutati e tutti e 8 hanno completato.

Cancellare a lotti, così la cache continua a funzionare

I fornitori di modelli possono riutilizzare il lavoro sull'inizio di una richiesta se è identico all'ultima — una cache di prefisso. Se cancellassimo un risultato in più a ogni chiamata, l'inizio della richiesta cambierebbe a ogni chiamata e la cache non servirebbe mai.

Quindi i risultati più vecchi vengono cancellati quattro alla volta, non uno. La parte cancellata resta uguale per diverse chiamate. Un risultato non molto più grande della nota viene lasciato stare: cancellarlo risparmierebbe quasi nulla e cambierebbe comunque l'inizio della richiesta. Quanti restano interi viene deciso dalla dimensione, non dal numero: restano i risultati più recenti che entrano in un quarto del budget, e ne resta sempre almeno uno. Una versione precedente ne teneva fissi sei interi, il che andava bene per output di comandi brevi, ma con letture di file lunghe lasciava la maggior parte del budget ai vecchi risultati.

Ora i rifiuti vengono detti chiaramente

Una richiesta che il modello respinge come non valida non viene più ritentata; inviare di nuovo la stessa richiesta darebbe la stessa risposta. Se la conversazione è troppo lunga per il modello, la persona vede: "Questa conversazione è diventata troppo lunga perché il modello possa leggerla in una volta sola. Inizia una nuova chat per il passo successivo — tutto ciò che è stato costruito finora resta." È qualcosa che spetta alla persona gestire, non un'interruzione, quindi non avvisa il nostro team.

Problema 2: l'agente si fermava per "risparmiare spazio"

Un sotto-agente a cui era stato chiesto di leggere 40 capitoli lunghi si è fermato dopo 2, dicendo che voleva risparmiare spazio. Aveva usato circa 100.000 token di un budget di 400.000.

Non poteva sapere che i vecchi risultati ora sarebbero stati cancellati per lui. Quindi glielo abbiamo detto. Le istruzioni dell'agente ora dicono che quando una conversazione cresce oltre ciò che il modello può accogliere, i risultati più vecchi degli strumenti vengono cancellati e quelli più recenti restano interi — quindi non interrompere un compito lungo per risparmiare spazio; continua, e rileggi un file se ti serve ciò che è stato cancellato.

Una correzione che il modello non vede non è una correzione dal punto di vista del modello. Il meccanismo aiuta solo se l'agente ci si fida.

Problema 3: contare i token come se tutto fosse inglese

Stimavamo i token senza eseguire un tokenizer, come caratteri divisi per quattro. È una regola empirica ragionevole per l'inglese. Non lo è per altri sistemi di scrittura: il russo è circa 2,2 caratteri per token, e il cinese o il giapponese circa uno.

Quindi un sotto-agente che leggeva capitoli in russo inviava una richiesta di circa 640.000 token, mentre la nostra stima diceva che era sotto il budget di 400.000. La stima avrebbe potuto far superare con la stessa facilità il limite fisso del modello.

La stima ora conta per sistema di scrittura: l'ASCII semplice a quattro caratteri per token, il cinese, il giapponese e il coreano a uno, e tutto il resto — cirillico, greco, arabo, lettere accentate, emoji — a due. Tende a sovrastimare di proposito. Su un capitolo in russo ora stima 43.423 token contro circa 44.600 misurati; prima diceva 25.023. Poiché un messaggio non cambia mai una volta scritto, la sua stima viene calcolata una sola volta e ricordata, invece di essere ricalcolata a ogni passo.

Cosa ne abbiamo ricavato

  • Taglia dove si trova davvero la dimensione. Nel lavoro degli agenti, sono i risultati degli strumenti, non i messaggi utente.
  • Dì all'agente quali sono le sue reti di sicurezza. Altrimenti pianifica attorno a limiti che non si applicano più.
  • "Caratteri ÷ 4" è un presupposto valido solo per l'inglese. Tutto ciò che conta i token per utenti multilingue deve contare per sistema di scrittura, oppure usare un vero tokenizer.
  • Attenzione alla cache. Una richiesta che cambia all'inizio a ogni chiamata costa di più e va più lenta.

Se stai integrando funzionalità di IA nella tua app, le nostre guide su cos'è un LLM e come usare le API degli LLM spiegano fin dall'inizio le finestre di contesto e i token. Maggiori dettagli su come funzionano i sotto-agenti in Mythex sono nella documentazione sui sotto-agenti.

Mythex · Pricing · Crea qualsiasi cosa con l'AI · Template per siti web e app · Mythex a confronto · Glossario per creare app con l'AI · Strumenti gratuiti per creare app con l'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 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 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 简体中文 繁體中文(香港) 繁體中文(台灣)