Si tu envoies un long prompt système — contexte RAG, un catalogue d’outils, des règles d’agent, des exemples — tu paies probablement le plein tarif d’entrée à chaque appel. Le prompt caching d’Anthropic réduit ça à 10 % du tarif sur la portion cachée. OpenAI fait la même chose implicitement. La plupart des équipes jugent l’opération rentable pour 30 minutes de travail, parce qu’elle retranche de manière fiable 60 à 90 % de leur poste de coût d’entrée.
Brievio fait passer les deux variantes sans modification, face au modèle authentique. Le cache_control de style Anthropic fonctionne sur l’API Messages ; le cache automatique de style OpenAI fonctionne sur l’API Chat Completions. Cet article parcourt les deux, les pièges qui invalident discrètement les caches, et comment vérifier ton taux de hit.
L’avant-après
Une boucle naïve qui envoie dix fois le même prompt système de 18K tokens :
# Le point de départ habituel : chaque appel repaie le prompt en entier.
import anthropic
client = anthropic.Anthropic(
api_key="sk-brievio-...",
base_url="https://api.brievio.com",
)
SYSTEM = open("system-prompt.md").read() # 18 000 tokens de règles + exemples
# 10 questions utilisateur dans une session. Chaque appel envoie le bloc système de 18K tokens.
for question in questions:
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=SYSTEM,
messages=[{"role": "user", "content": question}],
)
# Coût par appel (entrée seule) : 18 000 × $3 / 1M = $0.054
# 10 appels : $0.54 rien qu'en entrée.Maintenant, marque le bloc système comme cacheable — un champ de plus :
# Le correctif : marque le préfixe statique comme cacheable. Après le premier
# appel, les appels suivants dans les ~5 minutes paient 10 % du tarif d'entrée sur
# la portion cachée. Même réponse, 89 % moins cher.
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{
"type": "text",
"text": SYSTEM,
"cache_control": {"type": "ephemeral"}, # marquer comme cacheable
}
],
messages=[{"role": "user", "content": question}],
)
# Premier appel (écriture cache) : 18 000 × $3 / 1M = $0.054
# Appels 2 à 10 (hit de cache) : 18 000 × $0.30 / 1M = $0.0054 chacun
# Total : $0.054 + 9 × $0.0054 = $0.103 (c'était $0.54 — 81 % économisés)Tu viens d’économiser 81 % du coût d’entrée sur cette session. Le premier appel est en réalité légèrement plus cher que la version naïve (~1,25× le tarif d’entrée pour écrire le cache). Les appels 2 à 10 paient 10 % du tarif. Le point de bascule est à l’appel 2 — dès l’appel 3 tu es gagnant. À l’appel 10, c’est un raz-de-marée.
Style OpenAI : rien à faire
Si tu utilises le SDK OpenAI, Chat Completions cache le préfixe de n’importe quel prompt de plus de 1 024 tokens automatiquement. Aucun drapeau, aucune config. Le même modèle derrière Brievio obtient la remise, que tu sois passé par la voie Anthropic ou OpenAI dans :
# Style OpenAI Chat Completions — le cache est automatique pour les prompts ≥1024 tokens.
# Aucun drapeau à poser. L'objet "usage" t'indique ce qui a été caché.
from openai import OpenAI
client = OpenAI(
api_key="sk-brievio-...",
base_url="https://api.brievio.com/v1",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[
{"role": "system", "content": LONG_SYSTEM_PROMPT}, # >1024 tokens
{"role": "user", "content": "Latest question…"},
],
)
# Dans la réponse :
# resp.usage.prompt_tokens_details.cached_tokens → 17 800
# resp.usage.prompt_tokens → 18 200
# 17,8K/18,2K = 98 % de l'entrée vient du cache. La facture le reflète automatiquement.Lis usage.prompt_tokens_details.cached_tokens pour voir quelle part a été servie depuis le cache. Plus le préfixe fixe est grand, plus l’économie est grande. La règle empirique : si ton prompt système est plus court que ton contenu utilisateur variable, le cache ne fait pas grand-chose. Remodèle le prompt pour que les parties statiques soient grandes et placées en tête.
Cache multicouche — jusqu’à 4 points de coupure
Pour les boucles d’agent où certaines couches changent plus vite que d’autres, pose plusieurs points de coupure cache_control. Chacun est un instantané de tout ce qui précède jusqu’à ce point :
# Anthropic gère jusqu'à 4 points de coupure de cache par requête — sers-t'en
# pour garder le cache chaud même quand les couches ultérieures changent.
client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{"type": "text",
"text": ROLE_AND_RULES, # ~3 000 tokens
"cache_control": {"type": "ephemeral"}}, # coupure 1
{"type": "text",
"text": LARGE_KNOWLEDGE_BASE, # ~15 000 tokens, change rarement
"cache_control": {"type": "ephemeral"}}, # coupure 2
],
messages=[
{"role": "user",
"content": [
{"type": "text",
"text": CONVERSATION_HISTORY, # grandit à chaque tour
"cache_control": {"type": "ephemeral"}}, # coupure 3
{"type": "text", "text": new_question},
]},
],
)
# Quand CONVERSATION_HISTORY change, les coupures 1+2 touchent encore le cache.
# Seules la coupure 3 + la nouvelle question paient le plein tarif d'entrée.La clé de cache, c’est le préfixe entier. Ajoute un token en position N et chaque coupure à partir de N est invalidée. L’ordre compte : le contenu le plus stable en premier. La couche de règles devrait rarement changer ; la base de connaissances se met à jour chaque semaine ; la conversation grandit à chaque tour.
Les façons courantes de casser le cache en silence
- Mettre la date courante ou un request_id dans le prompt. Chaque appel est un nouveau préfixe, le taux de hit de cache est de 0 %. Hache les entrées de ton prompt et compare-les d’un appel à l’autre.
- Assemblage non déterministe du prompt système. Si tu construis le système à partir d’un dict, l’ordre d’itération du dict compte dans certaines versions de Python. Trie les clés explicitement.
- La durée de vie du cache est d’environ 5 minutes. Les trafics clairsemés (un appel toutes les 10 minutes) n’obtiennent aucun hit. Soit tu regroupes les appels, soit tu acceptes la perte.
- Le minimum de 1 024 tokens. En dessous de 1K tokens, le cache de style OpenAI ne s’enclenche pas. Combine les petits fragments statiques en un seul préfixe plus long.
- Les outils / définitions de fonctions font partie du préfixe. Un nouvel outil ajouté au catalogue invalide le cache pour tout le monde. Garde le catalogue d’outils stable ; versionne-le.
Vérifier le taux de hit
Un cache que tu ne peux pas voir, ce n’est pas de l’ingénierie — c’est de l’espoir. Journalise usage à chaque appel :
# Lis toujours usage. Si cached_tokens est à 0 alors que tu attendais un hit,
# quelque chose cloche — généralement un préfixe non déterministe.
resp = client.messages.create(...)
u = resp.usage
print({
"input_uncached": u.input_tokens,
"input_cache_read": u.cache_read_input_tokens,
"input_cache_write": u.cache_creation_input_tokens,
"output": u.output_tokens,
})
# Piège fréquent : mettre la date du jour ou un request_id dans le prompt système
# invalide silencieusement le cache. Hache tes entrées ; vérifie que
# cache_read_input_tokens est non nul au 2e appel identique.Dans le tableau de bord Brievio, la page Usage affiche la répartition du cache par modèle et par jour. Si tu vois cache_read_input_tokens croître en pourcentage de l’entrée totale, le cache fonctionne. S’il reste à 0 ou fluctue de manière erratique, déroule la liste des pièges ci-dessus.
Ce que ça coûte réellement sur Brievio
Le tarif de cache de chaque modèle est publié sur la page de tarifs :
- Modèles Anthropic : les lectures de cache sont à 10 % du tarif d’entrée. Les écritures de cache sont facturées au tarif d’entrée — aucun surcoût en amont.
- Modèles OpenAI / Gemini : les lectures de cache sont à 20 % du tarif d’entrée (le ratio publié par les fournisseurs).
- Tous les tarifs de cache reflètent le catalogue de Brievio — environ 15 % sous le tarif officiel du fournisseur. Ainsi une lecture de cache Sonnet 4.6 sur Brievio coûte
$3 × 0.95 × 0.10 = $0.285 per 1M tokens. Environ 10× moins cher que le tarif d’entrée non caché.
Quand le cache n’est pas la réponse
Quelques cas où l’effort n’en vaut pas la peine :
- Prompts courts (<1K tokens au total). La surcharge domine ; ne te casse pas la tête.
- Tâches one-shot sans trafic répété. Le premier appel est légèrement plus cher — le cache ne se rentabilise qu’à partir de l’appel 2.
- Tâches à forte sortie, faible entrée (écriture créative, génération de code). L’entrée représente déjà une petite part de la facture. Concentre-toi plutôt sur des plafonds de budget de sortie.
Pour tout le reste — chatbots RAG, agents avec un catalogue d’outils fixe, classifieurs qui tournent sur une grille statique, pipelines d’extraction structurée avec des few-shots constants — le cache est l’optimisation au meilleur ROI que tu puisses livrer en un seul après-midi. Associe-le aux quatre autres techniques de notre guide d’optimisation des coûts et 70 % de réduction de coût devient réaliste, sans le moindre compromis sur la qualité de sortie.
Déjà sur Brievio ? Ouvre /app/usage et regarde la colonne de cache de ton plus gros modèle. Si elle est à zéro, tu laisses de l’argent sur la table. Guide complet : /docs/caching.