Aller au contenu
16/30Chapitre 16 sur 30

Context window, tokens et facture : les chiffres

Une conversation de 40 tours coûte 22 fois sa longueur en input tokens. Le cache réduit cela de 68 % ; un timestamp mal placé ajoute 20 %.

Dans cet article

Voici une conversation de support en quarante tours, facturée tour par tour. Rien d’inhabituel : un développeur pose une question sur une API, un assistant répond en un ou deux paragraphes. L’échange complet représente 5 090 tokens de texte — environ huit pages.

tourprompt tokensnouveau texteoutputcoût de ce tourtotal cumulé
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

Lisez ensemble les deuxième et troisième colonnes. Au tour 40, l’utilisateur a tapé dix-sept tokens et a été facturé pour 4 947. La question n’était pas plus difficile que la première ; elle était plus courte. Ce qui a changé, c’est que la requête transportait toute la conversation avec elle, encore une fois, pour la quarantième fois.

Total des input tokens facturés sur ces quarante appels : 112 617. La conversation fait 5 090 tokens. Vous l’avez payée vingt-deux fois.

Ce chapitre explique pourquoi cela arrive, comment cela s’appelle sur la facture de chaque fournisseur, et sur lesquelles des cinq choses qui vous sont facturées vous pouvez agir.

Afficher les détails

Ce dont ce chapitre a besoin de la partie II.

  • Chapitre 7 a construit le tokenizer. Un token est aussi l’unité ici — la même unité, maintenant tarifée.
  • Chapitre 9 a dérivé self-attention et son coût O(n2)O(n^2), dans l’encadré sur la notation asymptotique. Ce coût explique pourquoi une limite existe tout court ; il est lié ici plutôt que réexpliqué.
  • Chapitre 13 a mesuré prefill par rapport à decode et calculé ce qu’occupe un KV cache. Ces deux phases sont ce qu’achètent réellement les colonnes input et output ci-dessus.

Tout le reste est du TypeScript, parce qu’il s’agit de comptabilité pour un appel distant et non de mathématiques sur un modèle.

Le malentendu le plus coûteux de ce secteur est de croire qu’un modèle se souvient d’une conversation.

Ce n’est pas le cas, et le mécanisme du chapitre 13 explique exactement pourquoi. L’état d’un transformer pendant la génération est le KV cache : les clés et valeurs calculées pour chaque token de la séquence. Ce cache vit pendant la durée d’une requête. Quand la requête se termine, le processus qui le détenait est libre de servir quelqu’un d’autre, et le cache disparaît. Il n’y a ni stockage par utilisateur de l’autre côté, ni session.

La requête suivante doit donc arriver avec tout ce que le modèle est censé savoir, et le modèle reconstruit cet état en exécutant une passe avant sur tout le prompt avant d’émettre un seul nouveau token. Le chapitre 15 appelait le prompt « l’état complet ». Voici la raison physique : le prompt est l’état complet parce que rien d’autre ne survit à l’appel.

Le context window est la longueur maximale de ce prompt plus sa réponse. C’est un plafond sur la quantité d’état que vous pouvez reconstruire, pas un conteneur qui conserve quoi que ce soit entre les requêtes. L’appeler « la mémoire du modèle » inverse la causalité — vous ne remplissez pas une mémoire, vous payez pour en rétablir une.

C’est de là que vient le vingt-deux. Le tour nn transporte les n1n-1 tours précédents, donc le total d’input sur une conversation de nn tours est la somme d’une série croissante, ce qui est quadratique :

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

ss est le system prompt et hih_i l’historique au tour ii. Ajuster l’input cumulé mesuré à an2+bnan^2 + bn sur les quarante tours donne 60.22n2+432.25n60.22\,n^2 + 432.25\,n, ce qui prédit 113 645 tokens au tour 40 contre 112 617 mesurés. Le terme quadratique domine, et le terme linéaire est ce que l’utilisateur a réellement tapé.

La conséquence à retenir de ce chapitre tient en une phrase : votre facture croît avec le carré de la conversation, pas avec la dernière question. Les mêmes quarante questions posées sans aucun historique coûtent $0.066036. Conserver l’historique coûte $0.274386. L’historique a multiplié la facture par 4,2, et il continuera à la multiplier, parce que le multiplicateur est la longueur de la conversation.

La fenêtre est finie pour deux raisons qui vont dans le même sens. La première est celle du chapitre 9 : attention compare chaque token à chaque autre token, donc le travail de cette couche croît avec le carré de la longueur de la séquence. La seconde est la mémoire : le KV cache croît linéairement avec la longueur de séquence, et le chapitre 13 a fait ce calcul — sur les longues séquences, il est plus grand que les poids.

Ces deux limites ont été attaquées, et aucune n’a été supprimée. FlashAttention1 réorganise le calcul pour lire et écrire beaucoup moins dans la mémoire à haute bande passante, ce qui rend les longues séquences praticables sans changer le coût asymptotique. Position Interpolation2 et YaRN3 étendent le context window utilisable d’un modèle entraîné en rééchelonnant les encodages positionnels du chapitre 9 plutôt qu’en réentraînant. Ensemble, ils expliquent pourquoi les fenêtres sont passées de 2K à 1M en cinq ans.

Ce qu’ils n’ont pas fait, c’est rendre les longs contextes gratuits. Ils ont relevé le plafond et adouci la pente. La pente est toujours là, et c’est elle que mesurent les paliers tarifaires plus loin dans ce chapitre.

Presque tous les calculateurs de coût sur Internet modélisent un appel API comme des input tokens multipliés par un prix d’input plus des output tokens multipliés par un prix d’output. C’était vrai en 2023. C’est désormais faux, d’une manière qui produit des factures erronées d’un facteur deux ou plus dans les deux sens.

Il existe cinq catégories de tokens facturables :

compartimentce que c’estprix typique, relatif à l’input
input non mis en cacheprompt tokens que le modèle a dû traiter à neuf
lecture de cacheprompt tokens servis depuis un préfixe stocké0,1×
écriture de cacheprompt tokens stockés dans le cache lors de cet appel1,25× à 2×
outputtokens générés par le modèle et envoyés à vous5× à 6×
reasoningtokens générés par le modèle et non envoyés à voustarif output

Trois de ces cinq catégories n’existaient pas comme lignes séparées il y a deux ans, et les deux lignes de cache sont celles que les gens comprennent mal, parce qu’une écriture de cache coûte plus qu’un input ordinaire, pas moins. Vous payez une prime pour stocker quelque chose afin de payer un tarif réduit quand vous le relisez, et l’intérêt de l’échange dépend entièrement du nombre de relectures.

Le compartiment reasoning est celui du chapitre 12, maintenant avec un prix, et il porte un détail qui mérite d’être dit clairement : la documentation de Google indique que la tarification « is based on the full thought tokens the model needs to generate, despite only the summary being output from the API ».4 Vous êtes facturé pour des tokens qui ne vous sont jamais transmis. C’est le seul compartiment dont vous ne pouvez ni compter, ni inspecter, ni vérifier le contenu.

Voici maintenant la partie qui en fait un problème de normalisation plutôt qu’un problème de multiplication. Chaque fournisseur déclare ces compartiments sous des noms différents, et — c’est le piège — deux d’entre eux utilisent le même mot pour deux quantités différentes.

Prenez un appel : 4 837 tokens lus depuis le cache, 110 nouveaux, 142 output tokens visibles, 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 } }

Regardez prompt_tokens: 4947 et input_tokens: 110. Les deux champs sont le nombre d’input tokens pour le même prompt. Celui d’OpenAI inclut les tokens en cache ; celui d’Anthropic les exclut — sa documentation énonce explicitement l’identité, total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens.5 input_tokens chez Anthropic signifie « les tokens après votre dernier point d’arrêt de cache ».

Et regardez l’output. OpenAI et Anthropic déclarent tous deux 442, qui contient déjà les 300 reasoning tokens. Gemini déclare 142 et place les 300 dans un champ séparé. Le chapitre 12 signalait cette incompatibilité entre deux façons de compter le même travail ; voici ce qu’elle coûte.

Un normaliseur tient en trente lignes, et il n’est pas optionnel :

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

Passez les trois payloads ci-dessus dans les trois lecteurs et tous trois produisent le même Usage, et donc le même nombre : $0.006491. Cet accord est toute la raison d’écrire cette couche.

Si vous vous trompez, voici ce que cela coûte, sur le même appel :

erreurfacturéécart
traiter cached_tokens comme additionnel à prompt_tokens$0.0161652,49× — vous facturez le prompt deux fois
traiter les lectures de cache comme gratuites au lieu de 0,1×$0.0055240,85× — vous absorbez 15 %
lire candidatesTokenCount et ignorer thoughtsTokenCount$0.00289155 % de l’appel disparaît

La troisième erreur est la dangereuse, parce qu’elle échoue silencieusement dans le sens des bonnes nouvelles. Votre tableau de bord montre qu’un modèle de reasoning coûte moins de la moitié de son coût réel, et rien nulle part ne déclenche d’erreur.

Une fois les compartiments normalisés, la fonction de coût est courte. La seule partie non évidente est la recherche du palier, que la section suivante explique :

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

Deux décisions de conception méritent d’être défendues. Les valeurs de repli — les prix de cache retombant sur l’input, le reasoning sur l’output — encodent ce que signifie une table manquante : les reasoning tokens sur Gemini sont facturés au tarif output, donc un prix reasoning absent n’est pas zéro, c’est le prix output. Et contextSize additionne les trois compartiments d’input plutôt que seulement les nouveaux, parce que le palier est choisi selon la longueur du prompt, pas selon la part facturée au plein tarif.

Un cache de prompt stocke l’état calculé du modèle pour un préfixe de votre prompt, afin qu’une requête ultérieure avec le même préfixe évite de le recalculer. Quatre propriétés découlent du mot « préfixe », et les quatre surprennent.

Le cache fait correspondre depuis le début du prompt rendu vers l’avant, et s’arrête au premier octet différent. Il n’y a pas de crédit partiel pour du contenu qui apparaît plus tard dans un autre ordre. OpenAI le dit sans détour : « cache reuse requires the entire rendered prefix to match ».6

En dessous, rien n’est mis en cache et aucune erreur n’est renvoyée. Chez OpenAI, le minimum est de 1 024 tokens pour GPT-5.6 et ultérieurs, et de 2 048 pour les modèles plus anciens. Chez Anthropic, il va de 512 à 4 096 selon le modèle — 1 024 pour Claude Sonnet 4.5, 4 096 pour Claude Haiku 4.5. Si les deux champs de cache reviennent à zéro, c’est généralement la raison.

Écrire coûte plus que lire, et plus que ne pas mettre en cache

Lien vers la section : Écrire coûte plus que lire, et plus que ne pas mettre en cache

Chez OpenAI et Anthropic, une écriture de cache coûte 1,25× le tarif d’input non mis en cache pour le cache de courte durée, et le cache d’une heure d’Anthropic coûte 2×. Une lecture coûte 0,1×. Google ne facture rien pour écrire, mais loue le stockage : $4.50 par million de tokens par heure sur Gemini 2.5 Pro.

L’entrée par défaut d’Anthropic vit cinq minutes, rafraîchie gratuitement à chaque hit. Celle d’OpenAI dure au moins trente minutes après la dernière écriture ou réutilisation. Et OpenAI note que les états mis en cache vivent sur des machines individuelles : une requête ne touche donc le cache que si elle est routée vers la machine qui détient l’entrée — ce que prompt_cache_key influence, sans garantir.

Le seuil de rentabilité est assez petit pour rester en tête, et la documentation d’OpenAI fait le calcul : écrire un préfixe une fois et le réutiliser une fois coûte 1,35× son coût d’input ordinaire, contre 2× pour le traiter deux fois sans cache ; sur dix requêtes, une écriture et neuf lectures coûtent 2,15× contre 10×. Une seule réutilisation paie l’écriture. Anthropic arrive au même point : une lecture pour le cache de cinq minutes, deux pour le cache d’une heure.

Reprenons maintenant la conversation de quarante tours, avec le cache activé et un préfixe stable :

input non mis en cachelectures de cacheécritures de cachetotal
sans cache112,617$0.274386
avec cache2,887104,7834,947$0.088250

Soixante-huit pour cent moins cher, et trois nombres dans ce tableau méritent votre attention.

Le cache ne s’active qu’au tour 6. Le prompt n’atteint pas 1 024 tokens avant ce moment, donc les cinq premiers tours sont facturés exactement comme avant — et le sixième est facturé plus cher, avec la prime d’écriture de 1,25×, parce que c’est le tour qui remplit le cache. La première lecture arrive au tour 7. Les 2 887 tokens non mis en cache du tableau sont l’arithmétique : cinq tours, pas six. Le cache est une remise sur les longs prompts, et une courte conversation n’en tire rien.

La prime d’écriture est de $0.002474, soit 2,8 % de la facture avec cache. Chaque tour écrit sa nouvelle queue, quarante fois, et toute la prime d’écriture est une erreur d’arrondi par rapport à ce que les lectures ont économisé. Comprendre précisément le coût d’écriture sert surtout à arrêter de s’en inquiéter.

Seuls 2 887 tokens ont été facturés au plein tarif d’input sur 112 617. Voilà la forme d’un cache qui fonctionne : presque tout est une lecture.

Voici l’échec qui coûte vraiment de l’argent, et c’est un bug d’une ligne.

Placez quelque chose qui change à chaque appel au début du prompt — un timestamp, un identifiant de requête, le nom de l’utilisateur, une ligne « aujourd’hui nous sommes le », un document fraîchement récupéré — et le préfixe diffère dès le premier octet. Rien ne correspond. Chaque appel est un miss. Et comme chaque appel présente un préfixe nouveau, chaque appel écrit aussi.

Même conversation, mêmes quarante tours, cache activé, avec un timestamp par appel en haut du system prompt :

totalpar rapport à
pas de cache du tout$0.274386
cache, préfixe stable$0.088250−67,8 %
cache, préfixe volatile$0.329251+20,0 %

Activer le prompt caching a rendu la conversation vingt pour cent plus chère que de ne pas l’activer. Vous avez payé la prime d’écriture de 1,25× sur 109 730 tokens et relu zéro token. Il n’y a ni erreur, ni avertissement, et la fonctionnalité est activée.

La règle — et c’est tout le prompt caching en une ligne — est donc : contenu stable devant, contenu variable derrière. Instructions système, définitions d’outils et matériel de référence d’abord ; timestamps, identité utilisateur et question actuelle en dernier. Anthropic rend la hiérarchie explicite — le cache suit toolssystemmessages, et une modification à n’importe quel niveau invalide ce niveau et tout ce qui suit ; modifier une seule description d’outil invalide donc tout le cache.5

Deux conséquences font trébucher les équipes. Changer les outils activés change les définitions d’outils, donc un feature flag qui ajoute un outil pour certains utilisateurs scinde votre cache en deux. Et chez Anthropic, activer ou désactiver la recherche web ou les citations modifie le system prompt, ce qui invalide les caches système et messages sans que vous touchiez une ligne de votre propre texte.

La réponse évidente à une facture quadratique est d’arrêter d’envoyer tout l’historique : garder les douze derniers messages et supprimer le reste. Cela réduit bien la facture, et c’est généralement la mauvaise décision ; la mesure explique pourquoi.

stratégietotalpar rapport à historique complet + cache
historique complet, sans cache$0.274386+211 %
historique complet, avec cache$0.088250
12 derniers messages, sans cache$0.118712+35 %
12 derniers messages, cache activé$0.122546+39 %

Tronquer à une fenêtre de douze messages est 57 % moins cher qu’envoyer tout sans cache — la comparaison que tout le monde fait, et la raison pour laquelle la technique est populaire. Mais c’est 39 % plus cher qu’envoyer tout avec un cache qui fonctionne, et activer le cache en plus de la troncature rend la situation légèrement pire plutôt que meilleure.

Le mécanisme est encore le préfixe. Une fenêtre glissante supprime le plus ancien message à chaque tour, donc le prompt ne commence plus là où il commençait la fois précédente et chaque tour présente un nouveau préfixe. Les recommandations d’OpenAI disent exactement cela : « summarisation, compaction, or context truncation can change the prefix and reset cache reuse ».6 Au tour 40, le prompt fenêtré fait 813 tokens, sous le minimum de 1 024 tokens, donc il ne peut pas être mis en cache du tout.

Et l’argent est la moitié la moins chère du coût. Ce que vous avez supprimé, c’est l’instruction donnée par l’utilisateur au tour 2 dont le modèle avait besoin au tour 40. La troncature échange une facture visible contre un échec invisible, et le faire correctement — compaction, notes structurées conservées hors de la fenêtre, récupération de l’historique à la demande — est le sujet du chapitre 24.

Les longs contextes ne sont pas seulement plus chers parce qu’ils sont plus longs. Au-delà d’un seuil, ils sont plus chers par token, et le seuil s’applique rétroactivement à tout le prompt.

La page modèle d’OpenAI pour gpt-5.6-terra l’énonce en une phrase : « Prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request. »7 Pas pour l’excédent. Pour l’ensemble.

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, cinquante-cinq cents. Si votre service construit des prompts à partir de documents récupérés dont vous ne contrôlez pas la taille, votre modèle de coût contient une falaise à une frontière que personne dans votre équipe n’a écrite.

La tarification de Google fonctionne de la même façon avec un seuil de 200 000 tokens : Gemini 2.5 Pro coûte $1.25 par million d’input tokens pour les prompts jusqu’à 200K et $2.50 au-delà, l’output passant de $10.00 à $15.00.8 Anthropic a pris la direction inverse — au 6 septembre 2026, sa documentation indique que Claude 4.6 et ultérieurs incluent tout le context window d’un million de tokens au tarif standard, si bien qu’« a 900k-token request is billed at the same per-token rate as a 9k-token request ».9 Les modèles antérieurs conservaient la surcharge.

C’est pourquoi un prix n’est pas un nombre. Un prix est une table de paliers indexée par longueur de prompt, ce à quoi sert Tier[] dans la fonction de coût, et c’est pourquoi computeCost sélectionne le palier avec tout le prompt plutôt qu’avec chaque compartiment séparément.

Prefill, decode, et pourquoi l’output coûte six fois l’input

Lien vers la section : Prefill, decode, et pourquoi l’output coûte six fois l’input

Les cinq compartiments correspondent aux deux phases du chapitre 13, et une fois cette correspondance visible, les ratios de prix cessent de paraître arbitraires.

Les input tokens sont prefill. Tout le prompt passe dans le modèle en une seule passe, traité en parallèle — grandes multiplications matricielles, limitées par le calcul. Le coût par token est faible, et c’est la phase qui fixe le temps jusqu’au premier token : un prompt de 4 947 tokens a 4 947 tokens de prefill à faire avant que le premier mot apparaisse.

Les output tokens sont decode. Ils sont produits un par un, chacun par une passe avant complète qui lit tout le KV cache, le GPU attendant surtout la mémoire plutôt que de calculer. C’est la phase qui fixe les tokens par seconde, elle ne peut pas être parallélisée au sein d’une réponse, et c’est pourquoi l’output coûte environ six fois l’input sur le modèle tarifé ici : $12.00 contre $2.00 par million de tokens.

Trois conséquences suivent directement. Une lecture de cache remplace du travail de prefill, donc elle achète à la fois de la latence et de l’argent — la même remise apparaît comme une facture plus basse et une attente plus courte avant le premier token. Les reasoning tokens sont du decode que vous ne voyez jamais, ce qui explique pourquoi un modèle de reasoning ne stream rien pendant plusieurs secondes puis répond vite : le chapitre 12 avertissait de la conséquence d’interface, voici la conséquence sur la facture. Et interrompre un stream n’arrête pas la génération — le chapitre 14 a construit l’annulation et laissé le prix à ce chapitre, et le prix est le nombre total d’output tokens, parce que les tokens sont produits et facturés, que quelqu’un écoute ou non. Il en va de même pour la réponse que personne ne garde : régénérer cinq fois une réponse au tour 40 coûte $0.057990 pour celle qui reste à l’écran.

Le tokenizer du chapitre 7 était en Python et y est resté. Le budget se fait dans le serveur qui construit la requête, donc il doit se faire ici, et il existe exactement trois niveaux de précision.

Niveau un : compter localement. js-tiktoken embarque les mêmes tables de fusion BPE que le tiktoken Python, donc un décompte identique octet pour octet pour les encodages OpenAI, sans appel réseau :

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

Les deux constantes comptent, et c’est là que les comptages locaux dérivent. Votre texte n’est pas ce qui est tokenisé — le template de chat du chapitre 11 enveloppe d’abord chaque message dans des marqueurs de rôle, et ce sont des tokens que vous payez. Quatre par message et trois pour l’amorce de réponse est l’approximation conventionnelle pour les modèles de chat OpenAI ; sur les quatre-vingt-un messages de la conversation ci-dessus, ils totalisent 324 tokens, soit 6,4 % de sa longueur. Les décomptes ici ont été vérifiés avec le tiktoken Python du chapitre 7 sur les quatre-vingt-un textes et sont identiques.

Niveau deux : demander au fournisseur. Anthropic expose /v1/messages/count_tokens et Google expose count_tokens, acceptant tous deux la même forme de requête qu’un vrai appel et renvoyant gratuitement un nombre d’input tokens. Utilisez-les quand vous ne pouvez pas compter localement — et vous ne pouvez pas compter localement pour Anthropic, dont le tokenizer n’est pas publié. La documentation d’Anthropic est prudente sur ce qu’elle vous donne : le comptage « is an estimate », et il « may include tokens added automatically by Anthropic for system optimizations », pour lesquels « you are not billed ».10

Niveau trois : lire usage dans la réponse. C’est la vérité, et elle arrive après que l’argent est dépensé. C’est précisément pourquoi les deux premiers niveaux existent — pour décider s’il faut envoyer la requête, pas pour la facturer.

Ce que vous payez sans que personne ne vous le montre

Lien vers la section : Ce que vous payez sans que personne ne vous le montre

Quatre postes qui n’apparaissent pas comme postes.

Le system prompt, payé à chaque appel. Celui ci-dessus fait 192 tokens avec son surcoût de template. Sur quarante appels, cela représente 7 680 tokens — 5,6 % de la facture totale de cette conversation, pour huit lignes écrites une fois. C’est aussi le meilleur candidat possible au cache, étant à la fois stable et premier.

Les définitions d’outils. Le nom, la description et le schéma JSON de chaque outil partent à chaque requête, et les fournisseurs ajoutent de l’échafaudage par-dessus. Anthropic publie le nombre : activer les outils ajoute à lui seul un system prompt caché de 496 tokens sur Claude Sonnet 4.5 avec tool_choice défini sur auto, ou 588 avec any ou un outil nommé.9 Cela vient avant vos propres schémas. Le chapitre 18 construit le catalogue ; le chapitre 24 mesure ce qu’il consomme.

Chaque génération, y compris celles que vous jetez. Cinq régénérations coûtent cinq fois. Le chat en montre une.

Les pensées qui ne vous sont pas montrées. La facturation repose sur l’ensemble des thought tokens bien que seul un résumé soit renvoyé, et aucune de vos comptabilités ne peut auditer ce nombre.

Un dernier avertissement, parce que c’est la pensée suivante naturelle et que la réponse n’est pas l’évidence.

Une fenêtre d’un million de tokens ne signifie pas un million de tokens utilisables. La précision de retrieval se dégrade avec la position : Liu et al. ont constaté que les modèles localisent l’information de manière fiable au début et à la fin d’un long input, et beaucoup moins au milieu.11 Une fenêtre plus grande achète la possibilité d’envoyer plus, pas la certitude d’être lu.

Ce phénomène est mesuré une fois dans ce cours — le taux de retrieval à neuf positions dans le même prompt de 853 tokens — et il appartient au chapitre 24, où il change ce qu’un agent fait. Il est cité ici parce qu’il change ce que vous devriez acheter : le token le moins cher est celui que vous n’avez pas envoyé.

Vous pouvez maintenant prédire ce que coûtera un appel avant de le faire, lire ce qu’il a réellement coûté ensuite, et distinguer les deux. Cela couvre tout ce qui concerne la requête, sauf la partie que vous n’avez pas touchée : les réglages.

Le chapitre 17 traite du sampling — temperature, top-p, top-k, les pénalités, et le déterminisme que vous n’avez pas. Il commence par démonter l’erreur la plus répandue du domaine : croire que temperature est un bouton de créativité. Ce n’est pas le cas : temperature divise les logits du chapitre 4 avant le softmax, et l’augmenter ne rend pas le modèle imaginatif, il augmente la probabilité de tokens que le modèle lui-même a notés comme moins bons. Ensuite viennent pourquoi le décodage greedy produit un texte mesurablement pire que le sampling, pourquoi top-k et top-p échouent sur des formes opposées de distribution, et l’expérience qui clôt le chapitre : vingt passes avant identiques à temperature 0 reviennent identiques bit pour bit quand le modèle tourne seul, et placer le même prompt dans un batch à côté des requêtes de quelqu’un d’autre déplace 97 % de ses logits.

Ils ne correspondent pas tous. La raison commence avec l’encadré sur les nombres à virgule flottante du chapitre 2.


Tous les prix, seuils et multiplicateurs de ce chapitre ont été lus sur les pages des fournisseurs eux-mêmes le 6 septembre 2026 et sont indiqués avec cette date parce qu’ils changeront. La méthode compte plus que les nombres : les compartiments, la règle du préfixe et l’arithmétique des paliers sont stables depuis deux ans, tandis que chaque chiffre qu’ils contiennent a bougé.

La leçon 2 de Stanford CS336, Resource accounting, est le traitement académique le plus proche de ce sujet et la bonne lecture suivante : elle fait la même arithmétique côté entraînement que ce chapitre côté inférence. Les nombres de tokens ici ont été produits avec js-tiktoken 1.0.21 en utilisant les encodages o200k_base et cl100k_base, sur une conversation de quarante tours de 5 090 tokens ; le surcoût de template par message est l’approximation conventionnelle quatre-plus-trois et est indiqué chaque fois qu’il est inclus. Les chiffres de cache, de palier et de troncature sont les règles de tarification documentées appliquées à ces décomptes de tokens mesurés, et non des observations de réponses API en direct — aucun appel payant n’a été effectué pour produire ce chapitre, ce qui est aussi la raison honnête pour laquelle les affirmations de latence sont qualitatives et les affirmations de coût ne le sont pas.

  1. Dao, T., Fu, D. Y., Ermon, S., Rudra, A. et Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). Pourquoi le plafond a bougé sans que le coût asymptotique change.

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

  3. Peng, B., Quesnelle, J., Fan, H. et 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, et Token counting, ai.google.dev/gemini-api/docs/tokens, tous deux consultés le 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’objet d’usage déclare total_input_tokens, total_output_tokens, total_thought_tokens, total_cached_tokens, total_tool_use_tokens et total_tokens — six compartiments, avec les pensées et l’utilisation d’outils hors du nombre d’output. Le nom de champ antérieur pour la même quantité, encore renvoyé par la surface generateContent, est thoughtsTokenCount, documenté sur une troisième page, ai.google.dev/gemini-api/docs/generate-content/thinking.

  5. Anthropic, Prompt caching, docs.anthropic.com/en/docs/build-with-claude/prompt-caching, consulté le 2026-09-06. Source de la hiérarchie d’invalidation toolssystemmessages et de sa table ; des longueurs minimales de cache par modèle ; de l’identité total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens ; et de la durée de vie par défaut de cinq minutes rafraîchie sans frais à chaque hit. 2

  6. OpenAI, Prompt caching, platform.openai.com/docs/guides/prompt-caching, consulté le 2026-09-06. Source de : la règle du préfixe entièrement rendu ; le préfixe minimal pouvant être mis en cache (1 024 input tokens visibles sur GPT-5.6 et ultérieurs, 2 048 auparavant) ; les multiplicateurs 1,25× en écriture et 0,1× en lecture, et l’absence de tout coût d’écriture sur GPT-5.5 et antérieurs ; la durée de vie de 30 minutes ; les limites de quatre écritures par requête et de cinquante breakpoints ; la note d’affinité machine et prompt_cache_key ; les exemples de seuil de rentabilité à 1,35×, 2,15× et 10× ; et l’énoncé selon lequel summarisation, compaction ou troncature réinitialisent la réutilisation du cache. 2

  7. OpenAI, Pricing (platform.openai.com/docs/pricing) et la page modèle pour gpt-5.6-terra, toutes deux consultées le 2026-09-06. gpt-5.6-terra, palier de service standard, par million de tokens : input $2.00, input en cache $0.20, écritures de cache $2.50, output $12.00 ; input long contexte $4.00, cache $0.40, écritures $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 de 1 050 000 tokens avec un maximum de 922 000 input tokens. La même table liste gpt-6-astra à $10.00/$1.00/$12.50/$50.00 et gpt-5.6-luna à $0.20/$0.02/$0.25/$1.20. Tous les coûts calculés de ce chapitre utilisent les tarifs standard court contexte de gpt-5.6-terra.

  8. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, consulté le 2026-09-06. Gemini 2.5 Pro, par million de tokens : input $1.25 pour les prompts jusqu’à 200K et $2.50 au-delà ; output $10.00 et $15.00, dans les deux cas libellé « including thinking tokens » ; context caching $0.125 et $0.25, plus un coût de stockage de $4.50 par million de tokens par heure. Gemini 3.1 Pro Preview utilise le même seuil de 200K à $2.00/$4.00 en input et $12.00/$18.00 en output.

  9. Anthropic, Pricing, docs.anthropic.com/en/docs/about-claude/pricing, consulté le 2026-09-06. Par million de tokens, input de base / écriture cache 5 minutes / écriture cache 1 heure / lecture cache / 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. Multiplicateurs : 1,25× pour l’écriture de cinq minutes, 2× pour l’écriture d’une heure, 0,1× pour une lecture. Également source de l’énoncé sur le long contexte (« Claude 4.6 and later models... include the full 1M token context window at standard pricing »), des nombres de tokens du system prompt d’utilisation d’outils (496 tokens sur Claude Sonnet 4.5 avec tool_choice de auto ou none, 588 avec any ou un outil nommé), et de la note selon laquelle Claude 4.7 et ultérieurs utilisent un tokenizer plus récent produisant « approximately 30 % more tokens for the same text ». 2 3

  10. Anthropic, Token counting, docs.anthropic.com/en/docs/build-with-claude/token-counting, consulté le 2026-09-06. L’endpoint /v1/messages/count_tokens prend les mêmes inputs qu’un message et renvoie un nombre d’input tokens ; la documentation indique que le nombre est une estimation, qu’il peut inclure des tokens ajoutés par Anthropic pour des optimisations système, et que ceux-ci ne sont pas facturés.

  11. Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. et Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Cité ici, mesuré au chapitre 24.

Prêt à laisser LIA choisir à votre place ?

Créez avec tous les modèles d'IA au même endroit — commencez gratuitement dès aujourd'hui.