Une fonctionnalité d’IA sans plafond de dépense, c’est une fonctionnalité qui peut te facturer un montant illimité. Une boucle d’agent qui s’emballe, un utilisateur qui colle un roman dans la zone de chat, un prompt qui fait divaguer le modèle sur 4 000 tokens — chacun de ces cas gonfle ta facture en silence. Le remède, ce sont deux contrôles bon marché et sans éclat : borne chaque appel avec max_tokens, et suis la dépense par utilisateur depuis l’objet usage pour pouvoir couper quelqu’un avant qu’il ne te coûte plus qu’il ne rapporte.
Rien de tout cela n’est difficile. Le difficile, c’est de faire confiance aux chiffres qui servent de base à tes plafonds. Un budget ne vaut que ce que valent les décomptes de tokens qui l’alimentent — si ta passerelle rembourre usage ou te facture les appels échoués, ton plafond soigneusement calculé à 1 $/utilisateur/jour vaut en réalité 1,40 $, et tu ne le saurais jamais. Cet article fait donc deux choses : il te montre la mécanique, et il explique pourquoi c’est la facturation honnête qui fait marcher cette mécanique.
Étape 1 — borne chaque appel avec max_tokens
La sortie est la moitié coûteuse de la plupart des factures. Sur Claude Sonnet 4.6, la sortie revient à 12,75 $ par 1M de tokens — cinq fois le tarif d’entrée de 2,55 $. Une réponse que tu attendais en trois phrases et qui revient en douze paragraphes n’est pas un problème de qualité ; c’est un problème de coût. max_tokens, c’est le plafond strict qui rend le pire cas connu d’avance.
# Plafonne le coût de chaque appel avec max_tokens.
# Cela borne la *sortie* — la moitié coûteuse de la plupart des factures — à un
# plafond strict. Le modèle s'arrête à la limite au lieu de partir en longueur.
from openai import OpenAI
client = OpenAI(
api_key="sk-brievio-...",
base_url="https://api.brievio.com/v1",
)
# Claude Sonnet 4.6 : 2,55 $ en entrée / 12,75 $ en sortie par 1M de tokens.
# Sans plafond, une réponse bavarde peut grimper à 4 000+ tokens de sortie.
# Avec max_tokens=500, tu bornes le coût de sortie de CET appel à :
# 500 × 12,75 $ / 1M = 0,0064 $ — peu importe ce que le modèle « veut » dire.
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
max_tokens=500, # respecté nativement — un vrai arrêt strict
messages=[
{"role": "system", "content": "Answer in at most 3 sentences."},
{"role": "user", "content": user_question},
],
)
# Vérifie toujours pourquoi ça s'est arrêté. "length" signifie que tu as touché le
# plafond et que la réponse est peut-être tronquée — le signal pour relever le
# plafond de CETTE classe de tâche, pas globalement.
if resp.choices[0].finish_reason == "length":
print("Truncated at the cap — consider a higher max_tokens here.")
print(resp.choices[0].message.content)
print(resp.usage) # décomptes entrée/sortie honnêtes — voir la section suivanteBrievio respecte max_tokens nativement face au modèle authentique — c’est un vrai arrêt, pas une suggestion. Règle-le par classe de tâche, pas une fois pour toutes : un classifieur a besoin de peut-être 5 tokens, une réponse de chat 500, un long résumé 2 000. La discipline, c’est de choisir un nombre pour chaque site d’appel et de surveiller finish_reason. Quand il revient "length", tu as tronqué une vraie réponse et tu devrais relever le plafond pour ce chemin précis — pas le relever partout et perdre la protection.
Étape 2 — valorise toi-même l’objet usage
Chaque réponse Brievio porte un objet usage avec les vrais décomptes de tokens d’entrée et de sortie de l’appel, et chaque requête est journalisée avec ses vrais tokens et son coût. Autrement dit, tu n’as pas à attendre une facture de fin de mois pour savoir ce que quoi que ce soit a coûté — tu peux valoriser chaque appel à l’instant où il revient :
usage.prompt_tokens— tokens d’entrée réellement envoyés.usage.completion_tokens— tokens de sortie réellement générés (c’est ce quemax_tokensborne).usage.total_tokens— la somme, pour une vérification rapide.
Multiplie chaque décompte par le tarif publié par modèle et tu obtiens le coût exact de l’appel, dans ton propre code, en temps réel. Les tarifs par modèle sont publiés sur la page de tarifs face à la référence officielle, si bien que les constantes dans ton code sont auditables — pas un chiffre que tu dois croire sur parole.
Étape 3 — suis la dépense par utilisateur et coupe à un budget
Les plafonds par requête te protègent d’un seul mauvais appel. Les budgets par utilisateur te protègent d’un seul mauvais acteur — le compte qui lance des milliers d’appels par jour, que ce soit par enthousiasme, par automatisation ou par abus. Le motif, c’est un nombre durable par utilisateur que tu vérifies avant l’appel et que tu incrémentes après :
# Suis la dépense par utilisateur depuis l'objet usage, puis coupe à un budget.
# usage renvoie les VRAIS décomptes de tokens entrée/sortie de l'appel. Tu les
# valorises en local face au tarif publié par modèle et tu les ajoutes à un
# cumul courant indexé par utilisateur.
from decimal import Decimal
# Tarifs Brievio publiés, en USD par 1M de tokens (≈15 % sous le catalogue officiel).
RATES = {
"claude-sonnet-4-6": {"in": Decimal("2.55"), "out": Decimal("12.75")},
"claude-haiku-4-5": {"in": Decimal("0.85"), "out": Decimal("4.25")},
}
def cost_usd(model: str, usage) -> Decimal:
r = RATES[model]
million = Decimal("1000000")
return (usage.prompt_tokens * r["in"] / million +
usage.completion_tokens * r["out"] / million)
# Le stockage de ton choix — compteur Redis, une colonne SQL, peu importe. Le but,
# c'est un nombre durable par utilisateur. Les appels 4xx/5xx échoués sont gratuits
# sur Brievio, donc tu n'ajoutes jamais de coût que pour les appels qui ont vraiment
# renvoyé un résultat.
DAILY_BUDGET = Decimal("1.00") # 1 $/utilisateur/jour
def chat_for_user(user_id: str, question: str, model="claude-sonnet-4-6"):
spent = get_spent_today(user_id) # Decimal, défaut à 0
if spent >= DAILY_BUDGET:
raise BudgetExceeded(f"{user_id} hit ${DAILY_BUDGET}/day")
resp = client.chat.completions.create(
model=model,
max_tokens=500,
messages=[{"role": "user", "content": question}],
)
add_spent_today(user_id, cost_usd(model, resp.usage)) # cumule le coût réel
return resp.choices[0].message.contentChoisis le seuil à partir de ton modèle économique : si un siège payant vaut 20 $/mois et que tu veux que l’IA reste sous, disons, 20 % du chiffre d’affaires, ça fait un budget d’environ 0,13 $/utilisateur/jour. Avertis en douceur à 80 % (une bannière, un e-mail), coupe net à 100 % (le chemin BudgetExceeded ci-dessus). Pour les utilisateurs de l’offre gratuite, mets le plafond bas et rétrograde le modèle — déplacer le trafic non critique de Sonnet vers Haiku 4.5 à 0,85 $ en entrée / 4,25 $ en sortie réduit le coût par token d’environ deux tiers tout en gardant le même comptage honnête.
Pourquoi une facturation honnête rend le calcul fiable
Voici la partie que la plupart des guides de maîtrise des coûts sautent. Les deux contrôles ci-dessus — le plafond par appel et le budget par utilisateur — sont de l’arithmétique sur des décomptes de tokens. Si ces décomptes sont gonflés, chaque chiffre en aval est faux du même facteur, en silence. Deux comportements de facturation décident si tes plafonds veulent bien dire ce qu’ils annoncent :
- Les appels échoués sont gratuits. Sur Brievio, une réponse 4xx ou 5xx ne coûte rien — tu es facturé pour des résultats, pas pour des tentatives. Ça compte pour les budgets en particulier : une tempête de retries contre un service en aval instable ne devrait pas vider l’allocation quotidienne d’un utilisateur. Comme tu ne cumules le coût que sur les appels qui ont renvoyé un résultat, ta courbe de dépense suit la valeur livrée, pas les erreurs encaissées.
- Les décomptes ne sont pas gonflés. L’objet
usagereflète les tokens que le modèle authentique a réellement traités — pas de prompt rembourré, pas de sortie fantôme ajoutée au compteur. Le bon réflexe, c’est de ne pas le croire sur parole : envoie un prompt fixe connu, relisprompt_tokens, et confirme qu’il correspond à ce que le tokenizer dit qu’il devrait être. Nous avons écrit un auto-test d’inflation de tokens en 20 lignes qui fait exactement ça — lance-le contre n’importe quelle passerelle, la nôtre comprise, avant de faire confiance à ses chiffres.
Le lien est direct : un budget calculé à partir de décomptes rembourrés coupe les utilisateurs trop tôt et surestime ton coût ; un budget qui inclut les appels échoués punit les utilisateurs pour les mauvais jours de ton infrastructure. C’est le comptage honnête qui permet à un plafond de 1 $/jour de vraiment valoir un dollar. Brievio facture le chat environ 15 % sous le catalogue officiel, au paiement à l’usage, avec un solde qui n’expire jamais — donc le plafond que tu fixes est le plafond que tu obtiens, et le budget inutilisé reste le tien.
On assemble le tout
Une posture de dépense prête pour la production, c’est quatre petites habitudes, dont aucune ne prend plus d’un après-midi :
- Chaque site d’appel fixe
max_tokensdimensionné à sa tâche. Aucune sortie illimitée, nulle part. - Chaque réponse est valorisée depuis
usageau tarif publié et ajoutée à un cumul par utilisateur. - Chaque utilisateur a un budget avec un avertissement en douceur et une coupure nette tirés de ton modèle économique.
- Le trafic moins exigeant rétrograde vers un modèle plus petit (Haiku, classe mini) plutôt que de payer des tarifs phares pour un travail qui n’en a pas besoin.
Fais ces quatre choses et ta facture du pire cas est un nombre que tu as choisi, pas un nombre que tu découvres. Pour les leviers plus profonds — cache de prompts, traitement par lots, choix du modèle, élagage des prompts — vois le guide d’optimisation des coûts, et la documentation pour le schéma complet de usage et les paramètres compatibles OpenAI que Brievio prend en charge. La maîtrise des coûts n’est pas une fonctionnalité que tu boulonnes une fois que la facture t’a fait peur — c’est deux lignes et un compteur, et ça marche d’autant mieux sur un compteur en qui tu peux avoir confiance.