Blog

Lange agentbeurten binnen het contextvenster houden

Een model kan maar zoveel tegelijk lezen: het contextvenster. Het werk van de agent van Mythex is soms lang: veel bestanden lezen, commando's draaien, afgebakende taken aan subagents geven. We vonden drie manieren waarop lang werk brak: subagents groeiden tot het model elk verzoek weigerde, een subagent stopte vroeg omdat hij dacht dat hij geen ruimte meer had, en onze tokentelling klopte slecht voor Russische, Chinese en Japanse tekst. Dit hebben we veranderd.

Eerst enkele termen

  • Tokens zijn de brokken die een model leest. Limieten en kosten worden in tokens geteld, niet in tekens of woorden.
  • Het contextvenster is het meeste wat een model in één verzoek kan lezen. Wij stellen daarnaast een eigen lager budget per verzoek in, zodat kosten en snelheid redelijk blijven.
  • Toolresultaten zijn wat de agent van zijn tools terugkrijgt: de inhoud van een bestand dat hij las, de uitvoer van een commando dat hij draaide. Bij lang werk vormen ze het grootste deel van wat wordt verstuurd.
  • Een subagent is een helper die de hoofdagent start voor een op zichzelf staande taak, zoals “controleer deze hoofdstukken tegen de notities”. Hij krijgt één instructie en werkt dan zelfstandig door vele toolaanroepen heen.

Probleem 1: subagents groeiden tot het model ze weigerde

Bij elke stap stuurt de agent het gesprek tot dan toe naar het model. Toen dat te groot werd, kapte onze code het in, maar alleen aan het begin van een gebruikersbericht, zodat een toolaanroep en zijn resultaat nooit uit elkaar werden gehaald. Het hield het eerste bericht, voegde een notitie toe dat eerder gesprek was ingekort, en hield de nieuwste volledige beurten die pasten.

Een subagent heeft precies één gebruikersbericht: zijn instructie. Er was dus geen plek om te knippen. Hij stuurde zijn volledige geschiedenis bij elke stap, en die groeide elke keer, tot het verzoek groter was dan het model überhaupt accepteert: ongeveer een miljoen tokens. In een test met 8 van zulke subagents werden alle 8 geweigerd.

De oplossing: eerst oude toolresultaten wissen

Verzoeken passen nu in drie stappen in het budget, waarbij elke stap alleen wordt geprobeerd als de vorige niet genoeg was:

  1. Wis de oudste toolresultaten. Hun inhoud wordt vervangen door een korte notitie: het resultaat is gewist om het gesprek binnen het contextvenster van het model te houden, en de agent kan de tool opnieuw draaien als hij het nodig heeft. Een bestand dat een uur geleden is gelezen is meestal het grootste en minst nuttige deel van het verzoek, en het bestand is nog steeds beschikbaar om opnieuw te lezen. De nieuwste resultaten blijven volledig staan.
  2. Houd volledige gebruikersbeurten. Zoals voorheen: het eerste bericht, een notitie, en de nieuwste volledige beurten die passen.
  3. Houd volledige toolrondes. Binnen één lange beurt, het enige soort dat een subagent heeft, houd je het eerste bericht, een notitie, en de nieuwste volledige rondes van “roep een tool aan, krijg het resultaat”.

Dit bepaalt alleen wat er wordt verstuurd. De opgeslagen geschiedenis van de agent bewaart alles. In dezelfde test werden er 0 van de 8 geweigerd en rondden ze alle 8 af.

Wissen in batches, zodat caching blijft werken

Modelproviders kunnen werk hergebruiken aan het begin van een verzoek als dat identiek is aan het vorige: een prefix-cache. Als we bij elke aanroep één resultaat extra wisten, zou het begin van het verzoek elke aanroep veranderen en zou de cache nooit helpen.

Daarom worden de oudste resultaten vier tegelijk gewist, niet één. Het gewiste deel blijft dan over meerdere aanroepen gelijk. Een resultaat dat niet veel groter is dan de notitie blijft staan: wissen zou bijna niets besparen en toch het begin van het verzoek veranderen. Hoeveel volledig blijft, wordt bepaald door grootte, niet door aantal: de nieuwste resultaten die samen in een kwart van het budget passen, blijven, en er blijft altijd minstens één staan. Een eerdere versie hield vaste zes volledige resultaten, wat goed was voor korte commando-uitvoer maar bij lange bestandslezingen het grootste deel van het budget aan oude resultaten liet.

Weigeringen zeggen nu wat er aan de hand is

Een verzoek dat het model als ongeldig weigert, wordt niet langer opnieuw geprobeerd; hetzelfde verzoek opnieuw sturen krijgt hetzelfde antwoord. Als het gesprek te lang is voor het model, ziet de persoon: “Dit gesprek is te lang geworden om het model in één keer te laten lezen. Start een nieuwe chat voor de volgende stap; alles wat tot nu toe is gebouwd blijft bestaan.” Dat is iets wat de persoon zelf kan doen, geen storing, dus het zet ons niet op scherp.

Probleem 2: de agent stopte om “ruimte te sparen”

Een subagent die 40 lange hoofdstukken moest lezen, stopte na 2, omdat hij ruimte wilde sparen. Hij had ongeveer 100.000 tokens van een budget van 400.000 gebruikt.

Hij kon niet weten dat oude resultaten nu voor hem zouden worden gewist. Dus hebben we het hem verteld. De instructies van de agent zeggen nu dat wanneer een gesprek groter wordt dan het model aankan, de oudste toolresultaten worden gewist en de nieuwste volledig blijven: stop een lange taak dus niet om ruimte te sparen; ga door, en lees een bestand opnieuw als je iets nodig hebt dat gewist is.

Een fix die het model niet kan zien, is vanuit het standpunt van het model geen fix. Het mechanisme helpt alleen als de agent erop vertrouwt.

Probleem 3: tokens tellen alsof alles Engels is

We schatten tokens zonder een tokenizer te draaien, als tekens gedeeld door vier. Dat is een redelijke vuistregel voor Engels. Voor andere schriftsystemen klopt het niet: Russisch zit op ongeveer 2,2 tekens per token, Chinees of Japans op ongeveer één.

Een subagent die Russische hoofdstukken las, stuurde dus een verzoek van ongeveer 640.000 tokens, terwijl onze schatting zei dat het onder het budget van 400.000 zat. De schatting had net zo goed een verzoek over de harde limiet van het model kunnen duwen.

De schatting telt nu per schriftsysteem: gewoon ASCII op vier tekens per token, Chinees, Japans en Koreaans op één, en al het andere (Cyrillisch, Grieks, Arabisch, letters met accenten, emoji) op twee. Hij is bedoeld om naar boven af te ronden. Bij één Russisch hoofdstuk schat hij nu 43.423 tokens tegen ongeveer 44.600 gemeten; voorheen zei hij 25.023. Omdat een bericht nooit verandert zodra het is geschreven, wordt de schatting één keer berekend en onthouden, in plaats van bij elke stap.

Wat we hieruit hebben geleerd

  • Snoei waar de omvang echt zit. Bij agentwerk is dat in toolresultaten, niet in gebruikersberichten.
  • Vertel de agent over zijn eigen vangnetten. Anders plant hij rond limieten die niet meer gelden.
  • “Tekens gedeeld door 4” is een Engelse aanname. Alles wat tokens telt voor meertalige gebruikers moet per schriftsysteem tellen, of een echte tokenizer gebruiken.
  • Let op de cache. Een verzoek dat aan het begin bij elke aanroep verandert, kost meer en loopt trager.

Als je AI-functies in je eigen app bouwt, behandelen onze gidsen over wat een LLM is en hoe je LLM-API's gebruikt contextvensters en tokens vanaf het begin. Meer over hoe subagents werken in Mythex staat in de subagent-documentatie.

Mythex · Pricing · Bouw alles met AI · Website- en app-templates · Mythex vergeleken · Woordenlijst voor apps bouwen met AI · Gratis tools voor apps bouwen met 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 ਪੰਜਾਬੀ 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 简体中文 繁體中文(香港) 繁體中文(台灣)