Blog

Jak utrzymać długie tury agenta w oknie kontekstu

Model może przeczytać naraz tylko określoną ilość — swoje okno kontekstu. Agent Mythex wykonuje długą pracę: czyta wiele plików, uruchamia polecenia, przekazuje ograniczone zadania podagentom. Znaleźliśmy trzy sposoby, w jakie długa praca się psuła: podagenci rośli, aż model odrzucał każde żądanie, podagent zatrzymywał się wcześnie, bo uważał, że nie ma już miejsca, a nasz licznik tokenów był znacznie błędny dla tekstu po rosyjsku, chińsku i japońsku. Oto, co zmieniliśmy.

Najpierw kilka pojęć

  • Tokeny to porcje, które czyta model. Limity i koszty liczy się w nich, a nie w znakach ani słowach.
  • Okno kontekstu to maksimum, które model może przeczytać w jednym żądaniu. Ustawiamy też własny, niższy budżet na każde żądanie, żeby koszty i szybkość pozostały rozsądne.
  • Wyniki narzędzi to to, co agent dostaje z powrotem od swoich narzędzi: zawartość pliku, który przeczytał, wynik polecenia, które uruchomił. W długiej pracy to one stanowią większość wysyłanych danych.
  • Podagent to pomocnik, którego główny agent uruchamia do samodzielnego zadania, na przykład „sprawdź te rozdziały względem notatek”. Dostaje jedną instrukcję, a potem sam przechodzi przez wiele wywołań narzędzi.

Problem 1: podagenci rośli, aż model ich odrzucił

Przy każdym kroku agent wysyła modelowi rozmowę do tej pory. Gdy stawała się za duża, nasz kod ją przycinał — ale tylko na początku wiadomości użytkownika, tak żeby wywołanie narzędzia i jego wynik nigdy nie zostały rozdzielone. Zachowywał pierwszą wiadomość, dodawał notatkę, że wcześniejsza rozmowa została przycięta, i trzymał najnowsze całe tury, które się mieściły.

Podagent ma dokładnie jedną wiadomość użytkownika: swoją instrukcję. Nie było gdzie ciąć. Więc wysyłał całą swoją historię w każdym kroku, rosnąc za każdym razem, aż żądanie przekraczało to, co model w ogóle przyjmuje — ok. miliona tokenów. W teście z 8 takimi podagentami wszystkie 8 zostało odrzuconych.

Naprawa: najpierw wyczyść stare wyniki narzędzi

Żądania teraz mieszczą się w budżecie w trzech krokach, a każdy próbowany jest tylko wtedy, gdy poprzedni nie wystarczył:

  1. Wyczyść najstarsze wyniki narzędzi. Ich treść zastępuje się krótką notatką: wynik został usunięty, aby utrzymać rozmowę w kontekście modelu, a agent może ponownie uruchomić narzędzie, jeśli go potrzebuje. Plik przeczytany godzinę temu jest zwykle największą i najmniej przydatną rzeczą w żądaniu, a sam plik nadal tam jest, do ponownego odczytania. Najnowsze wyniki zostają całe.
  2. Zachowaj całe tury użytkownika. Jak wcześniej: pierwsza wiadomość, notatka i najnowsze kompletne tury, które się mieszczą.
  3. Zachowaj całe rundy narzędzi. Wewnątrz jednej długiej tury — jedynego rodzaju, jaki ma podagent — zachowaj pierwszą wiadomość, notatkę i najnowsze kompletne rundy „wywołaj narzędzie, dostań wynik”.

To zmienia tylko kształt wysyłanych danych. Zapisana historia agenta zachowuje wszystko. W tym samym teście odrzucono 0 z 8, a wszystkie 8 się zakończyło.

Czyszczenie partiami, żeby cache działał

Dostawcy modeli mogą ponownie użyć pracy nad początkiem żądania, jeśli jest ono identyczne z poprzednim — to tak zwany prefix cache. Gdybyśmy czyścili jeden wynik więcej przy każdym wywołaniu, początek żądania zmieniałby się za każdym razem i cache nigdy by nie pomagał.

Dlatego najstarsze wyniki czyścimy po cztery naraz, a nie po jednym. Wyczyszczona część pozostaje wtedy taka sama przez kilka wywołań. Wynik niewiele większy od notatki zostaje nietknięty: jego wyczyszczenie zaoszczędziłoby prawie nic, a i tak zmieniłoby początek żądania. To, ile pozostaje w całości, decyduje rozmiar, a nie liczba: najnowsze wyniki, które mieszczą się w jednej czwartej budżetu, zostają, zawsze przynajmniej jeden. Wcześniejsza wersja zachowywała stałe sześć w całości, co było dobre dla krótkiego wyjścia poleceń, ale przy długich odczytach plików zostawiało większość budżetu starym wynikom.

Odrzucenia teraz to mówią

Żądania, które model odrzuca jako nieprawidłowe, nie są już ponawiane; wysłanie tego samego żądania ponownie daje tę samą odpowiedź. Jeśli rozmowa jest za długa dla modelu, osoba widzi: „Ta rozmowa jest za długa, by model przeczytał ją za jednym razem. Rozpocznij nowy czat na następny krok — wszystko zbudowane do tej pory zostaje.” To decyzja osoby, a nie awaria, więc nie wywołuje alarmu u nas.

Problem 2: agent zatrzymywał się, żeby „oszczędzić miejsce”

Podagent, którego poproszono o przeczytanie 40 długich rozdziałów, zatrzymał się po 2, mówiąc, że chce oszczędzić miejsce. Zużył ok. 100 000 tokenów z budżetu 400 000.

Nie mógł wiedzieć, że stare wyniki zostaną dla niego wyczyszczone. Więc mu powiedzieliśmy. Instrukcje agenta mówią teraz, że gdy rozmowa rośnie ponad to, co model może przyjąć, najstarsze wyniki narzędzi są czyszczone, a najnowsze zostają całe — więc nie przerywaj długiego zadania, żeby oszczędzać miejsce; idź dalej, a jeśli potrzebujesz tego, co zostało wyczyszczone, przeczytaj plik ponownie.

Poprawka, której model nie widzi, nie jest poprawką z jego punktu widzenia. Mechanizm pomoże tylko wtedy, gdy agent mu ufa.

Problem 3: liczenie tokenów tak, jakby wszystko było po angielsku

Szacowaliśmy tokeny bez uruchamiania tokenizera, jako liczbę znaków podzieloną przez cztery. To rozsądna zasada kciuka dla angielskiego. Dla innych pism już nie: rosyjski ma ok. 2,2 znaku na token, a chiński czy japoński ok. jeden.

Więc podagent czytający rosyjskie rozdziały wysłał żądanie na ok. 640 000 tokenów, podczas gdy nasz szacunek mówił, że mieści się w budżecie 400 000. Ten szacunek równie dobrze mógł wepchnąć żądanie ponad twardy limit modelu.

Szacunek liczy teraz według pisma: zwykły ASCII po cztery znaki na token, chiński, japoński i koreański po jednym, a wszystko inne — cyrylica, greka, arabski, litery z akcentami, emoji — po dwa. Ma być celowo zawyżony. Dla jednego rosyjskiego rozdziału szacuje teraz 43 423 tokeny wobec ok. 44 600 zmierzonych; wcześniej mówił 25 023. Ponieważ wiadomość nigdy nie zmienia się po zapisaniu, jej szacunek jest liczony raz i zapamiętywany, zamiast przy każdym kroku.

Co z tego wynieśliśmy

  • Przycinaj tam, gdzie naprawdę jest rozmiar. W pracy agenta to wyniki narzędzi, a nie wiadomości użytkownika.
  • Powiedz agentowi o jego własnych siatkach bezpieczeństwa. Inaczej planuje wokół limitów, które już nie obowiązują.
  • „Znaki ÷ 4” to założenie dla angielskiego. Wszystko, co liczy tokeny dla wielojęzycznych użytkowników, musi liczyć według pisma albo użyć prawdziwego tokenizera.
  • Uważaj na cache. Żądanie, które zmienia się na początku przy każdym wywołaniu, kosztuje więcej i działa wolniej.

Jeśli budujesz funkcje AI w swojej aplikacji, nasze poradniki o czym jest LLM i jak używać API LLM od początku omawiają okna kontekstu i tokeny. Więcej o tym, jak działają podagenci w Mythex, znajdziesz w dokumentacji podagentów.

Mythex · Pricing · Zbuduj wszystko z AI · Szablony stron i aplikacji · Mythex w porównaniu · Słownik budowania aplikacji z AI · Darmowe narzędzia do budowania aplikacji z 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 ਪੰਜਾਬੀ 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 简体中文 繁體中文(香港) 繁體中文(台灣)