INGÉNIERIE — COÛT DES SYSTÈMES IA

3,5 millions de tokens par jour : autopsie d'une facture LLM

Une journée de production, relevée. Où part l'argent dans un pipeline multi-agents, pourquoi la moitié de la dépense n'achetait aucune qualité, et les trois règles qui ont ramené un produit équivalent de 1,4 million à 827 000 tokens.

Post-mortem chiffré
14 min
Coût / qualité

La facture d'une journée

Une chaîne de production éditoriale automatisée tourne chez nous tous les soirs. Elle collecte des données de marché, écrit, relit, valide, publie. Elle est bâtie comme une équipe : des agents spécialisés, un orchestrateur, des scripts déterministes autour. Le 13 août, sur 24 heures, elle a consommé environ 3,5 millions de tokens rien qu'en sous-agents.

Ce chiffre n'a rien d'un accident ponctuel. Il est le résultat mécanique d'une série de choix d'architecture qui semblaient tous raisonnables pris isolément : mettre le meilleur modèle partout puisqu'on veut la meilleure qualité, faire relire par plusieurs agents puisque la relecture croisée attrape des erreurs, passer les données dans le prompt puisque c'est le plus simple. Empilés, ces trois choix ont produit une facture dont 60 à 70 % était évitable sans perdre un gramme de qualité.

3,5 M
Tokens de sous-agents consommés sur 24 heures, tous produits confondus
4,3 M
Tokens pour une seule production, lors d'un incident antérieur d'orchestration
827 k
Tokens pour le même produit après les correctifs, contre 1,4 M la veille
3 causes
Modèle uniforme, relecture redondante, données dans le contexte

Pour ceux qui découvrent

Un token est l'unité de facturation d'un modèle de langage : environ quatre caractères de texte. Tout ce qui entre dans la fenêtre du modèle est payé (les instructions, les données, l'historique de la conversation), et tout ce qui en sort l'est aussi, plus cher. Un système d'agents qui se relisent les uns les autres repaie donc le même texte à chaque étape. C'est cette répétition, invisible dans le code, qui fabrique les grosses factures.

Trois postes, un même réflexe

En décomposant la journée poste par poste, les trois causes se ressemblent : à chaque fois, on a payé un raisonnement là où une opération suffisait.

1 · Le modèle le plus cher partout, y compris pour du travail mécanique

Le pipeline utilisait le modèle haut de gamme, en mode raisonnement approfondi, sur toutes les étapes. Y compris celles qui consistent à lire un fichier JSON et vérifier qu'un champ existe. Une étape d'extraction n'a pas besoin de jugement : elle a besoin d'être fiable et rapide. Elle produit exactement le même résultat avec un modèle intermédiaire et un budget de réflexion moyen, pour une fraction du prix.

La bonne question n'est pas « quel est le meilleur modèle ? » mais « cette étape demande-t-elle un arbitrage, ou l'application d'une règle ? ». Un rédacteur arbitre. Un arbitre arbitre. Un parseur applique.

2 · Des relecteurs qui refont ce qu'un script vérifie gratuitement

Notre panel de relecture faisait vérifier par des agents le calcul du rapport risque/récompense, le respect des seuils de niveaux, la présence des balises structurelles, les tournures de style à bannir. Or ces quatre contrôles étaient déjà implémentés en scripts déterministes, exécutés dans le même pipeline, coût en tokens nul, résultat reproductible au bit près.

Un agent qui recalcule un ratio que trois lignes de code calculent mieux n'ajoute pas une seconde opinion : il ajoute une source de bruit payante. Pire, il peut se tromper là où le script ne le peut pas.

3 · Des données volumineuses transportées dans le contexte

Les appels de données revenaient directement dans la fenêtre de l'agent. Une salve de cotations pour huit symboles ramenait 15 000 caractères de JSON dans le contexte, soit près de 4 000 tokens, relus intégralement à chaque tour de conversation suivant. Sur une session qui enchaîne vingt tours, ce même bloc est payé vingt fois.

La donnée n'a pourtant aucune raison de traverser le modèle. Elle doit atterrir sur disque, être réduite par un script à ce qui compte, et n'entrer dans le prompt que sous forme condensée.

Le multiplicateur silencieux

Un fichier d'instructions de 36 000 caractères rechargé à chaque invocation coûte environ 9 000 tokens avant que le travail commence. Une référence de 77 000 caractères en coûte 19 000. Ces coûts sont invisibles dans les logs applicatifs parce qu'ils ne correspondent à aucune action : ils se paient à l'ouverture de la porte.

L'incident qui a rendu le problème visible

Le 22 juillet, une seule production a coûté 4,3 millions de tokens et 28 minutes . Une production. La cause tenait en une ligne d'orchestration : le workflow lançait un agent de validation par titre, soit quatorze agents en parallèle, chacun en mode raisonnement approfondi, chacun refaisant sa propre collecte de données (identité de l'instrument, dépôts réglementaires, cotation, indicateurs) et relisant les mêmes fichiers de contexte.

Le résultat n'était même pas bon : cinq titres retenus sur quatorze, et une liste finale incomplète. On avait payé quatorze contextes complets pour un verdict qui tient dans un tableau.

Avant1 agent par titre × 14 titres, chacun appelant les données pour son compte
Coût≈ 50 allers-retours de données, 14 fenêtres de contexte, 4,3 M tokens, 28 min
Après1 salve groupée multi-symboles en amont, dump sur disque, puis raisonnement sur le pré-collecté
Coût2 à 4 appels de données au total, 1 seul agent de verdict sur le lot

La règle qui en sort est simple à énoncer et facile à violer sans s'en apercevoir : le nombre d'allers-retours vers une source de données doit croître avec le nombre de TYPES de données, jamais avec le nombre d'éléments à traiter. Huit types de données pour quatorze titres, c'est huit requêtes multi-symboles, pas cent douze.

Le corollaire d'orchestration est tout aussi net : avant d'écrire une boucle parallèle d'agents, vérifier qu'aucune branche n'appelle une source externe. Si une branche le fait, la parallélisation ne divise pas le temps, elle multiplie la facture par le nombre de branches.

Le test des deux questions

Avant tout éclatement en agents parallèles : (1) est-ce que chaque branche a vraiment besoin de sa propre fenêtre de contexte, ou est-ce qu'un seul agent peut trancher sur le lot entier ? (2) est-ce qu'une branche déclenche un appel réseau qu'une autre branche déclenche aussi ? Deux « non » autorisent le fan-out. Un seul « oui » impose de sortir la collecte en amont.

Règle 1 : une hiérarchie de modèles par rôle

Le premier correctif consiste à cesser de traiter « le modèle » comme un paramètre global. Chaque étape d'un workflow a un rôle, et chaque rôle a un besoin cognitif différent. Notre grille tient en trois lignes.

Rôle dans le workflow Ce qu'il produit Niveau de modèle
Rédacteur, arbitre Un jugement : quelle thèse tient, quel désaccord entre relecteurs l'emporte, quelle formulation est honnête Haut de gamme, raisonnement approfondi
Analyste, relecteur de jugement Une opinion argumentée sur un artefact déjà écrit Intermédiaire, effort élevé
Extraction, validation, mise en forme Un résultat déterministe : un champ, un compte, un booléen Intermédiaire effort moyen, ou modèle rapide

Le défaut par défaut devient le niveau intermédiaire à effort élevé, et le haut de gamme se mérite. Une étape qui parse, valide ou filtre ne reçoit jamais le modèle le plus cher : c'est une règle, pas une recommandation, parce que l'exception se généralise toujours toute seule.

# Avant : un seul niveau, appliqué partout
stages = [
  collecte(modele="haut-de-gamme", effort="high"),   # parse du JSON
  extraction(modele="haut-de-gamme", effort="high"), # lit 6 champs
  redaction(modele="haut-de-gamme", effort="high"),  # légitime
  validation(modele="haut-de-gamme", effort="high"), # compare des seuils
]

# Après : le niveau suit le rôle
stages = [
  collecte(modele="rapide"),                                # mécanique
  extraction(modele="intermediaire", effort="medium"),  # mécanique
  redaction(modele="haut-de-gamme", effort="high"),     # jugement
  validation(script="regles-dures"),                        # zéro token
]

Cette dernière ligne est la plus rentable de toutes : la validation n'a pas changé de modèle, elle a quitté le modèle.

Règle 2 : le jugement aux agents, la mécanique aux scripts

La deuxième règle trace une frontière franche. Un contrôle qui peut s'écrire comme une fonction pure s'écrit comme une fonction pure. Un contrôle qui demande de lire un texte et de dire s'il sonne juste reste à un agent.

Contrôle Nature Qui l'exécute
Rapport risque/récompense, arithmétique des niveaux Calcul Script — coût nul, reproductible
Balises structurelles, présence des sections obligatoires Grammaire Script
Formules toutes faites et tics d'écriture Correspondance de motifs Script — 77 formules, 8 connecteurs, densité de ponctuation
Fraîcheur des données déclarées Comparaison d'horodatages Script
Le chiffre affiché correspond-il à la source ? Vérification contextuelle Agent — irréductible
La thèse tient-elle debout, le titre est-il honnête ? Jugement éditorial Agent — irréductible

Le panel de routine est passé de cinq à sept relecteurs à deux lentilles de jugement : un relecteur qui confronte chaque chiffre à sa source, un relecteur éditorial. Le reste est descendu dans les scripts, qui tournent de toute façon et qui bloquent la publication. Les panels larges restent, mais pour ce qu'ils justifient : une première publication importante, un contenu qui part par courriel, un format nouveau.

Le test avant de spawner un relecteur

  • Ce contrôle produit-il le même verdict sur la même entrée, toujours ? Alors c'est un script.
  • Existe-t-il déjà un script qui le couvre ? Alors le relecteur est une dépense nette.
  • Le verdict dépend-il d'un contexte que le script n'a pas ? Alors l'agent est justifié, et il faut lui donner ce contexte, pas le laisser le redécouvrir.

Règle 3 : les données sur disque, pas dans le contexte

La troisième règle est la plus simple à implémenter et la plus rentable sur les gros volumes. Dès qu'une collecte dépasse deux symboles croisés avec deux types de données, elle sort du modèle : un script appelle la source, écrit le résultat brut dans un fichier, et un second script en extrait les quelques valeurs utiles. L'agent reçoit un résumé compact, pas un dump.

# Anti-pattern : le JSON brut entre dans la conversation
quotes = fetch(symbols=[...8 symboles...])   # 15 000 caractères
agent(prompt=f"Voici les cotations : {quotes}. Analyse.")
# → ~4 000 tokens, repayés à chaque tour suivant de la session

# Pattern : le disque sert de mémoire, le script sert de filtre
run("collecte --symbols … --types quote,flags --out data/brut.json")
resume = run("reduire data/brut.json --champs last,var_pct,volume")
agent(prompt=f"Cotations : {resume}")   # ~300 tokens

Un corollaire compte autant que la règle : un résultat déjà écrit sur disque ne se re-télécharge jamais. Quand un retour d'outil est trop gros et déborde automatiquement dans un fichier, le réflexe correct est de parser ce fichier, pas de relancer l'appel pour « avoir la donnée sous les yeux ». Le second geste paie deux fois la même information.

Dernier point, moins technique et plus organisationnel : une méga-session qui enchaîne cinq produits différents finit par saturer sa fenêtre, se faire compacter, et repayer tout son historique à chaque compaction. Une session, un produit. Le découpage n'améliore pas seulement le coût, il améliore la traçabilité de ce qui a été décidé où.

Ce que ça a donné

Les trois règles ont été appliquées d'un bloc sur la chaîne éditoriale. La mesure porte sur un produit équivalent, même format, même exigence de sortie, même panel de publication : 827 000 tokens contre 1,4 million la veille. La facture du produit a été divisée par 1,7, la qualité de sortie n'a pas bougé, et le temps de cycle a baissé parce que les étapes mécaniques ne raisonnent plus.

Poste Avant Après Levier
Étapes mécaniques (extraction, validation, mise en forme) Haut de gamme, effort maximal Intermédiaire ou script Hiérarchie par rôle
Panel de relecture de routine 5 à 7 agents 2 lentilles de jugement Script d'abord
Collecte de données JSON inline dans le prompt Fichier + résumé compact Disque
Validation d'une liste de N éléments N agents, N collectes 1 collecte groupée, 1 agent Batch avant fan-out

Ce qui reste cher, et qu'on garde

Une diète mal faite coupe le muscle. Deux postes coûteux ont été explicitement sanctuarisés.

Le premier est le panel adversarial avant publication. C'est du raisonnement, il ne se compresse pas comme du transport de données, et il rallonge un cycle complet à une trentaine de minutes. Il reste, parce qu'une seule journée de relevé lui doit : une dizaine de cotations fausses attrapées dans une revue hebdomadaire, un risque de dilution de 32,5 millions d'actions manqué par le rédacteur, et un article dont la thèse entière reposait sur l'absence d'un catalyseur qui existait. Le coût du panel est connu ; le coût d'une publication fausse ne l'est pas.

Le second est le modèle haut de gamme sur le rédacteur et l'arbitre. Ce sont les deux seuls rôles où une meilleure capacité change le produit fini plutôt que sa vitesse. Économiser là revient à économiser sur ce qu'on vend.

Ce qui a été supprimé n'était ni du contrôle ni de la rédaction : c'était de la redondance déguisée en rigueur. Un système d'agents donne l'illusion réconfortante que plus d'yeux valent mieux, et cette illusion a un prix par token. La discipline consiste à demander, pour chaque agent que l'on ajoute, ce qu'il voit que personne d'autre ne voit.

La checklist en six points

  • Le niveau de modèle suit le rôle. Aucune étape mécanique ne reçoit le modèle le plus cher.
  • Aucun agent ne recalcule ce qu'un script calcule déjà.
  • La collecte de données est groupée en amont ; les branches parallèles ne rappellent jamais la source.
  • Les gros retours vont sur disque et n'entrent dans le prompt que réduits.
  • Une session, un produit. Les compactions à répétition repaient tout.
  • Les instructions rechargées à chaque invocation sont un coût fixe : les tenir courtes est un gain à chaque appel.

Portée de ces chiffres

Les volumes cités sont ceux relevés sur notre propre chaîne de production éditoriale, sur des journées identifiées. Ils dépendent de notre découpage en agents, de nos formats de sortie et de nos volumes de données : ils illustrent des ordres de grandeur et des mécanismes, ils ne se transposent pas tels quels. Cet article décrit une architecture logicielle et ne constitue pas un conseil financier.

La facture Diagnostic L'incident Modèles Scripts Données Résultat Arbitrage