Prompt Caching : L'Astuce qui Divise votre Facture LLM par 10 (Anthropic, OpenAI, Google)
Guide complet sur le prompt caching pour réduire vos coûts LLM : fonctionnement du prefix matching, stratégies par fournisseur (Anthropic, OpenAI, Google), calculs d'économies et optimisation RAG.
Prompt Caching : L'Astuce qui Divise votre Facture LLM par 10
Votre facture LLM explose ? Vous envoyez les mêmes instructions système, les mêmes few-shot examples, le même contexte RAG à chaque requête ? Il existe une solution qui peut réduire vos coûts de 90% chez Anthropic et de 50% chez OpenAI -- et la plupart des développeurs ne l'utilisent pas encore.
Bienvenue dans le monde du prompt caching.
TL;DR
- Prompt caching = le fournisseur LLM met en cache le préfixe de votre prompt pour ne pas le re-traiter à chaque requête
- Anthropic : -90% sur les tokens cachés (le plus agressif), minimum 1 024 tokens, TTL 5 minutes
- OpenAI : -50% sur les tokens cachés, automatique, minimum 1 024 tokens
- Google : -75% sur les tokens cachés, context caching explicite, minimum 32 768 tokens
- Pour le RAG : cachez le system prompt + few-shot examples + contexte statique, ne variez que la query
- Économies typiques : 40-80% de réduction sur la facture LLM mensuelle
Comment Fonctionne le Prompt Caching
Le principe : prefix matching
À chaque appel LLM, le fournisseur compare le début de votre prompt avec les prompts récents. Si un préfixe identique est trouvé en cache, seule la partie nouvelle est traitée à plein tarif.
Requête 1 :
┌──────────────────────────────────────────────────────────┐
│ System prompt (2000 tokens) │ Few-shots (1000) │ Query 1 │
│ ████████████████████████████ │ ████████████████ │ ████ │
│ Traité normalement │ │ │
└──────────────────────────────────────────────────────────┘
Coût : 3000 tokens × prix normal = $0.045
Requête 2 (même préfixe) :
┌──────────────────────────────────────────────────────────┐
│ System prompt (2000 tokens) │ Few-shots (1000) │ Query 2 │
│ ░░░░░░░░░░░░░░░░░░░░░░░░░░ │ ░░░░░░░░░░░░░░░ │ ████ │
│ EN CACHE (tarif réduit) │ │ Normal │
└──────────────────────────────────────────────────────────┘
Coût : 3000 tokens × prix caché + 50 tokens × prix normal = beaucoup moins
Conditions pour le cache hit
| Condition | Description |
|---|---|
| Préfixe identique | Les tokens doivent être rigoureusement identiques au début |
| Même modèle | Le cache est par modèle (GPT-4o ≠ GPT-4o mini) |
| TTL respecté | Le cache expire après un certain temps (varie par fournisseur) |
| Taille minimum | Un nombre minimum de tokens est requis pour déclencher le cache |
| Ordre important | System → User → Assistant doit être dans le même ordre |
Anthropic : Le Champion du Caching (-90%)
Fonctionnement
Anthropic offre la réduction la plus agressive : 90% de réduction sur les tokens cachés, avec un léger surcoût de 25% à l'écriture initiale du cache.
| Paramètre | Valeur |
|---|---|
| Réduction sur lecture cache | -90% |
| Surcoût écriture cache | +25% |
| TTL | 5 minutes (renouvelé à chaque hit) |
| Taille minimum | 1 024 tokens (Claude 3.5) / 2 048 tokens (Claude 3) |
| Blocs de cache | Multiples breakpoints possibles |
Tarification détaillée Claude 3.5 Sonnet
| Type de token | Prix / 1M tokens | vs Base |
|---|---|---|
| Input (base) | $3,00 | - |
| Input (cache write) | $3,75 | +25% |
| Input (cache read) | $0,30 | -90% |
| Output | $15,00 | - |
Implémentation Anthropic
DEVELOPERpythonimport anthropic client = anthropic.Anthropic() # Le system prompt sera caché après le premier appel SYSTEM_PROMPT = """Tu es un assistant expert pour {company_name}. Tu réponds uniquement à partir des documents fournis. Tu cites toujours tes sources avec [Source: nom_document]. Tu ne hallucines jamais. Si tu ne sais pas, dis-le. ## Règles de formatage - Réponses concises (3-5 phrases max) - Utilise des bullet points pour les listes - Cite la source entre crochets ## Exemples de réponses attendues Q: Quelle est la politique de retour ? A: Notre politique de retour permet les retours sous 30 jours pour tout article non utilisé [Source: politique-retours.pdf]. Les frais de retour sont à la charge du client sauf en cas de défaut produit [Source: CGV-2026.pdf]. Q: Comment configurer le SSO ? A: Pour configurer le SSO, allez dans Paramètres > Sécurité > SSO. Sélectionnez votre fournisseur (Okta, Azure AD, Google) et collez l'URL de métadonnées [Source: guide-admin.pdf]. """ + context_documents # Ajoutez votre contexte RAG ici def query_with_caching(user_query: str, rag_context: str): """Requête avec prompt caching Anthropic.""" response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, system=[ { "type": "text", "text": SYSTEM_PROMPT, "cache_control": {"type": "ephemeral"} # Active le cache } ], messages=[ { "role": "user", "content": f"Contexte RAG:\n{rag_context}\n\nQuestion: {user_query}" } ], ) # Vérifier le cache hit usage = response.usage print(f"Cache read: {usage.cache_read_input_tokens} tokens") print(f"Cache write: {usage.cache_creation_input_tokens} tokens") print(f"Input non-caché: {usage.input_tokens} tokens") return response.content[0].text
Stratégie multi-breakpoints Anthropic
DEVELOPERpythondef query_with_multi_cache(user_query: str, rag_context: str): """Plusieurs niveaux de cache pour maximiser les économies.""" response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, system=[ { "type": "text", "text": STATIC_SYSTEM_PROMPT, # Rarement change "cache_control": {"type": "ephemeral"} }, { "type": "text", "text": FEW_SHOT_EXAMPLES, # Change parfois "cache_control": {"type": "ephemeral"} } ], messages=[ { "role": "user", "content": [ { "type": "text", "text": rag_context, # Change souvent mais partagé "cache_control": {"type": "ephemeral"} }, { "type": "text", "text": user_query, # Toujours unique } ] } ], ) return response
OpenAI : Le Caching Automatique (-50%)
Fonctionnement
OpenAI a lancé le caching automatique : pas besoin de configuration, le système détecte et cache automatiquement les préfixes identiques.
| Paramètre | Valeur |
|---|---|
| Réduction sur lecture cache | -50% |
| Surcoût écriture cache | Aucun (gratuit) |
| TTL | 5-10 minutes (variable) |
| Taille minimum | 1 024 tokens |
| Activation | Automatique (pas de configuration) |
Tarification détaillée GPT-4o
| Type de token | Prix / 1M tokens | vs Base |
|---|---|---|
| Input (base) | $2,50 | - |
| Input (cached) | $1,25 | -50% |
| Output | $10,00 | - |
Implémentation OpenAI
DEVELOPERpythonfrom openai import OpenAI client = OpenAI() # Le caching est AUTOMATIQUE chez OpenAI # Il suffit de structurer le prompt avec un préfixe stable SYSTEM_PROMPT = """Tu es un assistant expert pour {company_name}. ... (même long system prompt) ... """ def query_with_openai_caching(user_query: str, rag_context: str): """Le caching est automatique - gardez juste le préfixe identique.""" response = client.chat.completions.create( model="gpt-4o", messages=[ {"role": "system", "content": SYSTEM_PROMPT}, # Astuce : mettre le contexte RAG stable en premier message user {"role": "user", "content": f"Contexte:\n{rag_context}"}, {"role": "assistant", "content": "J'ai bien noté le contexte."}, {"role": "user", "content": user_query}, ], max_tokens=1024, ) # Vérifier les tokens cachés dans l'usage usage = response.usage cached = getattr(usage, 'prompt_tokens_details', {}) if cached: print(f"Cached tokens: {cached.get('cached_tokens', 0)}") return response.choices[0].message.content
Optimiser le cache hit rate chez OpenAI
DEVELOPERpython# MAUVAIS : l'ordre des messages change → pas de cache hit messages_v1 = [ {"role": "system", "content": SYSTEM}, {"role": "user", "content": f"Context: {context_A}\nQuery: {query_1}"}, ] messages_v2 = [ {"role": "system", "content": SYSTEM}, {"role": "user", "content": f"Context: {context_B}\nQuery: {query_2}"}, ] # context_A ≠ context_B → cache miss dès le 2ème message # BON : séparer contexte stable et variable messages_v1 = [ {"role": "system", "content": SYSTEM}, # ← Toujours identique {"role": "user", "content": "Context: " + STATIC_CONTEXT}, # ← Identique {"role": "assistant", "content": "OK."}, {"role": "user", "content": query_1}, # ← Seul élément variable ] messages_v2 = [ {"role": "system", "content": SYSTEM}, # ← Cache hit ! {"role": "user", "content": "Context: " + STATIC_CONTEXT}, # ← Cache hit ! {"role": "assistant", "content": "OK."}, {"role": "user", "content": query_2}, # ← Seul élément variable ]
Google : Context Caching Explicite (-75%)
Fonctionnement
Google propose un context caching explicite avec des TTL configurables et une réduction de 75%.
| Paramètre | Valeur |
|---|---|
| Réduction sur lecture cache | -75% |
| Coût de stockage cache | $1,00 / 1M tokens / heure |
| TTL | Configurable (min 1 min, max 24h) |
| Taille minimum | 32 768 tokens (le plus élevé) |
| Activation | Explicite via API |
Tarification détaillée Gemini 1.5 Pro
| Type de token | Prix / 1M tokens | vs Base |
|---|---|---|
| Input (base) | $1,25 | - |
| Input (cached) | $0,3125 | -75% |
| Output | $5,00 | - |
| Stockage cache | $1,00/h/M tokens | - |
Implémentation Google
DEVELOPERpythonimport google.generativeai as genai from google.generativeai import caching import datetime genai.configure(api_key="GOOGLE_API_KEY") # Créer un cache explicite cache = caching.CachedContent.create( model="models/gemini-1.5-pro-002", display_name="rag-system-prompt", system_instruction=SYSTEM_PROMPT, contents=[ # Pré-charger le contexte RAG statique (doit être > 32K tokens) {"role": "user", "parts": [{"text": LARGE_RAG_CONTEXT}]}, {"role": "model", "parts": [{"text": "Context loaded."}]}, ], ttl=datetime.timedelta(hours=1), # Cache pendant 1 heure ) # Utiliser le cache pour les requêtes model = genai.GenerativeModel.from_cached_content(cached_content=cache) def query_with_google_caching(user_query: str): """Requête utilisant le context cache Google.""" response = model.generate_content(user_query) # Vérifier l'utilisation du cache print(f"Cached tokens: {response.usage_metadata.cached_content_token_count}") print(f"Total tokens: {response.usage_metadata.total_token_count}") return response.text # Supprimer le cache quand plus nécessaire cache.delete()
Comparatif des 3 Fournisseurs
Tableau récapitulatif
| Critère | Anthropic | OpenAI | |
|---|---|---|---|
| Réduction cache | -90% | -50% | -75% |
| Surcoût écriture | +25% | Aucun | Stockage/h |
| Taille minimum | 1 024 tokens | 1 024 tokens | 32 768 tokens |
| TTL | 5 min (renouvelable) | 5-10 min | Configurable (24h max) |
| Activation | Manuelle (cache_control) | Automatique | Manuelle (API) |
| Multi-breakpoints | Oui | Non | Non |
| Meilleur pour | Long system prompts | Tout usage | Très gros contextes |
Simulateur de coûts : 10 000 requêtes / jour
Hypothèse : system prompt de 3 000 tokens + query de 200 tokens, GPT-4o / Claude 3.5 Sonnet / Gemini 1.5 Pro.
| Scénario | Sans cache | Avec cache | Économie |
|---|---|---|---|
| Anthropic | $960/mois | $144/mois | -85% |
| OpenAI | $750/mois | $412/mois | -45% |
| $480/mois | $168/mois | -65% |
Note : Les économies réelles dépendent du cache hit rate. Avec un system prompt stable et un trafic régulier, le hit rate dépasse 90%.
Quel fournisseur choisir pour le caching ?
| Votre situation | Recommandation |
|---|---|
| System prompt > 2K tokens, trafic continu | Anthropic (économies max) |
| Pas envie de changer le code | OpenAI (automatique) |
| Contexte RAG > 32K tokens, TTL long | Google (cache explicite) |
| Budget serré, petites requêtes | OpenAI (pas de surcoût écriture) |
| Multi-tenant avec prompts différents | Anthropic (multi-breakpoints) |
Stratégies de Caching Spécifiques au RAG
Architecture optimale pour le RAG
┌─────────────────────────────────────────────────────┐
│ PROMPT STRUCTURE RAG │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ ← CACHÉ │
│ │ System prompt (instructions) │ (identique │
│ │ + règles de formatage │ pour toutes │
│ │ + tone of voice │ les requêtes) │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ ← CACHÉ │
│ │ Few-shot examples (3-5) │ (change │
│ │ + format attendu │ rarement) │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ ← PARTIELLEMENT │
│ │ Contexte RAG dynamique │ CACHÉ │
│ │ (documents récupérés) │ (si même docs) │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ ← NON CACHÉ │
│ │ Query utilisateur │ (toujours │
│ │ │ unique) │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Stratégie 1 : Cache du system prompt + few-shots
La stratégie la plus simple et la plus efficace :
DEVELOPERpython# Le system prompt et les few-shots ne changent jamais # → Cache hit rate proche de 100% CACHED_PREFIX = f"""{SYSTEM_PROMPT} ## Exemples {FEW_SHOT_EXAMPLES} """ # Seul le contexte RAG et la query changent def build_prompt(rag_docs: list, query: str) -> str: return f"""{CACHED_PREFIX} ## Documents de référence {format_documents(rag_docs)} ## Question {query} """
Stratégie 2 : Cache du contexte RAG fréquent
Pour les questions récurrentes qui retournent les mêmes documents :
DEVELOPERpythonfrom functools import lru_cache @lru_cache(maxsize=100) def get_top_documents(topic: str) -> str: """Cache local des documents les plus demandés.""" docs = search_qdrant(topic, limit=5) return format_documents(docs) # Si 2 utilisateurs posent des questions sur le même sujet # → même contexte RAG → cache hit sur le préfixe
Stratégie 3 : Regroupement par tenant / catégorie
DEVELOPERpython# Multi-tenant : chaque tenant a son propre system prompt caché TENANT_PROMPTS = { "tenant_A": "Tu es l'assistant de TechCorp...", "tenant_B": "Tu es l'assistant de RetailCo...", } # Tant que les requêtes d'un même tenant arrivent dans la fenêtre TTL # → le cache fonctionne parfaitement
Calculateur d'Économies
Formule de calcul
Économie mensuelle =
(nb_requêtes × tokens_cachés × prix_normal × (1 - réduction_cache))
- (nb_requêtes × tokens_cachés × prix_cache)
- coût_écriture_cache
Exemples concrets
| Profil | Requêtes/mois | Tokens cachés/req | Sans cache | Avec cache | Économie |
|---|---|---|---|---|---|
| Startup | 50K | 2 000 | $300 | $75 | $225/mois |
| PME | 300K | 3 000 | $2 700 | $540 | $2 160/mois |
| Enterprise | 2M | 5 000 | $30 000 | $4 500 | $25 500/mois |
| E-commerce | 1M | 2 500 | $7 500 | $1 500 | $6 000/mois |
Pièges et Bonnes Pratiques
Les erreurs courantes
| Piège | Conséquence | Solution |
|---|---|---|
| Timestamp dans le prompt | Cache miss systématique | Exclure du préfixe caché |
| Ordre messages variable | Cache miss | Standardiser l'ordre |
| Contexte RAG au début | Empêche le cache | Mettre en fin de prompt |
| TTL trop court | Cache expire entre les requêtes | Augmenter le trafic ou le TTL |
| Trop de variantes | Faible hit rate | Réduire les variantes de prompt |
Checklist d'optimisation
- Structurer le prompt : statique en haut, dynamique en bas
- Minimiser les changements dans le préfixe
- Monitorer le cache hit rate
- Regrouper les requêtes par tenant/catégorie
- Éviter les éléments dynamiques (date, heure) dans le préfixe
- Tester avec des métriques avant/après
FAQ
Le prompt caching est-il compatible avec le streaming ?
Oui, le prompt caching est totalement compatible avec le streaming chez les 3 fournisseurs. Le cache agit sur les tokens d'entrée (input), pas sur la génération (output). Vous pouvez donc cacher votre prompt et streamer la réponse normalement.
Que se passe-t-il si mon system prompt change ?
Un changement dans le system prompt invalide le cache. La première requête après le changement paiera le plein tarif (+ surcoût d'écriture chez Anthropic). Les requêtes suivantes bénéficieront du nouveau cache. Conseil : versionnez vos prompts et déployez les changements en heures creuses.
Le caching fonctionne-t-il en multi-tenant ?
Oui, mais chaque tenant aura son propre cache (puisque le system prompt diffère). L'astuce : structurez le prompt avec une partie commune à tous les tenants (cachée) et une partie spécifique au tenant (non cachée ou avec son propre cache via les breakpoints Anthropic).
Combien de temps le cache reste-t-il actif ?
Chez Anthropic : 5 minutes, renouvelé à chaque hit. Chez OpenAI : 5-10 minutes, non garanti. Chez Google : configurable jusqu'à 24h. Pour un trafic continu (> 1 requête / 5 min), le cache ne s'invalide pratiquement jamais chez Anthropic.
Le prompt caching est-il utile pour les petits volumes ?
Au-delà de ~100 requêtes par jour avec un prompt stable, le prompt caching est rentable. En dessous, le cache peut expirer entre les requêtes (surtout chez OpenAI avec son TTL court). Pour les très petits volumes, concentrez-vous d'abord sur l'optimisation du choix de modèle.
Prêt à diviser votre facture LLM ? Créez votre compte Ailog et profitez d'un pipeline RAG optimisé avec prompt caching intégré, hébergé en France.
Tags
Articles connexes
Cache RAG Intelligent : Comment Réduire vos Coûts LLM de 80% (Sans Sacrifier la Qualité)
Guide complet du cache RAG : semantic cache, prompt caching, embedding cache, comparaison Redis vs GPTCache, et calculs de ROI pour réduire vos coûts LLM de 80%.
Évaluer un système RAG : Métriques et méthodologies
Guide complet pour mesurer la performance de votre RAG : faithfulness, relevancy, recall, et frameworks d'évaluation automatisée.
Routage LLM : L'Architecture Secrète qui Réduit vos Coûts IA de 60% (Sans Perte de Qualité)
Guide complet sur le routage LLM pour optimiser les coûts : routage par complexité, cascade, consensus. Comparatif Martian, Unify, OpenRouter. Code et architecture pour un router custom.