Mniej tokenów to nie oznacza niższych kosztów: dlaczego agenci programistyczne marnują czas, a nie tokeny
Kompresowanie wyników narzędzi może zwiększyć koszt całego zadania programistycznego. Dowiedz się, dlaczego należy mierzyć koszt za ukończone zadanie, zachować ścieżkę odzyskiwania oraz projektować narzędzia dla agentów.
Odkąd agenci programistyczne zyskały popularność, deweloperzy skupiają się na jednej wartości: tokenach. Ile z nich wygenerował model, ile zwróciło narzędzie, jaki jest rozmiar kontekstu, ile zużył agent? To rozumowanie wydaje się logiczne. Mniej tokenów powinno oznaczać niższy rachunek.
Analiza GitHuba dotycząca agenta programistycznego Copilot pokazuje, dlaczego to założenie jest ryzykowne. Usunięcie części tekstu z odpowiedzi narzędzia może sprawić, że całe zadanie stanie się droższe, jeśli usunięty tekst zawierał coś ważnego. Wtedy agent ponownie uruchamia polecenia, wyszukuje oryginalną odpowiedź, poświęca dodatkowy czas na rozumowanie i przenosi większy kontekst we wszystkich kolejnych krokach.
Zatem najtańsza interakcja to nie automatycznie ta z najmniejszą liczbą tokenów. Rzeczywiście chcemy zakończonego zadania programistycznego z jak najmniejszą ilością zmarnowanego wysiłku, a to zmienia sposób oceny wydajności agenta.
Pułapka lokalnej optymalizacji
Załóżmy, że agent wykonywa komendę testową:
npm test
Wydrukuje 50 000 tokenów. Wydaje się to marnotrawstwem, więc piszesz otoczkę, która zmniejsza ilość wyjścia do 2 000. Na papierze to sukces – 48 000 tokenów mniej.
A teraz załóżmy, że te 2 000 tokenów pomija to, czego potrzebował agent. Odpowiada coś w rodzaju:
I need more information about the failing test.
Dlatego ponownie uruchamia polecenie, szuka zapisanego wyniku, otwiera plik logu lub próbuje użyć węższego polecenia. Przepływ staje się następujący:
Original command
↓
Compressed output
↓
Missing information
↓
Agent searches again
↓
Command runs again
↓
More context
↓
More reasoning
Jedno kroku stało się tańsze, podczas gdy sama zadanie kosztowało więcej. GitHub napotkał ten problem podczas testowania sposobów skrócenia wyników generowanych przez Copilot. W jednym z eksperymentów użyto narzędzia o nazwie RTK w celu skrócenia wyjścia z wiersza poleceń, a agenci często ponownie uruchamiali lub przeprowadzali polecenia, gdy brakujący szczegół miał znaczenie. Skutkiem było większa liczba prób, średnio więcej tokenów oraz wolniejsze ukończenie zadania. Z perspektywy czasu wydaje się to oczywiste, ale łatwo o to zapomnieć, gdy optymalizuje się niewłaściwy parametr.
Oceniaj zadanie, a nie wywołanie
Cel agenta to ukończenie zadania programistycznego, a nie minimalizacja kosztu jednego żądania API. Różnica pomiędzy tymi celami jest większa, niż się wydaje. Porównajmy dwa agenty. Agent A:
Task
↓
8 tool calls
↓
100K tokens
↓
Completed in 4 minutes
i Agent B:
Task
↓
15 tool calls
↓
80K tokens
↓
Completed in 9 minutes
Gdy patrzymy tylko na liczby tokenów, B wygrywa. Jednak w przypadku zarządzania organizacją inżynieryjną odpowiedź jest bardziej niejasna. Projekt ukończony szybciej prawdopodobnie wymagał mniej prób, zużył mniej zasobów obliczeniowych, może dostarczyć lepszą poprawkę i skrócić czas oczekiwania programistów. Jeśli ktoś musiałby nadzorować B przez kolejne pięć minut, rzeczywisty koszt B jeszcze bardziej rośnie.
Dlatego GitHub twierdzi, że liczba tokenów na interakcję niewiele mówi o efektywności agenta. Należy optymalizować wynik całego zadań.
Model kosztów end-to-end
Zdolni inżynierowie już wiedzą to z innych doświadczeń. Skrócenie czasu wykonywania zapytania do bazy danych z 200 ms na 100 ms brzmi jak oczywista korzyść. Ale jeśli nowe zapytanie sprawi, że inna usługa wyśle trzy dodatkowe żądania, system może ostatecznie działać wolniej. Należy dostosowywać cały system, a nie pojedynczą operację.
Agenci podlegają tej samej zasadzie. Przydatny model mentalny dotyczący całkowitych kosztów:
Total agent cost =
model inference
+ tool execution
+ retries
+ repeated work
+ context growth
+ developer waiting
+ infrastructure
I wzorzec, który często się pojawia:
smaller response
+
missing context
=
more recovery work
Dlatego inżynieria AI coraz bardziej przypomina inżynierię systemów.
Nie wszystkie wyniki są równie cenne
Godnym uwagi ustaleniem jest to, że wyniki wykonywanych poleceń różnią się gęstością informacji. Powtarzalne logi instalacji, kompilacji, testów oraz postępów mogą być pełne zbędnych danych. Z kolei wyniki przypominające kod źródłowy oraz dowolne rezultaty poleceń mogą zawierać dokładnie to, czego agent potrzebuje. Zamiast jednej reguły kompresji dla wszystkiego, GitHub opracował podejście selektywne. W zasadzie działa ono w następujący sposób:
Command output
│
▼
┌──────────────────────┐
│ What kind of output? │
└──────────┬───────────┘
│
┌─────┼─────┐
│ │ │
▼ ▼ ▼
Source Search Noise
output results logs
│ │ │
▼ ▼ ▼
Keep Reorganize Compress
all without selectively
losing
content
To jest lepsze od bezpośredniej alternatywy:
if output.length > X:
truncate()
Prosta zasada optymalizuje liczbę. Zasada selektywna optymalizuje zdolność agenta do dalszej pracy.
Czego uczy git diff
Załóżmy agenta, który edytował pięć plików i teraz uruchamia:
git diff
Wynik jest długi. Prosty kompresor uznałby go za zbyt duży i spróbowałby go skrócić. Jednak różnica między wersjami może zawierać dokładnie to, czego agent potrzebuje, aby ocenić, czy jego zmiany są poprawne. GitHub donosi, że wczesne wersje jego kompresora rzeczywiście skracały wyniki git diff, a testy pokazały, że agenci musieli ponownie otwierać oryginalny wynik, aby odzyskać te informacje. Dlatego ten filtr został usunięty.
To doskonała lekcja specyficzna dla sztucznej inteligencji: nie można uznać czegoś za bezużyteczne tylko dlatego, że jest duże. Niektóre długie wyniki stanowią cenny kontekst, podczas gdy niektóre krótkie są bezwartościowe. Liczba tokenów nie pozwala odróżnić ich od siebie.
Projektowanie własnych narzędzi
Jeśli budujesz agenta do programowania, możesz napisać coś takiego:
const result = await exec(command);
następuje górna granica maksymalna:
return result.stdout.slice(0, 5000);
Wygląda to rozsądnie, ale w tle zakłada się, że pierwsze 5 000 znaków zawiera wszystko, czego agent potrzebuje. Mądrzejszy projekt najpierw klasyfikuje wynik. Zacznij w ten sam sposób:
const result = await exec(command);
Następnie rozgałęźnij się w zależności od rodzaju wyjścia:
const outputType = classifyOutput(result);switch (outputType) {
case "source":
return result.stdout; case "search":
return reorganize(result.stdout); case "repetitive-log":
return compress(result.stdout); default:
return result.stdout;
}
Nawet to wymaga drogi ucieczki, aby agent mógł odzyskać oryginał:
return {
summary,
compressedOutput,
fullOutputAvailable: true
};
Agent otrzymuje zwięzły przegląd, a nic tak naprawdę nie zniknęło. Dla systemów autonomicznych to o wiele lepszy projekt.
Kompresja powinna opóźniać, a nie usuwać
Kompresja nie powinna oznaczać usuwania informacji. Powinna oznaczać jej odroczenie do momentu, gdy będzie potrzebna. Porównaj te dwa podejścia. Zła kompresja wygląda w ten sposób:
Original output
↓
Throw away 90%
↓
Agent cannot recover it
Lepsza kompresja utrzymuje drogę powrotną otwartą:
Original output
↓
Create useful summary
↓
Agent continues
↓
Needs more detail?
↓
Retrieve original
To bardziej przypomina sposób działania buforowania w zwykłym oprogramowaniu. Agent nie musi mieć wszystkiego od razu, ale nie powinien tracić dostępu do niczego ważnego. Rozwiązanie dostarczane przez GitHub umożliwia szybkie odzyskanie dostępu po skompresowaniu wyników.
Czasami więcej kontekstu jest korzystniejsze
To brzmi odwrotnie. Programiści od lat starają się zmniejszać ilość kontekstu. Jednak większy kontekst może zapobiec dodatkowej pracy. Załóżmy, że agent dostrzega zwięzłą informację o błędzie:
Test failed:
Expected 401
Received 500
Pełny wynik mógłby również pokazać:
Database connection refused
JWT middleware initialized correctly
Request reached /api/auth/login
PostgreSQL timeout after 5 seconds
Wersja skrócona informuje agenta, że coś się nie udało. Pełna wersja mówi, że prawdopodobnie nie leży to w winie logiki autoryzacji, a problemem jest połączenie z bazą danych. Druga wersja kosztuje więcej tokenów, ale może zaoszczędzić pięć wywołań narzędzia. Kontekst ma swoją cenę, podobnie jak brak kontekstu. Wyzwaniem inżynieryjnym jest znalezienie równowagi pomiędzy tymi dwoma czynnikami.
Dlaczego agenty wydają się krążyć w kółko
Prawdopodobnie widzieliście już agenta robiącego coś w ten sposób:
Run command
↓
Read partial output
↓
Run another command
↓
Search same file
↓
Run original command again
↓
Read more output
↓
Change code
↓
Run test
↓
Go back to original command
Wygląda to na zamieszanie, a czasami rzeczywiście nim jest. Ale czasami infrastruktura po prostu nie dostarcza modelowi wystarczająco dużo informacji, a agent próbuje nadrobić braki w interfejsie. Jeśli agent ciągle prosi o to samo, przyczyną może być projekt narzędzia, a nie model.
Projekt narzędzi to UX dla modeli
Rozwijający zazwyczaj oceniają API na podstawie danych wejściowych, wyjściowych, opóźnień, błędów oraz mechanizmów autoryzacji. Narzędzia do AI wymagają dodatkowego pytania: w jaki sposób to wyjście wpływa na kolejną decyzję modelu? Weźmy dwa przykłady odpowiedzi. API A:
{
"status": "failed"
}
i API B:
{
"status": "failed",
"error": "PostgreSQL connection timeout",
"service": "auth-api",
"retryable": true,
"attempt": 2,
"duration_ms": 5040
}
B zawiera więcej danych, ale może obniżyć całkowity koszt systemu, ponieważ agent może podjąć właściwą decyzję na miejscu. Celem nie jest najmniejszy możliwy plik JSON, lecz informacje, które umożliwiają agentowi podjęcie następnej słusznej decyzji.
Dostosowywanie całego cyklu
GitHub nie traktuje tego jako pojedynczego problemu kompresji. W swoich opisach wymienia kilka zmian: zachowanie przydatnego kontekstu przy jednoczesnym eliminowaniu powtórzeń, usunięcie formatowania, które nie pomaga w wykonywaniu zadania, skrócenie instrukcji bez zmiany zachowania oraz unikanie niepotrzebnych kroków pobierania danych dla zadań w tle. Każda zmiana była oceniana offline na podstawie benchmarków kodowania agentów, a następnie zweryfikowana w kontrolowanych eksperymentach online przed wprowadzeniem do użycia.
To właśnie jest inżynieria wydajności dla agentów. Pytanie zmienia się z tego, jak skrócić odpowiedź, na to, jak pomóc agentowi ukończyć zadanie z mniejszą ilością marnotrawionych zasobów – i to o wiele lepsze pytanie.
Obserwowalność dla agentów
To zmienia to, co śledzisz w środowisku produkcyjnym. W przypadku zwykłych usług obserwowałbyś:
Latency
Error rate
CPU
Memory
Throughput
Dla agentów, dodaj więcej:
Task completion rate
Tool-call count
Retry rate
Repeated-command rate
Context growth
Model escalation rate
Time to completion
Cost per completed task
Human intervention rate
Większość z nich to metryki przepływu pracy, a nie metryki tokenów. Tokeny wciąż są ważne, ale one wpływają na aspekty ekonomiczne, a nie określają efektywności.
Koszt za udaną zadanie
Najprostszą zmianą, jaką można wprowadzić, jest zaprzestanie śledzenia tego parametru:
cost per request
a zamiast tego śledź to:
cost per successfully completed task
Nie są równoważne. Rozważmy agenta o następujących wartościach:
Agent A
$0.20/task
70% success rate
w porównaniu z tym:
Agent B
$0.35/task
95% success rate
Taniejsza propozycja niekoniecznie oznacza tańszy system. Unormalizuj ją:
Effective cost
= inference cost / successful tasks
Dla A:
$0.20 / 0.70
≈ $0.286
Dla B:
$0.35 / 0.95
≈ $0.368
W tym prostym kryterium A wygrywa. Ale jeśli A wymaga znacznie większej opieki ze strony programistów, sytuacja ekonomiczna znów się zmienia, dlatego zespoły ostatecznie potrzebują szerszej definicji kosztu zadania.
To samo zasada dotyczy wyboru modeli
To wiąże się z przechodzeniem na system kierowania modelami. Przegląd badawczy HydraFusion w GitHubie już traktuje procesy programistyczne jako problem optymalizacyjny, wybierając dla każdego zadania między pojedynczym modelem, przechodzeniem na silniejsze modele lub drugim modelem pełniącym rolę niezależnego krytyka. Testy offline w kontrolowanych warunkach miały pokazać duże oszczędności, przy czym jakość w niektórych testach była równa lub wyższa od standardu Opus 5, który używano.
Połącz to z wcześniejszą lekcją. Inteligentny agent nie pyta tylko, który model jest najtańszy. Pyta, który proces pozwala ukończyć zadanie z najmniejszymi stratami. Taki proces może łączyć:
Cheap model
+
Good context
+
Efficient tools
+
Verification
i pokonaj tego:
Expensive model
+
Poor context
+
Repeated tool calls
Inteligencja nie znajduje się już tylko w modelu. Jest rozproszona w całym systemie.
Jeśli tworzysz produkty AI
Kuszące jest najpierw optymalizowanie oczywistych wskaźników: mniejsze zużycie tokenów, krótsze polecenia, krótsze wyniki, tańsze modele. Nie dostosowuj tylko ich. Zinstrumentalizuj cały proces pracy:
User request
↓
Model inference
↓
Tool call
↓
Tool response
↓
Model reasoning
↓
Another tool call
↓
Verification
↓
Final result
Zmierz każdy etap, a następnie zastanów się, gdzie agent wykonywa pracę niepotrzebną. Być może narzędzie do bazy danych zwraca zbyt mało kontekstu, albo narzędzie wyszukiwania zwraca zbyt wiele nieistotnych materiałów. Być może agent próbuje ponownie bez potrzeby, albo twoje polecenie zmusza do zbędnego planowania. Być może silniejszy model rozwiązałby to w połowie liczby kroków, albo tańszy model wystarczy do pierwszej próby. To są problemy inżynierii oprogramowania.
Przyszłość to nie mniej tokenów
Kuszące jest sprowadzenie całego problemu kosztów do:
tokens ↓
cost ↓
Prawdziwa relacja wygląda bardziej w ten sposób:
Useful context
↓
Better decisions
↓
Fewer retries
↓
Fewer unnecessary tool calls
↓
Shorter task duration
↓
Lower total cost
Czasami droga do niższych kosztów zaczyna się od dostarczenia modelowi więcej informacji. To jest ta sprzeczna z intuicją kwestia i dlatego inżynieria sztucznej inteligencji przekształca się w dyscyplinę systemową, a nie w ćwiczenie polegające na pisaniu instrukcji.
Mierzenie ukończonej pracy
Gdy oceniasz agenta, nie pytaj tylko o to, ile tokenów wykorzystał. Zapytaj, ile przydatnego oprogramowania stworzył oraz ile pracy zmarnował, aby to osiągnąć. Oznacza to monitorowanie poprawności, opóźnień, wywołań narzędzi, prób ponownych, wielkości kontekstu, kosztu inferencji, interwencji człowieka oraz pomyślnego zakończenia.
System kodowania, który wygra, niekoniecznie będzie generował najmniej tokenów. Można oczekiwać, że to taka konfiguracja, która przekształca każdy token, wezwanie narzędzia i wybór modelu w rzeczywisty postęp. Najnowsze działania inżynieryjne GitHub pokazują właściwy kierunek: optymalizować całe zadanie, zachowywać informacje niezbędne agentowi i eliminować zbędne działania tylko wtedy, gdy wiemy, że nie przynoszą one korzyści. Celem nie jest zmuszenie agentów do robienia mniej, lecz sprawienie, by marnowały mniej zasobów.