Większe okno kontekstowe nie naprawi twojego agenta: budżet uwagi i buforowanie
Okna kontekstowe funkcjonują jak budżet uwagi. Dowiedz się, jak działa mechanizm Lost in the Middle oraz kiedy stosować kompresję, przesuwane okna, spakowanie danych lub buforowanie promptów.
Dostawca może reklamować okno kontekstowe o pojemności miliona tokenów, a model i tak będzie je w rzeczywistości używał znacznie mniej. Testy RULER firmy NVIDIA sprawdzają długość, przy której model nadal wykazuje dobrą wydajność. W przypadku dwóch z siedemnastu przetestowanych modeli – Yi-34B i GPT-4 (1106 preview) – rzeczywista długość wyniosła około 32K przy deklarowanych 200K tokenów oraz 64K przy deklarowanych 128K tokenów. Najslabsze modele traciły wydajność już przy znikomo mniejszej długości, niż obiecywały ich specyfikacje. Po tym punkcie deklarowana pojemność jest jedynie informacją na liście cen, a nie rzeczywistą możliwością modelu.
W kilku miejscach widzimy ten sam podstawowy błąd. Agent zapomina o decyzji architektonicznej podjętej już w pierwszym kroku. System RAG znajduje właściwy dokument, a mimo to udziela błędnej odpowiedzi. Automatyczny podsumowanie sesji pomija dokładnie tę linię konfiguracji, której potrzebowałeś. Zwykłym odruchem jest zwiększenie rozmiaru okna, ale to nie pomaga w przypadku agentów, ponieważ przepustowość nigdy nie była problemem. Problemem jest to, jak model rozkłada swoją uwagę na wszystko, co już mieści się w tej przepustowości.
Wersja skrócona
Okno kontekstowe to nie jednolita pamięć. Jest to zasób z budżetem uwagi, który wyczerpuje się znacznie przed osiągnięciem limitu tokenów. Materiał znajdujący się na początku lub na końcu kontekstu jest wykorzystywany lepiej niż ten pośrodku, do tego stopnia, że model otrzymujący dokument ukryty w środku zapytania może odpowiadać gorzej niż ten, który nie otrzymał żadnych danych. Konkretny przykład: agent, który otrzymuje długi zapis działań narzędzi, zbiór pobranych fragmentów oraz instrukcje wszystko w jednym zapytaniu, będzie miał tendencję do uwzględniania elementów znajdujących się na brzegach i cicho zatracania reszty.
Trzy narzędzia zarządzają tym budżetem, a każde z nich traci coś innego:
- Kompresja zapytania usuwa tokeny o niskiej wartości informacyjnej. Daje dobre wyniki na standardowych testach, ale niezależne próby pokazują problemy z treściami strukturyzowanymi, takimi jak numeracja, dokładne ciągi znaków i fragmenty kodu.
Oto pułapka: zarówno kompresja, jak i kompakcja niszczą cache, a oszczędności uzyskane dzięki cache często przewyższają oszczędności z kompresji. Używanie niewłaściwego narzędzia do rozwiązania niewłaściwego problemu powoduje ukryte awarie w produkcji, których diagnoza jest trudna później.
Kontekst to budżet, a nie przestrzeń przechowywania
Najpierw dwie definicje. Token to jednostka tekstu, nad którą pracuje model – odpowiada mniej więcej czterem znakom lub trzem czwartym słowa w języku angielskim. Okno kontekstowe to maksymalna liczba tokenów przetwarzanych w jednej próbie, co jest bardziej związane z maksymalnym rozmiarem macierzy uwagi przy jednej iteracji niż z ilością pamięci dostępnej na co dzień.
Andrej Karpathy opisał inżynierię kontekstu jako sztukę wypełniania okna dokładnie tym, czego potrzebuje następny krok, przy czym model pełni rolę procesora, a okno jego pamięci roboczej. Ta analogia jest przydatna, ale obejmuje tylko połowę problemu. Drugą połową jest budżet uwagi. Wytyczne Anthropic dotyczące inżynierii kontekstu dla agentów traktują kontekst jako zasób skończony o malejących korzyściach, przy którym każdy dodany token wykorzystuje ograniczony zasób uwagi. To arytmetyka, a nie poezja: liczba par uwagi rośnie kwadratowo, więc tysiąc tokenów oznacza około miliona relacji, a sto tysięcy – dziesięć miliardów.
Dodawanie kontekstu na wszelki wypadek nigdy nie jest bezkosztowe. Trzy dodatkowe przykłady typu few-shot, pełna historia rozmów lub dwadzieścia definicji narzędzi zamiast pięciu – wszystko to pochodzi z tego samego źródła co fakty istotne. Pierwszym pytaniem w przeglądzie architektury nie powinno być, ile tokenów jest dostępnych, lecz które elementy budżetu faktycznie przyczyniają się do osiągnięcia celu.
Krzywa w kształcie litery U
Liu i jego współpracownicy (Stanford i Berkeley, 2023) zmierzyli dokładność w zadaniach odpowiadania na pytania w wielu dokumentach i stwierdzili kształt litery U. Odpowiedzi były najbardziej wiarygodne, gdy odpowiedni fragment znajdował się na początku lub na końcu, a najmniej wiarygodne, gdy znajdował się pośrodku. Określenie „Zagubione pośrodku” szybko się przyjęło, daleko przed jakimkolwiek uzgodnionym wyjaśnieniem.
To, co naprawdę budzi niepokój, to efekt uboczny. Gdy prompt zawierał dwadzieścia lub trzydzieści dokumentów, poprawna odpowiedź umieszczona w środku tekstu uzyskiwała gorsze wyniki niż bazowy scenariusz bez dostępu do dokumentów, w którym model w ogóle nie widział żadnych dokumentów. Przekazanie właściwych dowodów w niewłaściwym miejscu może pogorszyć sytuację systemu bardziej niż brak jakichkolwiek informacji.
Dlaczego to się dzieje: nadal nie jest jasne
Lata później nie ma konsensusu co do przyczyny. Istnieje kilka konkurencyjnych wyjaśnień:
- efekt artefaktu danych treningowych, ponieważ autorzy mają tendencję do umieszczania kluczowych punktów na początku i końcu tekstu,
- sposób działania kodowania pozycyjnego i maskowania przyczynowego,
- prosta geometria dekodera, która istnieje od samego początku inicjalizacji, jeszcze przed rozpoczęciem treningu,
- adaptacja, która pojawia się podczas wstępnego treningu, gdy model balansuje między sprzecznymi wymaganiami pamięciowymi.
Każda przyczyna wymaga innego rozwiązania: innych danych treningowych, innej maski uwagi, kalibracji mechanizmu uwagi lub po prostu przestawienia sekwencji poleceń. Połączenie ich w jedno, uporządkowane wyjaśnienie mogłoby wprowadzić w błąd.
Co zostało rozwiązane, a co nie
Zadawanie pytania, czy problem został już rozwiązany, przedstawia go w złym świetle. Proste wydobywanie faktów jest w dużej mierze rozwiązane: obecne modele na najwyższym poziomie potrafią znaleźć dosłownie określony element w bardzo długiej liczbie danych, niezależnie od jego lokalizacji. Rozumowanie wieloetapowe nie jest jeszcze rozwiązane. Syntetyzacja kilku dokumentów lub edycja kodu w dużym repozytorium to zupełnie inna zadanie niż lokalizacja pojedynczego faktu, a opublikowane oceny kodowania w długim kontekście pokazują gwałtowny spadek wskaźników skuteczności wraz ze wzrostem długości danych wejściowych dla tego samego modelu i typu zadania.
Istnieją również dowody przeciwko temu, by ta krzywa była uniwersalna. Badanie Chromy „Context Rot” przetestowało osiemnaście modeli typu frontier i stwierdziło, że losowo uporządkowana, logicznie niespójna masa danych przewyższała spójną w wszystkich przypadkach, a eksperymenty te nie wykazały również stałej przewagi pozycyjnej. Rozsądnym wnioskiem jest to, że istnieje więcej niż jeden mechanizm degradacji, a „Lost in the Middle” to zaledwie jeden z nich.
Jedno zdanie, które podniosło wynik z 27% na 98%
Anthropic przedstawił charakterystyczny przypadek z użyciem Claude 2.1 w teście typu „igła w stogu siana”. Dokładność wynosiła 27 procent, dopóki na początku odpowiedzi modela nie dodano jednej linijki z instrukcją wybrania najbardziej istotnego zdania z kontekstu. Po tym zmianie wynik osiągnął 98 procent. Nie dodano żadnych nowych funkcji – jedynie instrukcja zmieniła swoje położenie. Była to jedna ocena, jeden wersja modelu i jeden rodzaj zadania, więc należy to traktować jako ilustrację, a nie regułę obowiązującą we wszystkich przypadkach.
Mechanizm: „dół uwagi”
Pierwsze tokeny w sekwencji pochłaniają nadmierną ilość uwagi, niezależnie od tego, czy zawierają istotną treść, czy nie. Przyczyna leży w prostych zasadach matematyki – funkcja Softmax sprawia, że wagi uwagi sumują się na jeden, więc model musi skierować całą swoją uwagę gdzieś, nawet jeśli nic w danej chwili na to nie zasługuje. Unikanie tego nie jest możliwe, więc pierwsze pozycje stają się miejscem wyrzucania nadmiaru uwagi. Nazywa się to „dolem uwagi”.
Zespół z MIT (Xiao i współpracownicy) przekształcił tę osobliwość w narzędzie. Odkryli, że prosty okno przesuwane rozpada się dokładnie w momencie, gdy pierwszy token zostaje usunięty z pamięci podręcznej. Utrzymywanie jedynie pierwszej grupy tokenów jako stałych „zbiorników” zapewnia stabilną generację przy przetwarzaniu milionów tokenów, co jest nawet 22,2 raza szybsze niż ponowne obliczanie każdego okna. Popularne podsumowania często pomijają jeden ograniczenie: nie dodają one żadnych tokenów do rzeczywistej pamięci. Wyjście pozostaje płynne, podczas gdy stare tokeny znikają, a wszystkie informacje, które wypadną poza okno, tracą się na zawsze. Stabilność i pamięć to różne kwestie.
Zatem praktyczną radą jest umieszczenie kluczowej instrukcji tam, gdzie uwaga jest najsilniejsza, zazwyczaj na końcu, oraz przeprowadzenie pomiarów na własnym sprzęcie. Nie jest to rozwiązanie uniwersalne – niektóre badania pokazują, że zbiorniki umieszczone w środku sekwencji lepiej sprawdzają się jako elementy do tłumienia niż ochronne, a zachowanie różni się w zależności od modelu.
Kompresja, okno i zwartość
Pomyśl o walizce, która nie mieści wszystkiego. Możesz pozostawić rzeczy mniej ważne, spakować tylko najnowsze lub napisać notatkę o tym, co zostało w domu. Każda z tych opcji oznacza utratę czegoś innego.
Szybka kompresja
Familia LLMLingua ocenia stopień zaskoczenia każdego tokena za pomocą małego modelu pomocniczego i usuwa te o niskiej zawartości informacji. Efekty są imponujące: do 20 razy większa kompresja w przypadku LLMLingua, a w przypadku LongLLMLingua, który uwzględnia zapytanie, poprawa o 21,4 procent w zadaniach NaturalQuestions przy użyciu jednej czwartej tokenów. To dwa warianty, a nie jeden wynik.
Niezależne testy komplikują obraz sytuacji. W jednym z raportów skierowanych przeciwko repozytorium referencyjnemu stwierdzono, że pełny, niespakowany prompt wykazuje znacznie lepsze wyniki niż spakowany, co jest przeciwieństwem tego, co podano w artykule. Inne badanie dotyczące kompresji w tym obszarze wykazało spadek dokładności liczenia fragmentów, ponieważ kompresja niszczy numerację oraz dokładne ciągi znaków. Nie oznacza to, że kompresja zawodzi – jej niezawodność jest kwestionowana i zależy od typu danych. Tekst narracyjny dobrze ją toleruje, natomiast fragmenty z numeracją, identyfikatory, kod oraz liczby tak nie robią.
Trzy sposoby zarządzania sesją
- Suwak okna. Prosty model „pierwszy przychodzi, pierwszy wychodzi”: przechowuje się ostatnie k wiadomości lub N tokenów, a resztę usuwa. Nie wymaga to żadnych zasobów obliczeniowych, ale powoduje ogromne straty – decyzja podjęta na początku sesji znika już po piątym kroku, a model może zaproponować coś, co jest z nią sprzeczne.
Pułapka: kompresja niszczy zniżkę za cache
Dzięki szybkiemu cache’owaniu dostawca pamięta niezmienioną treść Twojego zapytania i pobieranie go później opłaca się w niewielkiej części standardowej stawki. Cache typu KV przechowuje obliczony stan wcześniejszych tokenów, dzięki czemu model nie musi powtarzać tych obliczeń.
Ceną tej zniżki jest sztywność: prefiks musi być identyczny pod względem bajtów we wszystkich wywołaniach. To wyklucza użycie zmiennego daty czasu na początku, losowego identyfikatora sesji przed instrukcjami czy przetasowanych kluczy w strukturze JSON. Wszystko, co zmienne, powinno znajdować się w sekcji niestabilnej. Zespoły używające profesjonalnych agentów produkcyjnych określają wskaźnik trafień w cache jako najważniejszą metrykę systemu, przy czym różnica kosztów między trafieniem a nieudanym dostępem wynosi około dziesięciokrotnie.
Tutaj pułapka się zamyka. Proces kompresji przepisuje prompt przy każdym wywołaniu, ponieważ tokeny, które są usuwane, zależą od zadawanej pytania, więc każda prośba skutkuje brakiem tokenów w pamięci cache. Oszczędność około sześćdziesięciu procent tokenów idzie w parze ze stratą dziewięćdziesięcioprocentowej zniżki, a strata ta występuje częściej, niż zakładają zespoły.
W materiałach marketingowych krąży anegdota o rachunku miesięcznym, który po wdrożeniu kompresji spadł z około 42 000 dolarów do 2 100 dolarów, przy czym nie podano żadnej firmy, daty ani metody. Niemożliwe jest stwierdzenie, czy ta porównanie uwzględniało utracone tokeny z pamięci cache, która jest właśnie tym czynnikiem decydującym o tym, czy taki wynik się powtórzy.
Plan na poniedziałek
Ta lista nie zastępuje testowania na własnych danych. Zapobiega najczęstszemu błędowi, jakim jest uciekanie się do kompresji lub większego okna czasowego, zanim sprawdzi się tańsze, bezpieczniejsze opcje.
- Klasyfikuj zadanie. Czy chodzi o proste wydobycie faktów, czy o wieloetapowe rozumowanie w długim kontekście? To decyduje o tym, na jak poważny problem naprawdę stanowi degradacja wyników.
- Jeśli jest pogrzebana w środku promptu, przenieś ją na koniec i sprawdź efekt. To zmiana składająca się z jednego zdania i jest jedynym dostępnym narzędziem w tym przypadku.
- Weryfikuj stabilność prefiksów. Gdy prompt systemu różni się nawet o jeden bajt pomiędzy poszczególnymi wywołaniami, cache nie jest przydatny, więc najpierw trzeba to naprawić. W recenzjach kwestia ta jest omawiana znacznie rzadziej niż wybór modelu, choć może mieć większy wpływ na ostateczny wynik.
Co wynieść z tego
Większe okno nie rozwiązuje problemu związанego z zasobem, ponieważ jedynie zwiększa jego pojemność, podczas gdy problemem nie była właśnie ta pojemność.
- Okno to budżet uwagi, a nie przestrzeń przechowywania – każdy dodany token jest pobierany z puli przeznaczonej dla najważniejszych elementów.
Prawdziwa zmiana w codziennej pracy dotyczy kolejności pytań podczas przeglądu projektu. Najpierw należy zapytać, co zawiera kontekst i gdzie znajduje się każdy element, a dopiero potem jak duży jest. Jeśli odwróci się ta kolejność, traci się możliwość lepszej kontroli – ważne informacje mają wtedy większą przestrzeń, w której mogą „zniknąć”. Krótka zasada do pamiętania: najpierw sprawdzić pozycję, potem stabilność, następnie objętość, a kompresję stosować na końcu.