Salta al contenuto
16/30Capitolo 16 di 30

Context window, token e conto: misurati

Una conversazione di 40 turni costa 22 volte la sua lunghezza in input token. La cache taglia il 68%; un timestamp aggiunge il 20%.

In questa pagina

Ecco una conversazione di supporto di quaranta turni, fatturata turno per turno. Non c’è nulla di insolito: uno sviluppatore fa domande su un’API, un assistant risponde in uno o due paragrafi. L’intero scambio è lungo 5.090 token di testo — circa otto pagine.

turnoprompt tokennuovo testooutputcosto di questo turnototale progressivo
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

Leggi insieme la seconda e la terza colonna. Al turno 40 l’utente ha digitato diciassette token ed è stato addebitato per 4.947. La domanda non era più difficile della prima; era più breve. Ciò che è cambiato è che la request portava con sé l’intera conversazione, di nuovo, per la quarantesima volta.

Totale degli input token fatturati su quelle quaranta call: 112.617. La conversazione è lunga 5.090 token. L’hai pagata ventidue volte.

Questo capitolo spiega perché succede, come viene chiamato nella fattura di ciascun provider, e su quali delle cinque cose che ti vengono addebitate puoi intervenire.

Mostra dettagli

Cosa serve a questo capitolo dalla Parte II.

  • Capitolo 7 ha costruito il tokenizer. Anche qui un token è l’unità — la stessa unità, ora con un prezzo.
  • Capitolo 9 ha derivato la self-attention e il suo costo O(n2)O(n^2), nel riquadro sulla notazione asintotica. Quel costo è il motivo per cui esiste un limite, ed è collegato qui invece di essere spiegato di nuovo.
  • Capitolo 13 ha misurato prefill rispetto a decode e calcolato quanto occupa una KV cache. Quelle due fasi sono ciò che le colonne input e output qui sopra stanno effettivamente comprando.

Tutto il resto è TypeScript, perché qui si fa contabilità di una call remota, non matematica su un model.

L’equivoco più costoso in questo settore è pensare che un model ricordi una conversazione.

Non la ricorda, e il meccanismo del Capitolo 13 dice esattamente perché. Lo stato di un transformer durante la generazione è la KV cache: le chiavi e i valori calcolati per ogni token nella sequenza. Quella cache vive per la durata di una sola request. Quando la request finisce, il processo che la conteneva è libero di servire qualcun altro, e la cache sparisce. Dall’altra parte non c’è alcuno store per utente, e nessuna sessione.

Quindi la request successiva deve arrivare portando tutto ciò che il model deve sapere, e il model ricostruisce quello stato eseguendo un forward pass sull’intero prompt prima di emettere un singolo nuovo token. Il Capitolo 15 chiamava il prompt «l’intero stato». Questa è la ragione fisica: il prompt è lo stato completo perché nient’altro sopravvive alla call.

La context window è la lunghezza massima di quel prompt più la sua risposta. È un tetto alla quantità di stato che puoi ricostruire, non un contenitore che conserva qualcosa tra una request e l’altra. Chiamarla «memoria del model» inverte la causalità: non stai riempiendo una memoria, stai pagando per ristabilirne una.

È da qui che arriva il ventidue. Il turno nn porta con sé tutti i n1n-1 turni precedenti, quindi l’input totale su una conversazione di nn turni è la somma di una serie crescente, che è quadratica:

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

dove ss è il system prompt e hih_i la history al turno ii. Adattando l’input cumulativo misurato a an2+bnan^2 + bn sui quaranta turni si ottiene 60.22n2+432.25n60.22\,n^2 + 432.25\,n, che prevede 113.645 token al turno 40 contro i 112.617 misurati. Il termine quadratico domina e il termine lineare è ciò che l’utente ha effettivamente digitato.

La conseguenza da portare via da questo capitolo è questa: la tua fattura cresce con il quadrato della conversazione, non con l’ultima domanda. Le stesse quaranta domande poste senza alcuna history costano $0.066036. Mantenere la history è costato $0.274386. La history ha moltiplicato la fattura per 4,2, e continuerà a moltiplicarla, perché il moltiplicatore è la lunghezza della conversazione.

La window è finita per due motivi che spingono nella stessa direzione. Il primo è quello del Capitolo 9: l’attention confronta ogni token con ogni altro token, quindi il lavoro di quel layer cresce con il quadrato della lunghezza della sequenza. Il secondo è la memoria: la KV cache cresce linearmente con la lunghezza della sequenza, e il Capitolo 13 ha fatto quei conti — su sequenze lunghe è più grande dei pesi.

Entrambi i limiti sono stati attaccati e nessuno dei due è stato eliminato. FlashAttention1 riorganizza il calcolo in modo da leggere e scrivere molto meno nella memoria ad alta banda, rendendo pratiche le sequenze lunghe senza cambiare il costo asintotico. Position Interpolation2 e YaRN3 estendono la window utilizzabile di un model addestrato riscalando le positional encodings del Capitolo 9 invece di fare retraining. Insieme spiegano perché le window sono passate da 2K a 1M in cinque anni.

Quello che non hanno fatto è rendere gratuiti i contesti lunghi. Hanno alzato il tetto e reso più dolce la pendenza. La pendenza c’è ancora, ed è ciò che misurano i tier di prezzo più avanti nel capitolo.

Quasi ogni calcolatore di costi su internet modella una call API come input token moltiplicati per un prezzo di input più output token moltiplicati per un prezzo di output. Nel 2023 era vero. Ora è sbagliato in un modo che produce fatture fuori scala di un fattore due o più, in entrambe le direzioni.

Ci sono cinque categorie di token fatturabili:

bucketcos’èprezzo tipico, relativo all’input
input non in cacheprompt token che il model ha dovuto elaborare da zero
cache readprompt token serviti da un prefisso salvato0,1×
cache writeprompt token salvati nella cache in questa call1,25× a 2×
outputtoken generati dal model e inviati a te5× a 6×
reasoningtoken generati dal model e non inviati a tetariffa output

Tre di queste cinque non esistevano come righe separate due anni fa, e le due righe della cache sono quelle che le persone sbagliano, perché una cache write costa più dell’input ordinario, non meno. Paghi un premio per salvare qualcosa in modo da poter pagare uno sconto quando lo rileggi, e se lo scambio convenga dipende interamente da quante volte lo rileggi.

Il bucket reasoning è quello del Capitolo 12, ora con un prezzo, e porta con sé un dettaglio che vale la pena dire chiaramente: la documentazione di Google dice che il pricing «si basa sui full thought tokens che il model deve generare, anche se dall’API viene restituito solo il riepilogo».4 Ti vengono fatturati token che non ti vengono mai trasmessi. È l’unico bucket di cui non puoi contare, ispezionare o verificare il contenuto.

Ora la parte che rende questo un problema di normalizzazione invece che un problema di moltiplicazione. Ogni provider riporta questi bucket con nomi diversi e — questa è la trappola — due di loro usano la stessa parola per due quantità diverse.

Prendi una call: 4.837 token letti dalla cache, 110 nuovi, 142 output token visibili, 300 reasoning token.

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 } }

Guarda prompt_tokens: 4947 e input_tokens: 110. Entrambi i campi sono il conteggio degli input token per lo stesso prompt. Quello di OpenAI include i token in cache; quello di Anthropic li esclude — la sua documentazione dichiara esplicitamente l’identità, total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens.5 input_tokens di Anthropic significa «i token dopo il tuo ultimo cache breakpoint».

E guarda l’output. OpenAI e Anthropic riportano entrambi 442, che contiene già i 300 reasoning token. Gemini riporta 142 e mette i 300 in un campo separato. Il Capitolo 12 segnalava questa incompatibilità tra due modi di contare lo stesso lavoro; qui vedi quanto costa.

Un normalizzatore è trenta righe e non è opzionale:

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
  };
};

Passa i tre payload sopra attraverso i tre reader e tutti e tre producono lo stesso Usage, e quindi lo stesso numero: $0.006491. Quell’accordo è il motivo stesso per cui scrivere il layer.

Sbaglialo ed ecco quanto costa, sulla stessa call:

errorefatturatoerrore
trattare cached_tokens come aggiuntivo rispetto a prompt_tokens$0.0161652,49× — addebiti il prompt due volte
trattare le cache read come gratuite invece che a 0,1×$0.0055240,85× — assorbi il 15 %
leggere candidatesTokenCount e ignorare thoughtsTokenCount$0.002891il 55 % della call sparisce

Il terzo è quello pericoloso, perché fallisce in silenzio nella direzione delle buone notizie. La tua dashboard mostra un reasoning model che costa meno della metà del suo costo reale, e da nessuna parte compare un errore.

Una volta normalizzati i bucket, la funzione di costo è breve. L’unica parte non ovvia è il lookup del tier, che la sezione successiva spiega:

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);
}

Due decisioni di design meritano di essere difese. I fallback — prezzi cache che ripiegano sull’input, reasoning sull’output — codificano cosa significa una tabella mancante: i reasoning token su Gemini sono fatturati alla tariffa output, quindi un prezzo reasoning assente non è zero, è il prezzo output. E contextSize somma tutti e tre i bucket di input invece dei soli token fresh, perché il tier viene scelto in base a quanto è lungo il prompt, non in base a quanta parte è stata addebitata a prezzo pieno.

Prompt caching, e quanto costa scriverla

Link alla sezione: Prompt caching, e quanto costa scriverla

Una prompt cache salva lo stato calcolato del model per un prefisso del tuo prompt, così una request successiva con lo stesso prefisso evita di ricalcolarlo. Dalla parola «prefisso» seguono quattro proprietà, e tutte e quattro sorprendono.

La cache fa match dall’inizio del prompt renderizzato in avanti, e si ferma al primo byte diverso. Non c’è credito parziale per contenuto che appare più avanti in un ordine diverso. OpenAI lo dice senza giri di parole: «cache reuse requires the entire rendered prefix to match».6

Sotto quella soglia, nulla viene messo in cache e non viene restituito alcun errore. Su OpenAI il minimo è 1.024 token per GPT-5.6 e successivi e 2.048 per i model più vecchi. Su Anthropic varia da 512 a 4.096 a seconda del model — 1.024 per Claude Sonnet 4.5, 4.096 per Claude Haiku 4.5. Se entrambi i campi cache tornano zero, di solito il motivo è questo.

Scrivere costa più che leggere, e più che non usare la cache

Link alla sezione: Scrivere costa più che leggere, e più che non usare la cache

Su OpenAI e Anthropic una cache write costa 1,25× la tariffa dell’input non in cache per la cache a breve durata, e la cache da un’ora di Anthropic costa 2×. Una read costa 0,1×. Google non addebita la scrittura ma affitta lo storage: $4.50 per milione di token all’ora su Gemini 2.5 Pro.

La entry predefinita di Anthropic vive cinque minuti, rinfrescata gratuitamente a ogni hit. Quella di OpenAI dura almeno trenta minuti dopo l’ultima write o reuse. E OpenAI nota che gli stati in cache vivono su singole macchine, quindi una request fa hit solo se viene instradata alla macchina che contiene la entry — ed è ciò su cui influisce prompt_cache_key, senza garantirlo.

Il break-even è abbastanza piccolo da tenerlo a mente, e la documentazione di OpenAI fa i conti: scrivere un prefisso una volta e riutilizzarlo una volta costa 1,35× il suo normale costo di input, contro 2× per processarlo due volte senza cache; su dieci request, una write e nove read costano 2,15× contro 10×. Un solo riutilizzo ripaga la write. Anthropic arriva allo stesso punto: una read per la cache da cinque minuti, due per quella da un’ora.

Ora di nuovo la conversazione di quaranta turni, con caching attiva e prefisso stabile:

input non in cachecache readcache writetotale
senza cache112,617$0.274386
caching2,887104,7834,947$0.088250

Sessantotto per cento in meno, e tre numeri in quella tabella meritano attenzione.

La cache non entra in funzione fino al turno 6. Il prompt non raggiunge 1.024 token prima di allora, quindi i primi cinque turni sono fatturati esattamente come prima — e il sesto è fatturato peggio, con il premio di write 1,25×, perché è il turno che riempie la cache. La prima read arriva al turno 7. I 2.887 token non in cache nella tabella sono il conto: cinque turni, non sei. Il caching è uno sconto sui prompt lunghi, e una conversazione breve non ne ricava nulla.

Il premio di write è $0.002474, cioè il 2,8 % della fattura con cache. Ogni turno scrive la nuova coda, quaranta volte, e l’intero premio di write è un arrotondamento rispetto a ciò che le read hanno risparmiato. Vale la pena capire con precisione l’addebito di write proprio per smettere di preoccuparsene.

Solo 2.887 token sono stati addebitati al prezzo pieno di input su 112.617. Questa è la forma di una cache che funziona: quasi tutto è una read.

L’ordine del prompt decide se tutto questo accade

Link alla sezione: L’ordine del prompt decide se tutto questo accade

Ecco il guasto che costa soldi veri, ed è un bug di una riga.

Metti qualcosa che cambia a ogni call vicino all’inizio del prompt — un timestamp, un request id, il nome dell’utente, una riga «oggi è», un documento appena recuperato — e il prefisso differisce dal primo byte. Nulla fa match. Ogni call è un miss. E poiché ogni call presenta un prefisso nuovo, ogni call scrive anche.

Stessa conversazione, stessi quaranta turni, caching abilitata, con un timestamp per call in cima al system prompt:

totalerispetto a
nessun caching$0.274386
caching, prefisso stabile$0.088250−67,8 %
caching, prefisso volatile$0.329251+20,0 %

Abilitare il prompt caching ha reso la conversazione del venti per cento più costosa che non abilitarla. Hai pagato il premio di write 1,25× su 109.730 token e hai riletto zero. Non c’è errore, non c’è warning, e la feature è attiva.

Quindi la regola, e tutto il prompt caching in una riga, è: contenuto stabile davanti, contenuto variabile dietro. System instructions, definizioni dei tool e materiale di riferimento prima; timestamp, identità utente e domanda corrente dopo. Anthropic rende esplicita la gerarchia — la cache segue toolssystemmessages, e una modifica a qualsiasi livello invalida quel livello e tutto ciò che viene dopo, quindi modificare una sola descrizione di tool invalida l’intera cache.5

Due conseguenze su cui inciampano in molti. Cambiare quali tool sono abilitati cambia le definizioni dei tool, quindi un feature flag che aggiunge un tool per alcuni utenti divide la tua cache in due. E su Anthropic, attivare o disattivare web search o citations modifica il system prompt, invalidando le cache di system e message senza che tu tocchi una riga del tuo testo.

La risposta ovvia a una fattura quadratica è smettere di inviare tutta la history: tenere l’ultima dozzina di messaggi e scartare il resto. Riduce il conto, ed è di solito la mossa sbagliata, e la misura spiega perché.

strategiatotalerispetto a history completa + cache
history completa, senza cache$0.274386+211 %
history completa, caching$0.088250
ultimi 12 messaggi, senza cache$0.118712+35 %
ultimi 12 messaggi, caching attiva$0.122546+39 %

Troncare a una window di dodici messaggi costa il 57 % in meno che inviare tutto senza cache — il confronto che fanno tutti, e il motivo per cui la tecnica è popolare. Ma costa il 39 % in più che inviare tutto con una cache funzionante, e attivare il caching insieme alla troncatura lo rende leggermente peggiore invece che migliore.

Il meccanismo è di nuovo il prefisso. Una sliding window elimina a ogni turno il messaggio più vecchio, quindi il prompt non inizia più dove iniziava la volta precedente e ogni turno presenta un nuovo prefisso. La guida di OpenAI lo dice esattamente: «summarisation, compaction, or context truncation can change the prefix and reset cache reuse».6 Al turno 40 il prompt con window è di 813 token, sotto il minimo di 1.024 token, quindi non può essere messo in cache affatto.

E il denaro è la metà economica del costo. Ciò che hai eliminato è l’istruzione che l’utente ha dato al turno 2 e che al model serviva al turno 40. La troncatura scambia una fattura che puoi vedere con un fallimento che non puoi vedere, e farla bene — compaction, note strutturate tenute fuori dalla window, recupero della history on demand — è l’argomento del Capitolo 24.

Superare un tier riprezza l’intera request

Link alla sezione: Superare un tier riprezza l’intera request

I contesti lunghi non sono più costosi solo perché sono più lunghi. Oltre una soglia sono più costosi per token, e la soglia si applica retroattivamente all’intero prompt.

La pagina model di OpenAI per gpt-5.6-terra lo dice in una frase: «Prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request».7 Non per l’eccedenza. Per tutto.

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

Un token, cinquantacinque centesimi. Se il tuo servizio costruisce prompt da documenti recuperati di cui non controlli la dimensione, hai un dirupo nel tuo modello di costo su un confine che nessuno nel tuo team ha scritto da qualche parte.

Il pricing di Google funziona allo stesso modo con una soglia di 200.000 token: Gemini 2.5 Pro costa $1.25 per milione di input token per prompt fino a 200K e $2.50 oltre, con l’output che passa da $10.00 a $15.00.8 Anthropic è andata nella direzione opposta — al 6 settembre 2026 la sua documentazione afferma che Claude 4.6 e successivi includono l’intera context window da un milione di token al pricing standard, quindi «una request da 900k token è fatturata alla stessa tariffa per token di una request da 9k token».9 I model precedenti mantenevano il sovrapprezzo.

Ecco perché un prezzo non è un numero. Un prezzo è una tabella di tier indicizzata dalla lunghezza del prompt, ed è a questo che serve Tier[] nella funzione di costo, ed è per questo che computeCost seleziona il tier usando l’intero prompt invece di ogni bucket separatamente.

Prefill, decode, e perché l’output costa sei volte l’input

Link alla sezione: Prefill, decode, e perché l’output costa sei volte l’input

I cinque bucket si mappano sulle due fasi del Capitolo 13, e una volta vista la mappa i rapporti di prezzo smettono di sembrare arbitrari.

Gli input token sono prefill. L’intero prompt attraversa il model in un solo passaggio, processato in parallelo — grandi moltiplicazioni di matrici, compute-bound. Il costo per token è basso, e questa è la fase che determina il time to first token: un prompt da 4.947 token ha 4.947 token di prefill da fare prima che compaia la prima parola.

Gli output token sono decode. Vengono prodotti uno alla volta, ciascuno con un forward pass completo che legge l’intera KV cache, con la GPU che passa più tempo ad aspettare la memoria che a calcolare. Questa è la fase che determina i token per secondo, non può essere parallelizzata dentro una singola risposta, ed è il motivo per cui l’output costa circa sei volte l’input sul model prezzato qui: $12.00 contro $2.00 per milione di token.

Ne seguono direttamente tre conseguenze. Una cache read sostituisce lavoro di prefill, quindi compra latenza e denaro insieme — lo stesso sconto appare come fattura più bassa e come attesa più breve per il primo token. I reasoning token sono decode che non vedi, ed è per questo che un reasoning model non streamma nulla per diversi secondi e poi risponde rapidamente: il Capitolo 12 avvertiva della conseguenza sull’interfaccia, e questa è la conseguenza in fattura. E interrompere uno stream non ferma la generazione — il Capitolo 14 ha costruito la cancellation e ha lasciato il prezzo a questo capitolo, e il prezzo è il conteggio completo dell’output, perché i token vengono prodotti e fatturati che qualcuno li ascolti o no. Lo stesso vale per la risposta che nessuno conserva: rigenerare cinque volte una risposta al turno 40 costa $0.057990 per quella che resta sullo schermo.

Il tokenizer del Capitolo 7 era in Python ed è rimasto lì. Il budgeting avviene nel server che costruisce la request, quindi deve avvenire qui, ed esistono esattamente tre livelli di accuratezza.

Livello uno: conta localmente. js-tiktoken distribuisce le stesse tabelle di merge BPE del tiktoken Python, quindi ottieni un conteggio identico byte per byte per gli encoding OpenAI, senza call di rete:

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);
}

Le due costanti contano, e sono il punto in cui i conteggi locali deviano. Il tuo testo non è ciò che viene tokenizzato — il chat template del Capitolo 11 avvolge prima ogni messaggio in marker di ruolo, e quelli sono token che paghi. Quattro per messaggio e tre per il priming della risposta è l’approssimazione convenzionale per i chat model OpenAI; sugli ottantuno messaggi della conversazione sopra sommano 324 token, il 6,4 % della sua lunghezza. I conteggi qui sono stati controllati contro il tiktoken Python del Capitolo 7 su tutte le ottantuno stringhe e sono identici.

Livello due: chiedi al provider. Anthropic espone /v1/messages/count_tokens e Google espone count_tokens, entrambi accettano la stessa forma di request di una call reale e restituiscono gratuitamente un conteggio degli input token. Usali quando non puoi contare localmente — e non puoi contare localmente per Anthropic, il cui tokenizer non è pubblicato. La documentazione di Anthropic è attenta a cosa ti sta dando: il conteggio «è una stima», e «può includere token aggiunti automaticamente da Anthropic per ottimizzazioni di sistema», per i quali «non vieni fatturato».10

Livello tre: leggi usage nella response. Quella è la verità, e arriva dopo che il denaro è stato speso. Ed è precisamente per questo che esistono i primi due livelli — per decidere se inviare la request, non per fatturarla.

Le cose per cui paghi e che nessuno ti mostra

Link alla sezione: Le cose per cui paghi e che nessuno ti mostra

Quattro voci che non compaiono come voci.

Il system prompt, pagato a ogni call. Quello sopra è di 192 token con il suo overhead di template. Su quaranta call fa 7.680 token — il 5,6 % dell’intera fattura di questa conversazione, per otto righe scritte una volta sola. È anche il miglior candidato possibile per la cache, essendo sia stabile sia primo.

Le definizioni dei tool. Nome, descrizione e schema JSON di ogni tool vengono inviati a ogni request, e i provider aggiungono scaffolding sopra. Anthropic pubblica il numero: abilitare i tool aggiunge comunque un system prompt nascosto di 496 token su Claude Sonnet 4.5 con tool_choice impostato a auto, o 588 con any o un tool nominato.9 Questo prima dei tuoi schemi. Il Capitolo 18 costruisce il catalogo; il Capitolo 24 misura quanto consuma.

Ogni generazione, incluse quelle che scarti. Cinque rigenerazioni costano cinque volte. La chat ne mostra una.

Pensieri che non ti vengono mostrati. La fatturazione si basa sui full thought tokens anche se viene restituito solo un riepilogo, e nessuna tua contabilità può auditare quel numero.

Un avvertimento finale, perché è il pensiero successivo naturale e la risposta non è quella ovvia.

Una window da un milione di token non significa un milione di token utilizzabili. L’accuratezza del retrieval degrada con la posizione: Liu et al. hanno trovato che i model localizzano informazioni in modo affidabile all’inizio e alla fine di un input lungo, e molto meno affidabilmente nel mezzo.11 Una window più grande compra la possibilità di inviare di più, non la certezza che venga letto.

Quel fenomeno viene misurato una volta in questo corso — il tasso di retrieval in nove posizioni nello stesso prompt da 853 token — e appartiene al Capitolo 24, dove cambia ciò che fa un agent. È citato qui perché cambia ciò che dovresti comprare: il token più economico è quello che non hai inviato.

Ora puoi prevedere quanto costerà una call prima di farla, leggere quanto è costata dopo, e distinguere le due cose. Questo copre tutto della request tranne la parte che non hai ancora toccato: le manopole.

Il Capitolo 17 è il sampling — temperature, top-p, top-k, le penalità, e il determinismo che non hai. Inizia smontando l’errore più diffuso nel settore, cioè che la temperature sia una manopola della creatività. Non lo è: la temperature divide i logits del Capitolo 4 prima della softmax, e alzarla non rende il model fantasioso, aumenta la probabilità di token che il model stesso ha valutato peggiori. Da lì, perché il greedy decoding produce testo misurabilmente peggiore del sampling, perché top-k e top-p falliscono su forme opposte di distribuzione, e l’esperimento che chiude il capitolo: venti forward pass identici a temperature 0 tornano identici bit per bit quando il model gira da solo, e mettere lo stesso prompt in un batch accanto alle request di qualcun altro sposta il 97 % dei suoi logits.

Non coincidono tutti. Il motivo inizia con il riquadro sui floating point del Capitolo 2.


Tutti i prezzi, le soglie e i moltiplicatori in questo capitolo sono stati letti dalle pagine dei provider il 6 settembre 2026 e vengono riportati con quella data perché cambieranno. Il metodo conta più dei numeri: i bucket, la regola del prefisso e l’aritmetica dei tier sono stabili da due anni, mentre ogni cifra al loro interno si è mossa.

La lezione 2 di Stanford CS336, Resource accounting, è il trattamento accademico più vicino a questo materiale e la lettura successiva giusta: fa sul lato training la stessa aritmetica che questo capitolo fa sul lato inference. I conteggi dei token qui sono stati prodotti con js-tiktoken 1.0.21 usando gli encoding o200k_base e cl100k_base, su una conversazione di quaranta turni da 5.090 token; l’overhead di template per messaggio è l’approssimazione convenzionale quattro-più-tre ed è dichiarato ovunque sia incluso. Le cifre su cache, tier e truncation sono le regole di pricing documentate applicate a quei conteggi di token misurati, non osservazioni di response API live — nessuna call a pagamento è stata effettuata per produrre questo capitolo, che è anche il motivo onesto per cui le affermazioni sulla latenza sono qualitative e quelle sui costi no.

  1. Dao, T., Fu, D. Y., Ermon, S., Rudra, A. and Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). Perché il tetto si è spostato senza che cambiasse il costo asintotico.

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

  3. Peng, B., Quesnelle, J., Fan, H. and 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, e Token counting, ai.google.dev/gemini-api/docs/tokens, entrambi consultati il 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.» L’oggetto usage riporta total_input_tokens, total_output_tokens, total_thought_tokens, total_cached_tokens, total_tool_use_tokens e total_tokens — sei bucket, con thoughts e tool use fuori dal conteggio output. Il nome di campo precedente per la stessa quantità, ancora restituito dalla superficie generateContent, è thoughtsTokenCount, documentato in una terza pagina, ai.google.dev/gemini-api/docs/generate-content/thinking.

  5. Anthropic, Prompt caching, docs.anthropic.com/en/docs/build-with-claude/prompt-caching, consultato il 2026-09-06. Fonte della gerarchia di invalidazione toolssystemmessages e della relativa tabella; delle lunghezze minime cacheable per model; dell’identità total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens; e della durata predefinita di cinque minuti rinfrescata senza addebito a ogni hit. 2

  6. OpenAI, Prompt caching, platform.openai.com/docs/guides/prompt-caching, consultato il 2026-09-06. Fonte di: la regola dell’intero prefisso renderizzato; il prefisso minimo cacheable (1.024 input token visibili su GPT-5.6 e successivi, 2.048 sui precedenti); i moltiplicatori 1,25× per write e 0,1× per read, e l’assenza di qualsiasi addebito di write su GPT-5.5 e precedenti; la durata di 30 minuti; i limiti di quattro write per request e cinquanta breakpoint; la nota sulla machine-affinity e prompt_cache_key; gli esempi di break-even calcolati 1,35×, 2,15× e 10×; e l’affermazione che summarisation, compaction o truncation resettano il cache reuse. 2

  7. OpenAI, Pricing (platform.openai.com/docs/pricing) e la pagina model per gpt-5.6-terra, entrambe consultate il 2026-09-06. gpt-5.6-terra, tier di servizio standard, per milione di token: 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 di 1.050.000 token con un massimo di 922.000 input token. La stessa tabella elenca gpt-6-astra a $10.00/$1.00/$12.50/$50.00 e gpt-5.6-luna a $0.20/$0.02/$0.25/$1.20. Ogni costo calcolato in questo capitolo usa le tariffe standard short-context di gpt-5.6-terra.

  8. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, consultato il 2026-09-06. Gemini 2.5 Pro, per milione di token: input $1.25 per prompt fino a 200K e $2.50 oltre; output $10.00 e $15.00, in entrambi i casi etichettato «including thinking tokens»; context caching $0.125 e $0.25, più un addebito di storage di $4.50 per milione di token all’ora. Gemini 3.1 Pro Preview usa la stessa soglia 200K a $2.00/$4.00 input e $12.00/$18.00 output.

  9. Anthropic, Pricing, docs.anthropic.com/en/docs/about-claude/pricing, consultato il 2026-09-06. Per milione di token, base input / cache write 5 minuti / cache write 1 ora / 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. Moltiplicatori: 1,25× per la write da cinque minuti, 2× per la write da un’ora, 0,1× per una read. Anche fonte dell’affermazione sul long-context («Claude 4.6 and later models... include the full 1M token context window at standard pricing»), dei conteggi dei token del system prompt per tool-use (496 token su Claude Sonnet 4.5 con tool_choice di auto o none, 588 con any o un tool nominato), e della nota che Claude 4.7 e successivi usano un tokenizer più nuovo che produce «approximately 30 % more tokens for the same text». 2 3

  10. Anthropic, Token counting, docs.anthropic.com/en/docs/build-with-claude/token-counting, consultato il 2026-09-06. L’endpoint /v1/messages/count_tokens accetta gli stessi input di un message e restituisce un conteggio degli input token; la documentazione afferma che il conteggio è una stima, che può includere token aggiunti da Anthropic per ottimizzazioni di sistema, e che questi non vengono fatturati.

  11. Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. and Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Citato qui, misurato nel Capitolo 24.


Creato da

David Vicente Campos

Fondatore di NeuraLIA Labs e cofondatore di MyRealFood

Sono ingegnere informatico, laureato all’Università di León. Ho cofondato MyRealFood, dove, come CTO, ho costruito l’app che milioni di persone hanno usato per mangiare meglio, e ho fondato NeuraLIA Labs, dove sviluppo prodotti AI. Qui scrivo di ciò che ho dovuto capire strada facendo, come avrei voluto che qualcuno me lo spiegasse.

Altro sull’autore

Pubblicato da NeuraLIA Labs.

Ricevi i nuovi articoli nella tua casella

Novità AI, guide e aggiornamenti di prodotto — una breve email quando pubblichiamo qualcosa che vale il tuo tempo.

Indice del corso

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev12 min di lettura

Il modello AI Jev è pensato per le decisioni, non per la prosa

Jev di TypeSafe AI sta attirando attenzione perché tratta l’intelligenza software come un problema di probabilità: scegliere il ramo giusto, associare una confidenza ed evitare di pagare un LLM per scrivere testo quando al codice serve una decisione.

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering12 min di lettura

Context engineering for long-horizon AI agents

Long-running agents do not fail only because the window is small. They fail when files, tool outputs and stale history crowd out the task the agent was supposed to finish.

Pronto a lasciare scegliere LIA?

Crea con ogni modello AI in un unico posto — inizia gratis oggi.