Clément Farkas DauduEN

J'ai mesuré ma dépense en tokens, puis je me suis trompé de conclusion

TL;DR

Tokens, contexte et cache en deux minutes

Un tour, c'est un aller-retour avec le modèle, en pratique un appel d'API : l'agent envoie ce que le modèle doit voir, le modèle renvoie une réponse. Tout se compte en tokens, les morceaux de texte qu'un modèle lit et écrit, et se facture au token.

Ce que l'agent envoie à chaque tour, c'est le contexte : les instructions fixes avec lesquelles il démarre (le préambule), plus tout ce que la conversation a accumulé depuis, réponses, fichiers lus et résultats d'outils compris. Le contexte entier est renvoyé à chaque tour, et repayé, et il grossit au fil de la session.

flowchart LR
  C["Contexte accumulé : préambule, messages, fichiers, résultats d'outils"] -->|"renvoyé à chaque tour"| M["Modèle"]
  M -->|"tokens de sortie"| R["Réponse"]
  R -->|"ajoutée au contexte"| C

Une session, c'est une conversation avec l'agent. Démarrer une nouvelle session repart du préambule, avec un contexte plus petit qu'il faut réécrire dans le cache.

L'essentiel du contexte d'un tour est identique à celui du tour précédent, et le fournisseur le sert depuis un cache. Les tokens d'entrée sont de trois sortes :

La sortie, c'est ce que le modèle écrit en retour. Les prix sont des multiples du prix d'entrée de base. Les ratios que j'utilise, mettez les vôtres :

Type de token Prix Par rapport à une lecture de cache
Lecture de cache 0,1× l'entrée de base
Écriture de cache 1,25× l'entrée de base ~12,5×
Sortie 5× l'entrée de base ~50×

Donc la sortie est facturée ~50× le prix d'une lecture de cache, et ça compte, comme on va le voir.

Ce qu'ont montré 14 jours de mes transcripts

Base de facturation, puisque ça change ce que "coût" veut dire : je suis sur un abonnement, donc rien de tout ça ne produit de facture. Chaque chiffre de coût ici est modélisé au prix catalogue de l'API, ce qui est à mon avis le bon angle de toute façon, c'est ce que le même travail coûterait sur l'API.

Fenêtre de 14 jours, mes propres transcripts locaux (les logs que l'agent garde de chaque session), 682 sessions :

Mesure Valeur
Tokens d'entrée qui sont des lectures de cache 97,3 %
Contexte moyen repayé à chaque tour 241 517 tokens
Sessions avec un pic de contexte au-dessus de 300k 33 sessions = 86,8 % du coût
Les deux plus grosses sessions (19 538 et 9 533 tours) 60 % du total
Tokens de sortie, toute la fenêtre 37,5 M
Lectures de cache, toute la fenêtre 13,1 Md

97,3 % de l'entrée n'est pas du contenu nouveau. C'est le même contexte, renvoyé, tour après tour. (Le pic de contexte, c'est le plus gros contexte qu'une session a atteint.)

La conclusion que j'en ai tirée : terminer les sessions plus tôt

La sortie représente 0,29 % de tous les tokens. Les lectures de cache, 97,3 %. Donc la facture, c'est du contexte repayé, une poignée de sessions la dominent, et le levier est évident : terminer les sessions plus tôt, ne pas laisser le contexte s'accumuler, et tout outil qui promet de compresser la sortie court après une erreur d'arrondi. J'en ai conclu que le correctif, c'était l'hygiène de session : terminer la session quand le sujet change.

Belle histoire. En grande partie fausse.

La mesure mérite quand même d'être publiée. L'erreur aussi, parce que c'est le genre d'erreur qui passe la relecture par les pairs en ayant l'air évidemment juste.

La division qui fait tout tomber

Puis quelqu'un a fait une division que je n'avais pas faite, et la conclusion s'est écroulée.

Les deux grosses sessions contiennent la moitié des tours

Nombre total de tours qu'impliquent mes propres chiffres : 13,1 Md de lectures de cache ÷ 241 517 tokens de contexte moyen = ~54 240 tours.

Les deux sessions marathon, c'est 19 538 + 9 533 = 29 071 tours. Soit 53,6 % de tous les tours de la fenêtre.

Les deux sessions marathon Tout le reste
Tours 29 071 25 169
Lectures de cache 7,86 Md 5,24 Md
Contexte moyen déduit par tour 7,86 Md ÷ 29 071 = ~270k 5,24 Md ÷ 25 169 = ~208k

Elles représentent 60 % du coût et contiennent 54 % du travail. Ce qui veut dire qu'elles sont à peine plus chères par tour que tout le reste.

Ce que terminer une session change vraiment

Donc, la version honnête :

20-25 %, ça reste réel, et je le prendrais quand même. Mais c'est une optimisation ordinaire, pas la découverte spectaculaire que je croyais tenir. Le chiffre de 86,8 % décrit où la dépense se concentre, et je l'ai lu comme ce qu'on peut récupérer. Ce n'est pas la même quantité, et rien dans les données ne reliait les deux.

Le pic de contexte n'est pas le contexte moyen

J'ai aussi écrit que ces sessions étaient "collées juste sous le plafond de 1M", le maximum de contexte qu'une session peut contenir. Une moyenne déduite de ~270k dit le contraire. Le pic de contexte et le contexte moyen sont deux chiffres différents, et je les ai confondus.

Le correctif n'est pas gratuit non plus

Démarrer une nouvelle session réécrit le préambule et reconstruit le contexte au tarif d'écriture de cache, ~12,5× le prix d'une lecture de cache.

Les 2,7 % restants des tokens d'entrée, que j'avais balayés comme du bruit, ce sont les écritures de cache plus l'entrée hors cache. Sur 13,46 Md de tokens d'entrée, 2,7 %, c'est ~363 M de tokens à 12,5× le tarif de lecture, ce qui tombe quelque part entre un quart et un tiers du coût des lectures de cache. Pas du bruit.

Donc "terminer la session" a un seuil de rentabilité : en dessous d'un certain contexte accumulé, couper coûte plus en cache reconstruit que ça n'économise en contexte relu. Je n'ai pas calculé le mien. Il se calcule à partir de données déjà sur mon disque, et j'aurais dû le faire avant de recommander cette pratique à qui que ce soit.

La concentration n'est pas du gaspillage

Le plus gros trou, et celui que j'aimerais qu'on me signale si on relisait mon travail.

86,8 % de la dépense concentrée dans 4,8 % des sessions, ce n'est un problème que si ces sessions ne produisaient pas 86,8 % de la valeur. Elles contenaient 54 % de tous les tours. C'est là que plus de la moitié du travail s'est fait.

Je n'ai jamais séparé "concentré" et "gaspillé". Toute la prescription part du principe que c'est la même chose. C'est peut-être le cas. Les longues sessions dérivent bel et bien, traînent du contexte sans rapport et relisent des fichiers dont personne n'a besoin. Mais c'est un argument que je devrais appuyer sur des preuves de ce que ces sessions ont produit, et je l'ai appuyé sur des preuves de ce qu'elles ont coûté.

Trois leviers, chiffrés

Levier Les chiffres Verdict
Terminer les sessions plus tôt contexte par tour ~270k -> ~208k environ 20-25 % de contexte en moins par tour, moins les nouvelles écritures de cache ; seuil de rentabilité non calculé
Compresser la sortie 0,3 % des tokens, ~12 % du coût vise ~10-12 % de la facture, pas une erreur d'arrondi
Réduire le préambule statique 12 953 -> 10 075 tokens, face à un contexte moyen de 241k du bruit

La compression de la sortie vise ~10-12 % de la facture, pas une erreur d'arrondi. J'ai dit à la fois "la sortie est une erreur d'arrondi" et "la compression de la sortie vise ~10 % de la facture", à huit lignes d'écart, ce qui se lit comme une contradiction. Les deux sont vrais, dans des unités différentes : la sortie, c'est 0,3 % des tokens et ~12 % du coût, parce qu'elle est facturée ~50× le prix d'une lecture de cache. Précisez l'unité, sinon vous allez vous embrouiller, comme moi.

Les leviers intuitifs sont vraiment petits. J'ai réduit mon préambule statique de 12 953 à 10 075 tokens. Face à un contexte moyen de 241k, c'est du bruit. J'ai gardé le changement parce que des instructions plus courtes sont de meilleures instructions, pas pour l'argent.

Mesurez par vous-même

Mesurez avant d'installer quoi que ce soit. Ce conseil-là se généralise, même si ma conclusion, non. Ce qui ne se généralise pas, c'est ma distribution : 682 sessions en 14 jours, dont deux qui contiennent la moitié des tours, c'est la façon de travailler d'une seule personne, et une façon plutôt extrême. Quelqu'un qui lance beaucoup de petites invocations scriptées en CI a le profil inverse, peu de contexte par tour et beaucoup de sessions, et pour lui la compression de la sortie compte nettement plus.

La consommation rapportée par le fournisseur est déjà sur votre disque. Claude Code l'écrit dans ~/.claude/projects/**/*.jsonl.

Ce sur quoi je me suis trompé la première fois, pour vous l'éviter

Les étapes

  1. Listez les fichiers avec un glob.
  2. Filtrez les entrées sidechain.
  3. Additionnez les quatre champs par message de l'assistant.
  4. Multipliez par votre grille de prix.
  5. Regroupez par sessionId.
  6. Triez.

Vingt lignes de Python.

Trois questions à poser au résultat

Deux questions auxquelles répondre, et une à laquelle répondre ensuite :

  1. Les lectures de cache dominent-elles votre entrée ? Si oui, votre facture, c'est du contexte repayé.
  2. Une poignée de sessions domine-t-elle ces lectures ? Si oui, regardez de plus près.
  3. Ces sessions contiennent-elles aussi une part proportionnelle de vos tours ? Si oui, vous avez trouvé où est le travail, pas où est le gaspillage. C'est la question que j'ai sautée.

Avant d'installer un outil "économiseur de tokens"

Mêmes règles que pour n'importe quelle dépendance, on les saute juste plus souvent parce que l'argument de vente, c'est de vous faire économiser de l'argent.

J'ai cité auparavant un chiffre de "60,8 % économisés" venant d'un proxy CLI que j'utilise. C'est l'outil qui corrige sa propre copie, et mes propres notes indiquent que ce même proxy casse certains flags de commande et renvoie des résultats faux. Le citer avec approbation dans un article sur la vérification des affirmations, c'était exactement l'incohérence qu'un lecteur hostile devrait repérer.

Si vous voulez formuler une critique précise d'un outil précis, nommez-le et mettez un lien vers les lignes qui étayent l'affirmation. Décrire un projet identifiable sans le nommer, c'est perdant sur les deux tableaux : évident pour quiconque s'y intéresse, impossible à réfuter pour tous les autres, et le mainteneur ne peut pas répondre.

Ce que j'en retiens

Mise à jour, novembre 2026

Deux mesures qui changent cet article. J'avais la première avant de publier, et je l'ai laissée de côté.

Les plus gros contextes sont aussi plus lents. En août, j'ai mesuré la latence sur une autre fenêtre, environ 20k tours de l'assistant regroupés par taille de contexte. L'attente médiane par tour augmente avec le contexte :

Taille du contexte Attente médiane par tour
0-100k tokens 4,9 s
100-200k 14,0 s
300-400k 19,8 s
800-900k 30,1 s

Relire un contexte en cache, c'est bon marché, pas instantané. "Le correctif n'est pas gratuit non plus" chiffrait le découpage uniquement en tarifs de cache, et n'a jamais pris en compte le temps d'attente qui va avec un plus gros contexte. Ce que vaut le passage de ~270k à ~208k, je ne peux pas le dire : les deux tombent dans la tranche 200-300k, que cette mesure ne donne pas. Le contexte médian de cette fenêtre était de 380k, donc aucune de ces médianes ne s'applique aux chiffres de coût plus haut.

Le modèle est un levier que j'avais laissé de côté. J'ai écrit "Les leviers intuitifs sont vraiment petits", à propos de la réduction de mon préambule. Ça tient toujours. Ce que je n'avais pas envisagé, c'est que le niveau de modèle est un levier d'une autre taille. En septembre, le même diff a été relu en CI par Sonnet 4.6, puis par Opus 5 :

Modèle relecteur Coût Tours
Sonnet 4.6 0,27 $ 10
Opus 5 1,31 $ 24

Soit 4,8×. Sur ce dépôt, une revue Opus typique (médiane) coûtait environ 2,2× une revue Sonnet 4.6 typique ; mes notes n'indiquent pas sur combien de revues ça porte. C'est par exécution de CI, une charge de travail différente des sessions interactives plus haut, donc je ne peux pas classer ce levier face aux 20-25 %, qui étaient une baisse du contexte par tour, pas de la facture totale.

Les réserves ne sont pas minces :