Strona główna / Artykuły / Mniej tokenów to nie oznacza niższych kosztów: dlaczego agenci programistyczne marnują czas, a nie tokeny

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.

2258 słó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.