Przejdź do treści
16/30Rozdział 16 z 30

Context window, tokeny i rachunek — zmierzone

40-turowa rozmowa kosztuje 22 razy więcej input tokens niż jej długość. Cache obcina to o 68 %, a zły timestamp dodaje 20 %.

Na tej stronie

Oto czterdziestoturowa rozmowa supportowa, rozliczona tura po turze. Nie ma w niej nic niezwykłego: developer pyta o API, assistant odpowiada akapitem albo dwoma. Cała wymiana ma 5 090 tokenów tekstu — około osiem stron.

turaprompt tokensnowy tekstoutputkoszt tej turysuma narastająco
121318183$0.002622$0.002622
589214123$0.003260$0.014354
101,65619114$0.004680$0.035530
202,86818103$0.006972$0.094426
303,9412099$0.009070$0.174170
404,94717142$0.011598$0.274386

Czytaj drugą i trzecią kolumnę razem. W turze 40 użytkownik wpisał siedemnaście tokenów, a został obciążony za 4 947. Pytanie nie było trudniejsze niż pierwsze; było krótsze. Zmieniło się to, że request niósł ze sobą całą rozmowę, znowu, po raz czterdziesty.

Łączna liczba input tokens rozliczonych w tych czterdziestu wywołaniach: 112 617. Rozmowa ma 5 090 tokenów. Zapłaciłeś za nią dwadzieścia dwa razy.

Ten rozdział wyjaśnia, dlaczego tak się dzieje, jak nazywa się to na fakturze każdego providera i na które z pięciu rozliczanych elementów możesz mieć wpływ.

Pokaż szczegóły

Czego ten rozdział potrzebuje z części II.

  • Rozdział 7 zbudował tokenizer. Token jest jednostką także tutaj — tą samą jednostką, teraz wycenioną.
  • Rozdział 9 wyprowadził self-attention i jego koszt O(n2)O(n^2) w ramce z notacją asymptotyczną. Ten koszt jest powodem, dla którego limit w ogóle istnieje; tutaj linkuję do niego zamiast tłumaczyć go od nowa.
  • Rozdział 13 zmierzył prefill względem decode i policzył, ile zajmuje KV cache. Te dwie fazy są tym, co naprawdę kupują powyższe kolumny input i output.

Cała reszta to TypeScript, bo to księgowość zdalnego wywołania, a nie matematyka modelu.

Najdroższym błędnym przekonaniem w tej branży jest to, że model pamięta rozmowę.

Nie pamięta, a mechanizm z rozdziału 13 mówi dokładnie dlaczego. Stan transformera podczas generowania to KV cache: keys i values policzone dla każdego tokena w sekwencji. Ten cache żyje przez czas trwania jednego requestu. Gdy request się kończy, proces, który go trzymał, może obsłużyć kogoś innego, a cache znika. Po drugiej stronie nie ma per-user store ani sesji.

Następny request musi więc przyjść z wszystkim, co model ma wiedzieć, a model odbudowuje ten stan, wykonując forward pass przez cały prompt, zanim wyemituje choćby jeden nowy token. Rozdział 15 nazwał prompt „całym stanem”. Oto fizyczny powód: prompt jest kompletnym stanem, bo nic innego nie przeżywa wywołania.

Context window to maksymalna długość tego promptu plus jego odpowiedzi. To sufit określający, ile stanu możesz odbudować, a nie pojemnik, który przechowuje cokolwiek między requestami. Nazywanie go „pamięcią modelu” odwraca kierunek przyczynowości — nie wypełniasz pamięci, tylko płacisz za jej ponowne ustanowienie.

Stąd bierze się te dwadzieścia dwa. Tura nn niesie wszystkie n1n-1 poprzednie tury, więc łączny input w rozmowie o nn turach jest sumą rosnącego szeregu, czyli jest kwadratowy:

total input  =  i=1n(s+hi)  =  Θ(n2)\text{total input} \;=\; \sum_{i=1}^{n} \big(s + h_i\big) \;=\; \Theta(n^2)

gdzie ss to system prompt, a hih_i to historia w turze ii. Dopasowanie zmierzonego skumulowanego inputu do an2+bnan^2 + bn na przestrzeni czterdziestu tur daje 60.22n2+432.25n60.22\,n^2 + 432.25\,n, co przewiduje 113 645 tokenów w turze 40 wobec 112 617 zmierzonych. Człon kwadratowy dominuje, a człon liniowy jest tym, co użytkownik naprawdę wpisał.

Konsekwencją jest zdanie, które warto wynieść z tego rozdziału: twój rachunek rośnie z kwadratem rozmowy, nie z ostatnim pytaniem. Te same czterdzieści pytań zadanych bez żadnej historii kosztuje $0.066036. Utrzymanie historii kosztowało $0.274386. Historia pomnożyła rachunek przez 4,2 i będzie mnożyć dalej, bo mnożnikiem jest długość rozmowy.

Okno jest skończone z dwóch powodów, które ciągną w tę samą stronę. Pierwszy to powód z rozdziału 9: attention porównuje każdy token z każdym innym tokenem, więc praca tej warstwy rośnie z kwadratem długości sekwencji. Drugi to pamięć: KV cache rośnie liniowo z długością sekwencji, a rozdział 13 wykonał tę arytmetykę — przy długich sekwencjach jest większy niż weights.

Oba limity atakowano i żadnego nie usunięto. FlashAttention1 reorganizuje obliczenia tak, by znacznie mniej czytać i zapisywać w pamięci o dużej przepustowości, co czyni długie sekwencje praktycznymi bez zmiany kosztu asymptotycznego. Position Interpolation2 i YaRN3 rozszerzają użyteczne okno wytrenowanego modelu przez przeskalowanie positional encodings z rozdziału 9 zamiast retrainingu. Razem wyjaśniają, dlaczego okna urosły z 2K do 1M w pięć lat.

Nie sprawiły jednak, że długie contexts stały się darmowe. Podniosły sufit i złagodziły nachylenie. Nachylenie wciąż istnieje i to właśnie mierzą tier cenowe w dalszej części tego rozdziału.

Prawie każdy kalkulator kosztów w internecie modeluje wywołanie API jako input tokens razy cena inputu plus output tokens razy cena outputu. To było prawdziwe w 2023 roku. Dziś jest błędne w sposób, który potrafi rozjechać rachunek o czynnik dwa albo więcej w obie strony.

Istnieje pięć rozliczalnych kategorii tokenów:

koszykco to jesttypowa cena względem inputu
uncached inputprompt tokens, które model musiał przetworzyć od zera
cache readprompt tokens obsłużone z zapisanego prefiksu0,1×
cache writeprompt tokens zapisane do cache w tym wywołaniu1,25× do 2×
outputtokeny wygenerowane przez model i wysłane do ciebie5× do 6×
reasoningtokeny wygenerowane przez model i niewysłane do ciebiestawka outputu

Trzy z tych pięciu nie istniały jako osobne pozycje dwa lata temu, a dwie linie cache są tym, co ludzie mylą najczęściej, bo cache write kosztuje więcej niż zwykły input, nie mniej. Płacisz premię za zapisanie czegoś, żeby potem zapłacić mniej za odczyt, a opłacalność tej wymiany zależy wyłącznie od tego, ile razy to odczytasz.

Koszyk reasoning należy do rozdziału 12, teraz z ceną, i niesie szczegół, który warto powiedzieć wprost: dokumentacja Google mówi, że pricing „is based on the full thought tokens the model needs to generate, despite only the summary being output from the API”.4 Rozliczane są tokens, które nigdy nie są do ciebie transmitowane. To jedyny koszyk, którego zawartości nie możesz policzyć, obejrzeć ani zweryfikować.

Teraz część, która robi z tego problem normalizacji, a nie mnożenia. Każdy provider raportuje te koszyki pod innymi nazwami i — to jest pułapka — dwóch z nich używa tego samego słowa dla dwóch różnych wielkości.

Weź jedno wywołanie: 4 837 tokenów odczytanych z cache, 110 świeżych, 142 widoczne output tokens, 300 reasoning tokens.

three usage payloads, one callJSON
// OpenAI-compatible
{ "usage": { "prompt_tokens": 4947,
             "prompt_tokens_details": { "cached_tokens": 4837 },
             "completion_tokens": 442,
             "completion_tokens_details": { "reasoning_tokens": 300 } } }

// Anthropic
{ "usage": { "input_tokens": 110,
             "cache_read_input_tokens": 4837,
             "cache_creation_input_tokens": 0,
             "output_tokens": 442 } }

// Gemini
{ "usageMetadata": { "promptTokenCount": 4947,
                     "cachedContentTokenCount": 4837,
                     "candidatesTokenCount": 142,
                     "thoughtsTokenCount": 300 } }

Spójrz na prompt_tokens: 4947 i input_tokens: 110. Oba pola są liczbą input tokens dla tego samego promptu. Pole OpenAI zawiera cached tokens; pole Anthropic je wyklucza — jego dokumentacja podaje tożsamość wprost, total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens.5 Anthropicowe input_tokens oznacza „tokens po ostatnim cache breakpoint”.

Spójrz też na output. OpenAI i Anthropic raportują 442, co już zawiera 300 reasoning tokens. Gemini raportuje 142 i wkłada 300 do osobnego pola. Rozdział 12 oznaczył to jako niekompatybilność między dwoma sposobami liczenia tej samej pracy; tutaj widać, ile to kosztuje.

Normalizator ma trzydzieści linii i nie jest opcjonalny:

normalise.tsTS
export interface Usage {
  promptTokens?: number;        // input, NOT cached
  cachedInputTokens?: number;   // read from cache
  cacheWriteTokens?: number;    // written to cache on this call
  completionTokens?: number;    // output
  reasoningTokens?: number;     // billed apart from output (Gemini only)
}

const num = (v: unknown) => (typeof v === "number" && isFinite(v) ? v : 0);

export const fromOpenAI = (raw: any): Usage => {
  const u = raw.usage ?? {}, d = u.prompt_tokens_details ?? {};
  const cached = num(d.cached_tokens), write = num(d.cache_write_tokens);
  return {
    promptTokens: Math.max(0, num(u.prompt_tokens) - cached - write), 
    cachedInputTokens: cached,
    cacheWriteTokens: write,
    completionTokens: num(u.completion_tokens),   // reasoning already inside
    reasoningTokens: 0,
  };
};

export const fromAnthropic = (raw: any): Usage => {
  const u = raw.usage ?? {};
  return {
    promptTokens: num(u.input_tokens),            // already excludes cache
    cachedInputTokens: num(u.cache_read_input_tokens),
    cacheWriteTokens: num(u.cache_creation_input_tokens),
    completionTokens: num(u.output_tokens),
    reasoningTokens: 0,
  };
};

export const fromGemini = (raw: any): Usage => {
  const m = raw.usageMetadata ?? {}, cached = num(m.cachedContentTokenCount);
  return {
    promptTokens: Math.max(0, num(m.promptTokenCount) - cached),
    cachedInputTokens: cached,
    cacheWriteTokens: 0,
    completionTokens: num(m.candidatesTokenCount), // EXCLUDES thinking
    reasoningTokens: num(m.thoughtsTokenCount),    // billed at output rate
  };
};

Przepuść trzy powyższe payloady przez trzy readery, a wszystkie trzy wyprodukują to samo Usage, a więc tę samą kwotę: $0.006491. Ta zgodność jest całym sensem pisania tej warstwy.

Pomyłka kosztuje tak, dla tego samego wywołania:

błądrozliczoneodchylenie
traktowanie cached_tokens jako dodatkowego względem prompt_tokens$0.0161652,49× — naliczasz prompt dwa razy
traktowanie cache reads jako darmowych zamiast 0,1×$0.0055240,85× — zjadasz 15 %
czytanie candidatesTokenCount i ignorowanie thoughtsTokenCount$0.00289155 % wywołania znika

Trzeci jest niebezpieczny, bo zawodzi po cichu w kierunku dobrych wiadomości. Dashboard pokazuje, że reasoning model kosztuje mniej niż połowę realnego kosztu, i nigdzie nic nie zgłasza błędu.

Po znormalizowaniu koszyków funkcja kosztu jest krótka. Jedyna nieoczywista część to lookup tier, który wyjaśnia następna sekcja:

cost.tsTS
export interface Tier { maxPromptTokens: number | null; price: number }
export interface Pricing {
  input: Tier[]; output: Tier[];
  cachedInput?: Tier[]; cacheWrite?: Tier[]; reasoning?: Tier[];
}

const tierPrice = (tiers: Tier[] | undefined, contextSize: number, fallback?: Tier[]) => {
  const table = tiers ?? fallback;
  if (!table?.length) return 0;
  const sorted = [...table].sort(
    (a, b) => (a.maxPromptTokens ?? Infinity) - (b.maxPromptTokens ?? Infinity));
  for (const t of sorted)
    if (t.maxPromptTokens === null || contextSize <= t.maxPromptTokens) return t.price;
  return sorted[sorted.length - 1].price;
};

export function computeCost(pricing: Pricing, usage: Usage): number {
  const fresh = usage.promptTokens ?? 0;
  const read  = usage.cachedInputTokens ?? 0;
  const write = usage.cacheWriteTokens ?? 0;
  const out   = usage.completionTokens ?? 0;
  const think = usage.reasoningTokens ?? 0;
  const contextSize = fresh + read + write;   // the tier depends on the WHOLE prompt
  return fresh * tierPrice(pricing.input, contextSize)
       + read  * tierPrice(pricing.cachedInput, contextSize, pricing.input)
       + write * tierPrice(pricing.cacheWrite,  contextSize, pricing.input)
       + out   * tierPrice(pricing.output, contextSize)
       + think * tierPrice(pricing.reasoning, contextSize, pricing.output);
}

Warto bronić dwóch decyzji projektowych. Fallbacki — ceny cache spadające do inputu, reasoning do outputu — kodują znaczenie brakującej tabeli: reasoning tokens w Gemini są rozliczane według stawki outputu, więc brak ceny reasoning nie oznacza zera, tylko cenę outputu. A contextSize sumuje wszystkie trzy koszyki inputu, nie tylko świeże, bo tier wybiera się według długości promptu, a nie według tego, za ile z niego zapłaciłeś pełną cenę.

Prompt cache przechowuje obliczony stan modelu dla prefiksu twojego promptu, więc późniejszy request z tym samym prefiksem pomija jego ponowne liczenie. Ze słowa „prefiks” wynikają cztery własności i wszystkie cztery zaskakują ludzi.

Cache dopasowuje od początku wyrenderowanego promptu do przodu i zatrzymuje się na pierwszym bajcie, który się różni. Nie ma częściowego uznania za treść, która pojawia się później w innej kolejności. OpenAI mówi to wprost: „cache reuse requires the entire rendered prefix to match”.6

Poniżej niej nic nie trafia do cache i nie wraca żaden błąd. W OpenAI minimum to 1 024 tokeny dla GPT-5.6 i późniejszych oraz 2 048 dla starszych modeli. W Anthropic zakres wynosi od 512 do 4 096 zależnie od modelu — 1 024 dla Claude Sonnet 4.5, 4 096 dla Claude Haiku 4.5. Jeśli oba pola cache wracają jako zero, zwykle to jest powód.

Zapis kosztuje więcej niż odczyt i więcej niż brak cache

Link do sekcji: Zapis kosztuje więcej niż odczyt i więcej niż brak cache

W OpenAI i Anthropic cache write kosztuje 1,25× stawki uncached input dla krótkotrwałego cache, a godzinny cache Anthropic kosztuje 2×. Odczyt to 0,1×. Google nie pobiera opłaty za zapis, ale wynajmuje storage: $4.50 za milion tokenów na godzinę w Gemini 2.5 Pro.

Domyślny wpis Anthropic żyje pięć minut, odświeżany za darmo przy każdym trafieniu. W OpenAI to co najmniej trzydzieści minut po ostatnim zapisie albo reuse. OpenAI zauważa też, że cached states żyją na pojedynczych maszynach, więc request trafia tylko wtedy, gdy zostanie skierowany do maszyny trzymającej wpis — na co wpływa prompt_cache_key, bez gwarancji.

Próg opłacalności jest na tyle mały, że da się go trzymać w głowie, a dokumentacja OpenAI robi rachunek: zapisanie prefiksu raz i użycie go ponownie raz kosztuje 1,35× zwykłego kosztu inputu, wobec 2× za przetworzenie go dwa razy bez cache; w dziesięciu requestach jeden zapis i dziewięć odczytów kosztują 2,15× wobec 10×. Jedno ponowne użycie spłaca zapis. Anthropic ląduje w tym samym miejscu: jeden odczyt dla cache pięciominutowego, dwa dla godzinnego.

Teraz znów czterdziestoturowa rozmowa, z włączonym caching i stabilnym prefiksem:

uncached inputcache readscache writessuma
bez cache112,617$0.274386
caching2,887104,7834,947$0.088250

O sześćdziesiąt osiem procent taniej, a trzy liczby w tej tabeli są warte uwagi.

Cache nie włącza się aż do tury 6. Prompt nie osiąga 1 024 tokenów wcześniej, więc pierwsze pięć tur jest rozliczane dokładnie jak przedtem — a szósta jest rozliczana gorzej, z premią 1,25× za zapis, bo to tura, która wypełnia cache. Pierwszy odczyt przychodzi w turze 7. 2 887 uncached tokens w tabeli to arytmetyka: pięć tur, nie sześć. Caching jest rabatem na długie prompty, a krótka rozmowa nic z niego nie ma.

Premia za zapis to $0.002474, czyli 2,8 % rachunku z cache. Każda tura zapisuje nowy ogon, czterdzieści razy, a cała premia za zapis jest błędem zaokrąglenia wobec tego, co oszczędziły odczyty. Opłatę za zapis warto rozumieć precyzyjnie po to, żeby przestać się nią martwić.

Tylko 2 887 tokenów rozliczono po pełnej cenie inputu z 112 617. Tak wygląda działający cache: prawie wszystko jest odczytem.

Kolejność promptu decyduje, czy cokolwiek z tego zadziała

Link do sekcji: Kolejność promptu decyduje, czy cokolwiek z tego zadziała

Oto awaria, która kosztuje prawdziwe pieniądze, i jest jednolinijkowym bugiem.

Umieść coś, co zmienia się przy każdym wywołaniu, blisko początku promptu — timestamp, request id, imię użytkownika, linię „dziś jest”, świeżo pobrany dokument — a prefiks różni się od pierwszego bajtu. Nic nie pasuje. Każde wywołanie jest pudłem. A ponieważ każde wywołanie prezentuje nowy prefiks, każde wywołanie także zapisuje.

Ta sama rozmowa, te same czterdzieści tur, włączony caching, z timestampem per call na górze system promptu:

sumawzględem
bez żadnego caching$0.274386
caching, stabilny prefiks$0.088250−67,8 %
caching, zmienny prefiks$0.329251+20,0 %

Włączenie prompt caching uczyniło rozmowę o dwadzieścia procent droższą niż niewłączanie go. Zapłaciłeś premię 1,25× za zapis na 109 730 tokenach i odczytałeś z powrotem zero. Nie ma błędu, nie ma warningu, a funkcja jest włączona.

Zasada, czyli całe prompt caching w jednym zdaniu: stabilna treść z przodu, zmienna treść z tyłu. System instructions, definicje tooli i materiały referencyjne najpierw; timestamps, tożsamość użytkownika i bieżące pytanie na końcu. Anthropic pokazuje hierarchię wprost — cache podąża za toolssystemmessages, a zmiana na dowolnym poziomie unieważnia ten poziom i wszystko po nim, więc edycja jednego opisu toola unieważnia cały cache.5

Dwie konsekwencje często podcinają nogi. Zmiana tego, które tools są włączone, zmienia definicje tooli, więc feature flag dodający tool dla części użytkowników dzieli cache na dwa. A w Anthropic przełączenie web search albo citations modyfikuje system prompt, co unieważnia cache systemu i wiadomości bez dotykania choćby jednej linijki twojego tekstu.

Ucinanie historii nie jest naprawą

Link do sekcji: Ucinanie historii nie jest naprawą

Oczywistą odpowiedzią na kwadratowy rachunek jest przestać wysyłać całą historię: zachować ostatni tuzin wiadomości i wyrzucić resztę. To obniża rachunek, zwykle jest złym ruchem, a pomiar pokazuje dlaczego.

strategiasumawzględem pełnej historii + cache
pełna historia, bez cache$0.274386+211 %
pełna historia, caching$0.088250
ostatnie 12 wiadomości, bez cache$0.118712+35 %
ostatnie 12 wiadomości, caching włączony$0.122546+39 %

Ucięcie do okna dwunastu wiadomości jest o 57 % tańsze niż wysyłanie wszystkiego bez cache — to porównanie robią wszyscy i dlatego ta technika jest popularna. Ale jest o 39 % droższe niż wysyłanie wszystkiego z działającym cache, a włączenie caching razem z truncation pogarsza wynik zamiast go poprawić.

Mechanizmem znów jest prefiks. Sliding window wyrzuca najstarszą wiadomość w każdej turze, więc prompt nie zaczyna się już tam, gdzie zaczynał się poprzednio, i każda tura prezentuje nowy prefiks. Wskazówka OpenAI mówi dokładnie to: „summarisation, compaction, or context truncation can change the prefix and reset cache reuse”.6 W turze 40 prompt okienkowy ma 813 tokenów, poniżej minimum 1 024 tokenów, więc w ogóle nie może zostać zcacheowany.

A pieniądze są tańszą połową kosztu. To, co wyrzuciłeś, to instrukcja, którą użytkownik dał w turze 2 i której model potrzebował w turze 40. Truncation zamienia widoczny rachunek na niewidoczną awarię, a robienie tego dobrze — compaction, structured notes trzymane poza oknem, pobieranie historii na żądanie — jest tematem rozdziału 24.

Przekroczenie tier wycenia od nowa cały request

Link do sekcji: Przekroczenie tier wycenia od nowa cały request

Długie contexts są droższe nie tylko dlatego, że są dłuższe. Po przekroczeniu progu są droższe per token, a próg działa wstecznie na cały prompt.

Strona modelu OpenAI dla gpt-5.6-terra mówi to jednym zdaniem: „Prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request”.7 Nie za nadwyżkę. Za całość.

the most expensive token you will ever sendTEXT
prompt 271,999 + 500 output  ->  $0.5500
prompt 272,000 + 500 output  ->  $0.5500
prompt 272,001 + 500 output  ->  $1.0970

Jeden token, pięćdziesiąt pięć centów. Jeśli twój serwis buduje prompty z pobranych dokumentów, których rozmiaru nie kontrolujesz, masz w modelu kosztowym klif na granicy, której nikt w zespole nie zapisał.

Pricing Google działa tak samo z progiem 200 000 tokenów: Gemini 2.5 Pro kosztuje $1.25 za milion input tokens dla promptów do 200K i $2.50 powyżej, przy output rosnącym z $10.00 do $15.00.8 Anthropic poszedł w drugą stronę — według dokumentacji z 6 września 2026 Claude 4.6 i późniejsze obejmują pełne jednomilionowe context window w standardowej cenie, więc „a 900k-token request is billed at the same per-token rate as a 9k-token request”.9 Wcześniejsze modele utrzymywały dopłatę.

Dlatego cena nie jest liczbą. Cena jest tabelą tier indeksowanych długością promptu — po to w funkcji kosztu jest Tier[] — i dlatego computeCost wybiera tier przy użyciu całego promptu, a nie każdego koszyka osobno.

Prefill, decode i dlaczego output kosztuje sześć razy tyle co input

Link do sekcji: Prefill, decode i dlaczego output kosztuje sześć razy tyle co input

Pięć koszyków mapuje się na dwie fazy z rozdziału 13, a gdy zobaczysz mapowanie, relacje cen przestają wyglądać arbitralnie.

Input tokens to prefill. Cały prompt przechodzi przez model w jednym przebiegu, przetwarzany równolegle — duże mnożenia macierzy, compute-bound. Koszt per token jest niski i to ta faza ustala time to first token: prompt o długości 4 947 tokenów ma 4 947 tokenów prefill do wykonania, zanim pojawi się pierwsze słowo.

Output tokens to decode. Są produkowane po jednym, każdy jako pełny forward pass czytający cały KV cache, z GPU głównie czekającym na pamięć zamiast liczyć. To ta faza ustala tokens per second, nie da się jej zrównoleglić wewnątrz jednej odpowiedzi i dlatego output kosztuje około sześć razy więcej niż input w modelu wycenianym tutaj: $12.00 wobec $2.00 za milion tokenów.

Z tego wynikają trzy bezpośrednie konsekwencje. Cache read zastępuje pracę prefill, więc kupuje naraz latency i pieniądze — ten sam rabat widać jako niższy rachunek i krótsze czekanie na pierwszy token. Reasoning tokens to decode, którego nigdy nie widzisz, dlatego reasoning model przez kilka sekund nic nie streamuje, a potem szybko odpowiada: rozdział 12 ostrzegał przed konsekwencją w interfejsie, a to jest konsekwencja na fakturze. I przerwanie streamu nie zatrzymuje generowaniarozdział 14 zbudował cancellation i zostawił cenę temu rozdziałowi, a ceną jest pełna liczba output, bo tokeny są produkowane i rozliczane niezależnie od tego, czy ktokolwiek słucha. To samo dotyczy odpowiedzi, której nikt nie zachowuje: pięć regeneracji odpowiedzi w turze 40 kosztuje $0.057990 za tę jedną pozostawioną na ekranie.

Liczenie tokenów przed wysłaniem

Link do sekcji: Liczenie tokenów przed wysłaniem

Tokenizer z rozdziału 7 był w Pythonie i tam został. Budżetowanie dzieje się na serwerze, który buduje request, więc musi dziać się tutaj, i istnieją dokładnie trzy poziomy dokładności.

Poziom pierwszy: licz lokalnie. js-tiktoken dostarcza te same tabele BPE merge co pythonowy tiktoken, więc dostajesz byte-for-byte identyczne liczenie dla OpenAI encodings, bez wywołania sieciowego:

count.tsTS
import { getEncoding } from "js-tiktoken";

const enc = getEncoding("o200k_base");
const PER_MESSAGE = 4;   // role and delimiters added by the chat template
const PER_REPLY = 3;     // priming for the assistant turn

export function promptTokens(messages: { role: string; content: string }[]) {
  return messages.reduce(
    (sum, m) => sum + enc.encode(m.content).length + PER_MESSAGE, PER_REPLY);
}

Dwie stałe mają znaczenie i to w nich lokalne liczenia odpływają. Twój tekst nie jest tym, co trafia do tokenizacji — chat template z rozdziału 11 najpierw owija każdą wiadomość markerami ról, a to są tokeny, za które płacisz. Cztery na wiadomość i trzy na reply priming to zwyczajowe przybliżenie dla modeli chat OpenAI; dla osiemdziesięciu jeden wiadomości z powyższej rozmowy daje to 324 tokeny, 6,4 % jej długości. Liczenia tutaj zostały sprawdzone względem pythonowego tiktoken z rozdziału 7 na wszystkich osiemdziesięciu jeden stringach i są identyczne.

Poziom drugi: zapytaj providera. Anthropic udostępnia /v1/messages/count_tokens, a Google count_tokens; oba przyjmują ten sam kształt requestu co realne wywołanie i zwracają liczbę input tokens za darmo. Używaj ich, gdy nie możesz liczyć lokalnie — a dla Anthropic nie możesz, bo jego tokenizer nie jest opublikowany. Dokumentacja Anthropic ostrożnie mówi, co daje: count „is an estimate” i „may include tokens added automatically by Anthropic for system optimizations”, za które „you are not billed”.10

Poziom trzeci: czytaj usage w odpowiedzi. To jest prawda i przychodzi po wydaniu pieniędzy. Właśnie dlatego istnieją dwa pierwsze poziomy — żeby zdecydować, czy wysłać request, a nie żeby go rozliczyć.

Rzeczy, za które płacisz, a których nikt ci nie pokazuje

Link do sekcji: Rzeczy, za które płacisz, a których nikt ci nie pokazuje

Cztery pozycje, które nie pojawiają się jako pozycje.

System prompt, opłacany przy każdym wywołaniu. Ten powyżej ma 192 tokeny z narzutem template. Przez czterdzieści wywołań daje to 7 680 tokenów — 5,6 % całego rachunku tej rozmowy, za osiem linii napisanych raz. To także najlepszy możliwy kandydat do cache, bo jest stabilny i pierwszy.

Definicje tooli. Nazwa, opis i JSON schema każdego toola wychodzą w każdym requeście, a providerzy dodają na to scaffolding. Anthropic publikuje liczbę: samo włączenie tools dodaje ukryty system prompt o długości 496 tokenów w Claude Sonnet 4.5 z tool_choice ustawionym na auto albo 588 z any lub named tool.9 To jeszcze przed twoimi schema. Rozdział 18 buduje katalog; rozdział 24 mierzy, ile on zjada.

Każde generowanie, także te odrzucone. Pięć regeneracji kosztuje pięć razy. Chat pokazuje jedną.

Myśli, których ci nie pokazano. Rozliczenie opiera się na pełnych thought tokens, choć zwracane jest tylko summary, a twoja księgowość nie może zaudytować tej liczby.

Mieć 200K tokenów to nie znaczy ich używać

Link do sekcji: Mieć 200K tokenów to nie znaczy ich używać

Jedno ostrzeżenie na koniec, bo to naturalna kolejna myśl, a odpowiedź nie jest oczywista.

Milionowe context window nie oznacza miliona użytecznych tokenów. Dokładność retrieval pogarsza się wraz z pozycją: Liu i wsp. odkryli, że modele niezawodnie lokalizują informacje na początku i na końcu długiego inputu, a znacznie gorzej w środku.11 Większe okno kupuje możliwość wysłania więcej, nie pewność, że zostanie to przeczytane.

To zjawisko jest mierzone w tym kursie raz — retrieval rate w dziewięciu pozycjach tego samego promptu o długości 853 tokenów — i należy do rozdziału 24, gdzie zmienia to, co robi agent. Jest cytowane tutaj, bo zmienia to, co powinieneś kupować: najtańszy token to ten, którego nie wysłałeś.

Umiesz już przewidzieć koszt wywołania przed jego wykonaniem, odczytać rzeczywisty koszt po fakcie i odróżnić jedno od drugiego. To obejmuje wszystko w requeście poza częścią, której jeszcze nie dotknąłeś: pokrętłami.

Rozdział 17 to sampling — temperature, top-p, top-k, penalties i determinizm, którego nie masz. Zaczyna od rozbrojenia najbardziej rozpowszechnionego błędu w branży: że temperature jest pokrętłem kreatywności. Nie jest: temperature dzieli logits z rozdziału 4 przed softmax, a jego podniesienie nie sprawia, że model staje się pomysłowy; podnosi prawdopodobieństwo tokenów, które sam model ocenił jako gorsze. Dalej: dlaczego greedy decoding daje mierzalnie gorszy tekst niż sampling, dlaczego top-k i top-p zawodzą na przeciwnych kształtach rozkładu, oraz eksperyment kończący rozdział: dwadzieścia identycznych forward passes przy temperature 0 wraca bit w bit identycznych, gdy model działa sam, a włożenie tego samego promptu do batch obok requestów kogoś innego przesuwa 97 % jego logits.

Nie wszystkie się zgadzają. Powód zaczyna się od ramki o floating-point z rozdziału 2.


Wszystkie ceny, progi i mnożniki w tym rozdziale zostały odczytane z własnych stron providerów 6 września 2026 i podane z tą datą, ponieważ się zmienią. Metoda jest ważniejsza niż liczby: koszyki, reguła prefiksu i arytmetyka tier są stabilne od dwóch lat, podczas gdy każda liczba w nich się poruszyła.

Stanford CS336 lecture 2, Resource accounting, jest najbliższym akademickim omówieniem tego materiału i właściwą kolejną lekturą: wykonuje tę samą arytmetykę po stronie trainingu, którą ten rozdział wykonuje po stronie inference. Liczby tokenów tutaj wyprodukowano z js-tiktoken 1.0.21 przy użyciu encodings o200k_base i cl100k_base, na czterdziestoturowej rozmowie o długości 5 090 tokenów; narzut template per message to konwencjonalne przybliżenie cztery-plus-trzy i jest wskazany wszędzie tam, gdzie został uwzględniony. Dane cache, tier i truncation to udokumentowane reguły pricing zastosowane do tych zmierzonych liczby tokenów, nie obserwacje z live API responses — nie wykonano żadnego płatnego wywołania, aby przygotować ten rozdział, co jest też uczciwym powodem, dla którego twierdzenia o latency są jakościowe, a twierdzenia o kosztach nie.

  1. Dao, T., Fu, D. Y., Ermon, S., Rudra, A. i Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). Dlaczego sufit się przesunął bez zmiany kosztu asymptotycznego.

  2. Chen, S., Wong, S., Chen, L. i Tian, Y. Extending Context Window of Large Language Models via Positional Interpolation. arXiv:2306.15595 (2023).

  3. Peng, B., Quesnelle, J., Fan, H. i Shippole, E. YaRN: Efficient Context Window Extension of Large Language Models. arXiv:2309.00071 (2023).

  4. Google, Thinking, ai.google.dev/gemini-api/docs/thinking, oraz Token counting, ai.google.dev/gemini-api/docs/tokens, oba dostępne 2026-09-06. „Pricing is based on the full thought tokens the model needs to generate, despite only the summary being output from the API.” Obiekt usage raportuje total_input_tokens, total_output_tokens, total_thought_tokens, total_cached_tokens, total_tool_use_tokens i total_tokens — sześć koszyków, z thoughts i tool use poza liczbą output. Wcześniejsza nazwa pola dla tej samej wielkości, nadal zwracana przez powierzchnię generateContent, to thoughtsTokenCount, udokumentowane na trzeciej stronie, ai.google.dev/gemini-api/docs/generate-content/thinking.

  5. Anthropic, Prompt caching, docs.anthropic.com/en/docs/build-with-claude/prompt-caching, dostęp 2026-09-06. Źródło hierarchii unieważniania toolssystemmessages i jej tabeli; minimalnych cacheable lengths per model; tożsamości total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens; oraz domyślnego czasu życia pięciu minut odświeżanego bez opłat przy każdym hit. 2

  6. OpenAI, Prompt caching, platform.openai.com/docs/guides/prompt-caching, dostęp 2026-09-06. Źródło: reguły całego wyrenderowanego prefiksu; minimalnego cacheable prefix (1 024 widoczne input tokens w GPT-5.6 i późniejszych, 2 048 we wcześniejszych); mnożników 1,25× za zapis i 0,1× za odczyt oraz braku opłaty za zapis w GPT-5.5 i wcześniejszych; czasu życia 30 minut; limitów czterech zapisów na request i pięćdziesięciu breakpoint; uwagi o machine affinity i prompt_cache_key; przykładów break-even 1,35×, 2,15× i 10×; oraz stwierdzenia, że summarisation, compaction lub truncation resetuje cache reuse. 2

  7. OpenAI, Pricing (platform.openai.com/docs/pricing) oraz strona modelu dla gpt-5.6-terra, oba dostępne 2026-09-06. gpt-5.6-terra, standard service tier, za milion tokenów: input $2.00, cached input $0.20, cache writes $2.50, output $12.00; long context input $4.00, cached $0.40, writes $5.00, output $18.00; „prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request”; context window 1 050 000 tokenów z maksimum 922 000 input tokens. Ta sama tabela podaje gpt-6-astra po $10.00/$1.00/$12.50/$50.00 oraz gpt-5.6-luna po $0.20/$0.02/$0.25/$1.20. Każdy wyliczony koszt w tym rozdziale używa standardowych short-context stawek gpt-5.6-terra.

  8. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, dostęp 2026-09-06. Gemini 2.5 Pro, za milion tokenów: input $1.25 dla promptów do 200K i $2.50 powyżej; output $10.00 i $15.00, w obu przypadkach opisany jako „including thinking tokens”; context caching $0.125 i $0.25 plus opłata storage $4.50 za milion tokenów na godzinę. Gemini 3.1 Pro Preview używa tego samego progu 200K przy $2.00/$4.00 input i $12.00/$18.00 output.

  9. Anthropic, Pricing, docs.anthropic.com/en/docs/about-claude/pricing, dostęp 2026-09-06. Za milion tokenów, base input / 5-minute cache write / 1-hour cache write / cache read / output: Claude Sonnet 4.5 $3 / $3.75 / $6 / $0.30 / $15; Claude Haiku 4.5 $1 / $1.25 / $2 / $0.10 / $5; Claude Opus 5 $5 / $6.25 / $10 / $0.50 / $25. Mnożniki: 1,25× dla pięciominutowego write, 2× dla godzinnego write, 0,1× dla read. Także źródło stwierdzenia o long-context („Claude 4.6 and later models... include the full 1M token context window at standard pricing”), liczby tokenów tool-use system prompt (496 tokenów w Claude Sonnet 4.5 z tool_choice równym auto lub none, 588 z any albo named tool) oraz uwagi, że Claude 4.7 i późniejsze używają nowszego tokenizer produkującego „approximately 30 % more tokens for the same text”. 2 3

  10. Anthropic, Token counting, docs.anthropic.com/en/docs/build-with-claude/token-counting, dostęp 2026-09-06. Endpoint /v1/messages/count_tokens przyjmuje te same inputs co message i zwraca input token count; dokumentacja stwierdza, że count jest estimate, że może obejmować tokens dodawane automatycznie przez Anthropic na potrzeby system optimisations i że nie są one rozliczane.

  11. Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. i Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Cytowane tutaj, mierzone w rozdziale 24.

Gotowy, żeby to LIA wybierała za Ciebie?

Twórz ze wszystkimi modelami AI w jednym miejscu — zacznij dziś za darmo.