Fransys
Tous les cours
M2
1 h 30
Pédagogie complète

Cost optimization deep dive (token economics)

Token economics avancé, prompt caching, model routing intelligent, dashboards de coût.

CTO, dirigeants, FinOps, équipes en production

Pourquoi ce module

Une équipe qui industrialise Claude sans token economics passe facilement à 5–10 fois le budget nécessaire. En 2026, une startup typique brûle 150 k$ par mois sur Claude API (Opus) quand elle pourrait dépenser 25 k$ avec routing et cache. 95 % des équipes ne savent pas que la sortie coûte 5 fois plus cher que l'entrée. Ce module dissèque les 4 leviers d'économie (caching, batch, model routing, truncation) et vous fait construire un dashboard de coût opérationnel.

À l'issue, vous réduirez vos dépenses de 60–90 % sans perte de qualité. Cas réel : une PME qui aurait payé 40 k€/an pour support client via Opus + Sonnet = 8 k€/an avec Haiku + routing stratégique.

Panneau /cost de Claude Code : ce qui contribue à la consommation (contexte, sous-agents, sessions longues)
/cost met le doigt sur les vrais postes de dépense : usage à fort contexte (>150k), sessions subagent-heavy, et sessions très longues — exactement les leviers travaillés dans ce module.
Graphiques de données et courbes d'analyse sur écran d'ordinateur, symbolisant l'analytics et la mesure des coûts
FinOps Claude : mesurer, optimiser et économiser 50-80% via caching, routing et batch processing

Objectifs pédagogiques

À l'issue de ce module, vous serez capable de :

  1. Maîtriser la tarification 2026 : prix input/output Opus 4.8, Sonnet 4.6, Haiku 4.5; ratio coût réel par use case
  2. Implémenter prompt caching avec cache_control et calculer ROI (économie jusqu'à 90 % sur input, coût write initial +25 %)
  3. Concevoir un routeur de complexité : Haiku pour classification → Sonnet pour reasoning → Opus pour synthèse, avec seuils calibrés
  4. Utiliser Batch API pour réduire coûte de 50 % sur tâches non-temps-réel (reporting, pre-processing)
  5. Mettre en place observabilité coûts : dashboard Helicone/Langfuse, alertes dépassement budget
  6. Construire stratégie d'économie layered applicable à votre cas d'usage réel (perte qualité < 2 %)

Plan détaillé

  1. Tarification 2026 : prix fixes, ratios input/output
  2. Quand chaque modèle est réellement le moins cher
  3. Prompt caching : cache_control, breakpoints, éphmère (5 min vs 1 h)
  4. Model routing : architecture décision + seuils
  5. Batch API : trade latence vs coût (-50 %)
  6. Truncation : quand laisser tomber contexte ancien
  7. Observabilité coûts : Helicone vs Langfuse
  8. Cas pratique : audit d'un workflow
  9. Atelier : réduction 60–90 %
  10. Ressources tarification

Tarification 2026 : prix fixes, ratios input/output

Tarif par modèle (2026)

ModèleInput (1M tokens)Output (1M tokens)Ratio output/inputUse case optimal
Opus 5 🆕$5$255 ×Reasoning complexe, synthèse — défaut Opus depuis le 24 juillet 2026
Opus 4.8$5$255 ×Génération précédente, même tarif ; défaut sur Bedrock/Vertex
Sonnet 5$2 (promo → 31 août 2026, puis $3)$10 (puis $15)5 ×Défaut Claude Code — agentique proche d'Opus
Sonnet 4.6$3$155 ×Équilibre vitesse/qualité (génération précédente)
Haiku 4.5$1$55 ×Classification, filtrage
Fable 5$10$505 ×Frontière — 2× le tarif Opus (cf. M4)

💡 Le cas rare de la montée de génération gratuite. Opus 5 (24 juillet 2026) arrive au tarif exact d'Opus 4.8. En optimisation de coûts, on raisonne d'habitude « nouveau modèle = plus cher, j'attends » ; ici la bonne décision est l'inverse — migrer immédiatement, puisque la performance monte à budget constant. Le seul arbitrage qui subsiste est Opus 5 vs Sonnet 5 (5 $/25 $ contre 2 $/10 $ en promo), et il se tranche par tâche, pas par principe.

🧮 Piège tokenizer Sonnet 5 (30 juin 2026). Sonnet 5 utilise un nouveau tokenizer : le même contenu compte 1,0 à 1,35× plus de tokens que sur Sonnet 4.6. Pour comparer les coûts entre générations, raisonnez en $ par tâche, jamais en tokens — un prix au token plus bas peut être partiellement mangé par une tokenisation plus dense.

Fast mode (mis à jour juillet 2026). Le fast mode (sortie accélérée, même modèle) est facturé $10 / $50 par MTok — soit 2× le tarif standard. Depuis la v2.1.219, il s'applique à Opus 5 et Opus 4.8 ; Opus 4.7 en a été retiré. À intégrer dans l'arbitrage latence/coût : payer le fast mode peut être rentable sur une boucle interactive, jamais sur du batch. S'active dans Claude Code avec /fast.

🧮 Coïncidence tarifaire à ne pas confondre. Le fast mode d'Opus 5 (10 $ / 50 $) coûte exactement le prix standard de Fable 5. Ce sont deux dépenses de nature différente : l'une achète de la vitesse sur un modèle donné, l'autre achète un modèle plus capable. Si votre problème est la latence, le fast mode ; si c'est la difficulté de la tâche, Fable 5. Payer 10 $/50 $ sans savoir laquelle des deux contraintes vous limite, c'est la façon la plus courante de gaspiller un budget en 2026.

Calcul coût réel par request

Formule simple :

Coût = (input_tokens × price_input + output_tokens × price_output) / 1_000_000

Exemple : 2 000 tokens input (prompt + contexte) + 500 tokens output (réponse)

Opus : (2000 × 0.000005 + 500 × 0.000025) = 0.010 + 0.0125 = 0.0225 $ par requête
Sonnet : (2000 × 0.000003 + 500 × 0.000015) = 0.006 + 0.0075 = 0.0135 $ par requête
Haiku : (2000 × 0.000001 + 500 × 0.000005) = 0.002 + 0.0025 = 0.0045 $ par requête

Conclusion : pour cette requête, Opus = 5 × plus cher que Haiku, 1,67 × plus cher que Sonnet.

Impact output dans le coût global

Pour une requête type (2 k input, 500 output), l'output représente 55 % du coût Opus, 55 % Sonnet, 55 % Haiku (le ratio output/input reste 5× partout). La différence : le multiplicateur absolu. Réduire l'output de 100 tokens sur 10 k requêtes (= 1 M tokens) économise 25 $ sur Opus, 15 $ sur Sonnet, 5 $ sur Haiku.

Insight clé : si ton coût est dominé par output (résumés longs, code généré), tu dois réduire output tokens, pas juste switcher vers Haiku (qui reste cher si tu génères 2 k output).

Adaptive thinking & effort : le levier coût/qualité 2026

Avant même de changer de modèle, deux paramètres pilotent le coût. Ils ont remplacé l'ancien budget_tokens (qui renvoie désormais une erreur HTTP 400 sur Opus 4.7/4.8 si envoyé) :

  • Adaptive thinking (thinking: {type: "adaptive"}) : Claude décide seul quand et combien réfléchir — plus de budget de tokens à régler à la main.
  • effort (output_config: {effort: "low" | "medium" | "high" | "xhigh" | "max"}) : le principal levier coût de 2026. Il règle la profondeur de raisonnement ET le nombre d'appels d'outils / la verbosité.
client.messages.create(
    model="claude-opus-4-8",
    max_tokens=4096,
    thinking={"type": "adaptive"},
    output_config={"effort": "medium"},   # souvent le meilleur compromis coût/qualité
    messages=[...],
)
effortQuandEffet
lowClassification, tâches scopées, latence-sensibleMin tokens, réponses directes
mediumLa plupart des casBon compromis (souvent le sweet spot)
highTravail intelligence-sensible (défaut)+ de raisonnement
xhighCoding/agentique (défaut de Claude Code)Encore + d'outils/raisonnement
maxOpus uniquement — correction critiquePlafond (peut sur-réfléchir)

Réflexe coût : baisser l'effort d'un cran (ex. highmedium) réduit fortement les tokens de thinking et la longueur des réponses, souvent sans perte perceptible sur les tâches simples. À tester avant de changer de modèle. Pour borner une boucle agentique entière, voir task_budget plus bas.

Quand chaque modèle est réellement le moins cher

Cas 1 : Classification simple (Haiku)

Tâche : catégoriser 1 M emails par sentiment (5 catégories).

Setup : system prompt 300 tokens + email 200–400 tokens = 500–700 input, réponse 1–5 tokens output.

Coût Haiku : 1M × (500 × 0.000001 + 3 × 0.000005) = 500 + 15 ≈ 515 $ par 1M emails
Coût Sonnet : 1M × (500 × 0.000003 + 3 × 0.000015) = 1500 + 45 ≈ 1545 $ par 1M
Coût Opus : 1M × (500 × 0.000005 + 3 × 0.000025) = 2500 + 75 ≈ 2575 $ par 1M

Verdict : Haiku ≈ 5 × moins cher que Opus (et 3 × moins cher que Sonnet). Switch obligatoire.

Cas 2 : Reasoning avec output court (Sonnet)

Tâche : analyser 50 k documents (2 k tokens chacun) pour identifier 10 points clés (output ~300 tokens).

Coût Haiku : 50k × (2000 × 0.000001 + 300 × 0.000005) = 50k × 0.0035 = 175 $ + hallucinations potentielles (Haiku moins bon reasoning)
Coût Sonnet : 50k × (2000 × 0.000003 + 300 × 0.000015) = 50k × 0.0105 = 525 $ + haute qualité
Coût Opus : 50k × (2000 × 0.000005 + 300 × 0.000025) = 50k × 0.0175 = 875 $

Verdict : Sonnet est 3 × plus cher que Haiku, mais qualité 3–4 × supérieure pour reasoning. ROI Sonnet.

Cas 3 : Synthèse document long avec output long (Opus ou Sonnet)

Tâche : résumer 30 documents légaux (10 k tokens chacun) en dossier cohérent (2 k tokens output).

Coût Sonnet : 30 × (10 000 × 0.000003 + 2 000 × 0.000015) = 30 × 0.06 = 1,80 $
Coût Opus : 30 × (10 000 × 0.000005 + 2 000 × 0.000025) = 30 × 0.10 = 3,00 $

Verdict : Opus 1,67 × plus cher, mais pour synthèse légale, 1–2 % qualité supérieure mérite le coût. ROI Opus si erreur = coûteux (relecture avocate).

Règle pratique : Haiku par défaut (sauf si quality loss > 5 %). Sonnet si output > 500 tokens ou reasoning complexe. Opus seulement si erreur est très coûteuse (légal, sécurité) ou reasoning multi-step critique.

Prompt caching : cache_control, breakpoints, éphémère (5 min vs 1 h)

Prompt caching économise jusqu'à 90 % sur input en stockant partie du contexte (system, tools, documents) côté Anthropic. Coût write = +25 % du coût read, gains rapides après 1.3 appels.

Anatomie caching

{
  "system": [
    {
      "type": "text",
      "text": "Tu es analyste de CVs. [ruleset long 5 k tokens]",
      "cache_control": {"type": "ephemeral"}
    }
  ],
  "tools": [
    {
      "name": "eval_cv",
      "description": "[100 tokens]",
      "input_schema": {...},
      "cache_control": {"type": "ephemeral"}
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "CV à analyser : [document 500 tokens]"
        },
        {
          "type": "text",
          "text": "Retourne JSON structuré",
          "cache_control": {"type": "ephemeral"}
        }
      ]
    }
  ]
}

Cache hit : sur appel 2+, input = juste le CV nouveau (500 tokens), pas les 5.6 k du system + tools + prompt. Économie : (5.6 k / 6.1 k) = 91 % input.

Durée de cache : éphémère (5 min par défaut)

Par défaut, cache Anthropic = 5 minutes. Suffit pour :

  • Batch de 10–20 requêtes séquentielles (API call every 10–20 sec)
  • Session utilisateur (chatbot = 5 min timeout)
  • Pipeline workflow court (< 5 min)
# Exemple : batch CVs dans une loop
for cv in cvs_list[0:100]:  # 100 CVs, chacun 10 sec de traitement
    response = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=500,
        system=[
            {
                "type": "text",
                "text": "SYSTEM PROMPT [5 k tokens]",
                "cache_control": {"type": "ephemeral"}
            }
        ],
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": f"Analyse ce CV:\n{cv}",
                        "cache_control": {"type": "ephemeral"}
                    }
                ]
            }
        ]
    )
    # Cache hit sur appel 2–100 : system prompt réutilisé, 0 coût input system

Éphémère vs 1 h (GA depuis août 2025)

La durée de cache 1 heure est disponible en GA depuis août 2025 (ce n'est plus une beta). Le coût write = 2 × le coût de base, tandis que le coût read = 0.1 × le coût de base. Donc, le coût write est 20 × le coût read (non 2 ×) — contre +25 % pour le cache 5 min. Use case : même prompt réutilisé par plusieurs utilisateurs ou sessions.

Cas : customer support
- Jour 1 08:00 : Agent 1 crée cache de system prompt + knowledge base (50 k tokens)
- Jour 1 08:15 : Agent 2 pose question → cache hit (2 min après création)
- Jour 1 13:00 : Agent 3 pose question → cache hit (5 h après création)
- Jour 2 14:00 : Agent 4 pose question → cache miss (> 1 h), new cache

Économie vs classique :

Classique : 4 agents × 50 k input tokens × $0.000005 (Opus) = 1 $ par jour
Cache 1 h : 1 × write + 3 × cache read = (50k × 1.25 × 0.000005) + (3 × 50k × 0.1 × 0.000005)
          = 0.3125 + 0.075 = 0.39 $ par jour

Gain : ~2,6 × économie sur 1 j. Pas révolutionnaire, mais utile pour support 24/7 ou pipelines réutilisés.

Nouveauté API 2026 : instructions system dans messages (cache préservé)

Avec Opus 4.8, la Messages API accepte désormais des entrées system à l'intérieur du tableau messages (et plus seulement dans le champ system racine). Intérêt FinOps : on peut injecter une nouvelle instruction en cours de tâche sans casser le préfixe mis en cache. Avant, modifier le system prompt invalidait tout le cache du préfixe ; maintenant l'instruction tardive s'ajoute après le préfixe stable, qui reste un cache hit.

client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": [
            {"type": "text", "text": "[gros contexte stable]",
             "cache_control": {"type": "ephemeral"}}]},          # ← reste caché
        {"role": "system", "content": "Recentre-toi sur la TVA uniquement."},  # ← instruction tardive, n'invalide pas le cache
        {"role": "user", "content": "Analyse cette facture."},
    ],
)

Côté Claude Code : /cd change de dossier sans purger le cache (v2.1.169)

Même logique côté CLI. Auparavant, changer de répertoire de travail en cours de session relançait le contexte et invalidait le préfixe mis en cache. La commande /cd <dir> (depuis v2.1.169) change le working directory en préservant le cache : on navigue dans un monorepo (passer de apps/web à apps/api) sans repayer l'amorçage du préfixe. Réflexe FinOps sur les longues sessions multi-dossiers.

Status line de Claude Code affichant l'usage du contexte en pourcentage
La status line affiche l'usage du contexte en direct (Ctx: … %) : un repère immédiat pour surveiller la fenêtre et déclencher /compact avant saturation.

Model routing : architecture décision + seuils

Repli automatique sur overload (Claude Code v2.1.166). Distinct du routing par complexité : le setting fallbackModel (settings.json) prend jusqu'à 3 modèles de repli essayés en séquence quand le modèle principal est surchargé (529) ou retourne une autre erreur serveur non-retryable. Les erreurs de rate-limit (429) ne déclenchent PAS le fallback—elles sont gérées par les mécanismes de retry normaux. C'est de la résilience (rester disponible), pas de l'optimisation de coût (router selon la difficulté). Les deux se combinent : on route par complexité et on déclare un repli.

Idée : analyser complexité d'une requête avec Haiku rapide, escalader vers Sonnet/Opus si nécessaire. Voici l'architecture :

Chargement du schéma…

Architecture routeur 3 étages (économise 10-60% coûts)

Routeur 3 étages

Input utilisateur
  ↓
Stage 1 (Haiku) : Classification complexité en 2 sec
  ├─ Complexité BASSE (scoring < 0.4) → Haiku complet
  ├─ Complexité MOYENNE (0.4–0.7) → Sonnet
  └─ Complexité HAUTE (> 0.7) → Opus

Classification Haiku (500 tokens, output 50 tokens)

def classify_complexity(user_input):
    """Retourne score 0–1 de complexité."""
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=100,
        system="""Tu analyses requête utilisateur et retournes score JSON:
        {
          "complexity_score": 0–1,
          "reason": "pourquoi",
          "recommended_model": "haiku|sonnet|opus"
        }
        
        Règles :
        - Score < 0.3 : requête simple, répond directement. Ex: "Catégorise cet email"
        - Score 0.3–0.7 : reasoning nécessaire. Ex: "Propose stratégie marketing pour PME tech"
        - Score > 0.7 : multi-step reasoning, contexte long. Ex: "Merge 5 documents légaux + propose roadmap conformité"
        """,
        messages=[
            {
                "role": "user",
                "content": user_input
            }
        ]
    )
    
    return json.loads(response.content[0].text)

# Exécution réelle
score = classify_complexity("Résume cet email en 50 mots")
# {"complexity_score": 0.1, "reason": "tâche simple, pas de reasoning", "recommended_model": "haiku"}

# Coûts routing complet :
# - Classification Haiku : (500 × 0.000001 + 50 × 0.000005) = $0.00075
# - Haiku exécution (si complexité basse) : (700 × 0.000001 + 200 × 0.000005) = $0.0017
# - Total : ~$0.0025 par requête
# vs
# - Opus direct : (2000 × 0.000005 + 500 × 0.000025) = $0.0225 (≈9× plus cher)

Seuils calibrés par domaine

DomaineHaiku (< 0.4)Sonnet (0.4–0.7)Opus (> 0.7)
Support client"Catégorise problème", "Approche FAQ""Explique technique", "Propose solution""Cas légal complexe", "Escalade exec"
RH/Recrutement"Trier CVs par compétence""Évaluer soft skills""Décision embauche"
Marketing"Extraire entités""Générer copy court""Stratégie long-term"
Analyse docs"Indexer documents""Résumer chapitre""Synthèse multi-doc cross-domain"

Piège : seuils sont contexte-spécifiques. Classification Haiku peut échouer sur requête ambiguë. Solution : humain révise 50 cas de routing erroné/mois et recalibre seuils.

Batch API : trade latence vs coût (-50 %)

Batch API = envoi liste de requêtes asynchrone, exécution groupée, réduction coûts 50 %. Délai : 24 h max (typiquement 1–5 h).

Quand utiliser Batch

  • ✅ Reportings quotidiens (données du jour, délai 6 h acceptable)
  • ✅ Pre-processing gros volumes (indexation corpus, classification documents)
  • ✅ Evals de modèles (test 1 k prompts, délai non-critique)
  • ❌ Support client temps-réel (latence 24 h inacceptable)
  • ❌ Chatbot interactif (utilisateur attend réponse < 10 sec)

Format Batch (JSONL)

{"custom_id": "request-1", "params": {"model": "claude-opus-4-8", "max_tokens": 1024, "system": "Tu es analyste", "messages": [{"role": "user", "content": "Analyse cette donnée: [data_1]"}]}}
{"custom_id": "request-2", "params": {"model": "claude-opus-4-8", "max_tokens": 1024, "system": "Tu es analyste", "messages": [{"role": "user", "content": "Analyse cette donnée: [data_2]"}]}}

Coûts comparés

Exemple : 10 k requêtes, Opus, 2 k input + 500 output chacune.

API normal : 10k × (2000 × 0.000005 + 500 × 0.000025) = 10k × 0.0225 = 225 $ + temps 5–10 min
Batch API : 10k × 0.0225 × 0.5 = 112,50 $ + temps 1–5 h

Économie : -50 % (seulement tarif, pas CPU)

Implémentation Python

import anthropic
import json

client = anthropic.Anthropic(api_key="...")

# 1. Préparer requêtes en JSONL
requests = []
for i, data in enumerate(my_data_list):  # 10 k items
    requests.append({
        "custom_id": f"request-{i}",
        "params": {
            "model": "claude-opus-4-8",
            "max_tokens": 1024,
            "messages": [
                {
                    "role": "user",
                    "content": f"Analyse: {data}"
                }
            ]
        }
    })

# 2. Upload file
batch_input_file = client.beta.files.upload(
    file=("batch.jsonl", "\n".join(json.dumps(r) for r in requests).encode()),
    betas=["batch-2024-09-24"],
)

# 3. Submit batch
batch = client.beta.batches.create(
    input_file_id=batch_input_file.id,
    endpoint="/v1/messages",
    timeout_minutes=1440,  # 24 h
    betas=["batch-2024-09-24"],
)

# 4. Poll status
while batch.processing_status in ["queued", "in_progress"]:
    batch = client.beta.batches.retrieve(batch.id, betas=["batch-2024-09-24"])
    print(f"Status: {batch.processing_status}")
    time.sleep(30)

# 5. Retrieve results
result_file = client.beta.files.retrieve_content(batch.result_file_id, betas=["batch-2024-09-24"])
results = [json.loads(line) for line in result_file.text.strip().split("\n")]

Truncation : quand laisser tomber contexte ancien

Si ton prompt fait 100 k tokens et tu dois réduire coûts, deux options :

  1. Cache (garde tout, cache après 1 hit)
  2. Truncate (jette contexte ancien, garde pertinent)

Stratégies truncation

Option 1 : Fenêtre glissante (Keep last N tokens)

def truncate_context(messages, max_tokens=50000):
    """Garde messages récents jusqu'à max_tokens."""
    total = 0
    kept = []
    for msg in reversed(messages):  # Commencer par récent
        msg_tokens = estimate_tokens(msg)  # Rough estimate
        if total + msg_tokens <= max_tokens:
            kept.append(msg)
            total += msg_tokens
        else:
            break
    return list(reversed(kept))

Use case : chatbot où utilisateur veut seulement les 10 derniers échanges, pas l'historique complet (12 mois).

Option 2 : Résumé progressif (Keep summary + recent)

def progressive_summary(messages, max_tokens=50000):
    """Garde résumé ancien + messages récents."""
    if len(messages) < 10:
        return messages  # Pas besoin résumé
    
    old_messages = messages[:-5]  # Tout sauf 5 derniers
    recent = messages[-5:]
    
    # Résumer ancien avec Haiku (cheap)
    summary = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=500,
        messages=[
            {
                "role": "user",
                "content": f"Résume en 500 tokens:\n{format_messages(old_messages)}"
            }
        ]
    ).content[0].text
    
    return [
        {"role": "system", "content": f"HISTORIQUE RÉSUMÉ:\n{summary}"},
        *recent
    ]

Use case : support client longue durée (6 mois), tu veux garder contexte mais réduire tokens. Pertes qualité : ~5 % (rares détails oubliés du résumé).

Contrôle des boucles agentiques : task_budget, compaction, context editing

Pour un agent qui enchaîne des dizaines d'appels d'outils, trois leviers natifs bornent le coût là où effort et caching ne suffisent plus :

  • Task budgets (beta Opus 4.7/4.8, header task-budgets-2026-03-13) : output_config: {task_budget: {type: "tokens", total: N}} donne au modèle un compteur visible de tokens pour toute la boucle ; il s'auto-modère et conclut proprement en approchant la limite. ≠ max_tokens (plafond dur par réponse, dont le modèle n'a pas conscience). Minimum 20 000.
  • Compaction serveur (beta, header compact-2026-01-12) : quand la conversation approche la fenêtre, l'API résume automatiquement l'historique ancien côté serveur. Réintégrez response.content (pas juste le texte) à chaque tour, sinon l'état de compaction est perdu.
  • Context editing : élague les anciens tool_result / blocs de thinking devenus inutiles (seuils configurables) — garde le transcript léger sans résumer.
client.beta.messages.create(
    betas=["task-budgets-2026-03-13"],
    model="claude-opus-4-8",
    max_tokens=8000,
    output_config={"effort": "high", "task_budget": {"type": "tokens", "total": 128_000}},
    messages=[...],
)

Combo recommandé pour un agent long : effort adapté + task_budget (borne globale) + compaction (survie au-delà de la fenêtre) + caching (le préfixe stable reste à 0,1×). Voir aussi M5 pour le grand contexte.

Observabilité coûts : Helicone vs Langfuse

Pour tracker coûts réels et optimiser, deux outils open-source/cloud :

Helicone

# Installation
pip install helicone

# Usage
from helicone import Helicone

client = anthropic.Anthropic(
    api_key="...",
    base_url="https://api.helicone.ai/v1",
    default_headers={
        "Helicone-Auth": f"Bearer {HELICONE_API_KEY}"
    },
)

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Bonjour"}]
)

Dashboard Helicone : coûts par modèle, latence, token count, error rate. Gratuit jusqu'à 10 k requêtes/mois (soit ~333 requêtes/jour).

MétriqueGranularitéAlertes
CoûtsPar modèle, par jour, totalBudget cap
LatencePercentile 50/95/99Seuil temps réponse
TokensInput/output ratioAnomalies
ErrorsRate par endpointSeuil tolérance

Langfuse

# Installation
pip install langfuse

# Usage
from langfuse.openai import OpenAI
from anthropic import Anthropic

langfuse_client = Langfuse(
    secret_key="sk_...",
    public_key="pk_..."
)

# Wrapper custom pour Claude (Langfuse = natif OpenAI, Claude = plugin)
client = Anthropic(api_key="...")

def claude_with_trace(messages, model="claude-opus-4-8", **kwargs):
    trace = langfuse_client.trace(
        name="claude-call",
        metadata={"model": model}
    )
    
    response = client.messages.create(
        model=model,
        messages=messages,
        **kwargs
    )
    
    trace.generation(
        name="claude-generation",
        model=model,
        input=messages,
        output=response.content[0].text,
        usage={
            "input_tokens": response.usage.input_tokens,
            "output_tokens": response.usage.output_tokens
        }
    )
    
    return response

Dashboard Langfuse : coûts + latence + quality scoring (si tu as labels). Freemium : 5 k events/mois.

Cas pratique : audit d'un workflow

Tu exploites Claude Opus pour générer 20 k emails/mois via API. Voici comment réduire les coûts :

Pièces de monnaie et billets de banque empilés, symbolisant l'économie et l'optimisation des coûts
Budget IA : réduction progressive des coûts sans compromis sur la qualité

Chargement du schéma…

Réduction progressive 200$ → 46$ (gain -77% coûts, loss 3% qualité)

Baseline

Workflow : /draft-email <customer_data>
Input : 1 k tokens (customer profile + product context + system prompt)
Output : 200 tokens (email body)
Fréquence : 20 k appels/mois
Modèle actuel : Opus

Coût/mois = 20k × (1000 × 0.000005 + 200 × 0.000025) = 20k × 0.010
          = 200 $/mois

Étape 1 : Audit qualité Haiku

Tester Haiku sur 100 emails réels. Métrique : "Accepté sans modification par agent" (baseline Opus = 92 %).

Haiku result : 71 % accepté sans modif, 21 % petit fix, 8 % rejet
Verdict : Haiku = -21 % quality, pas acceptable (seuil tolérance = 5 %)

Étape 2 : Essayer Sonnet

Sonnet result : 89 % accepté, 9 % petit fix, 2 % rejet
Verdict : Sonnet = -3 % quality, acceptable

Coût Sonnet/mois = 20k × (1000 × 0.000003 + 200 × 0.000015) = 20k × 0.006
                  = 120 $/mois

Économie : 200 → 120 $ = -40 % (loss 3 % quality)

Étape 3 : Ajouter routing

Ajouter stage 1 Haiku classification (est-ce que requête est "complexe"?) :

Requête simple (email relance standard) → Haiku complet
Requête complexe (email vente de suite produit nouveau) → Sonnet
# Classification 100 requêtes passées
- 40 % simple → Haiku
- 60 % complexe → Sonnet

Nouveau coût = (0.4 × 20k) × coût_haiku + (0.6 × 20k) × coût_sonnet + 20k × coût_classif_haiku
             = 8k × 0.002 + 12k × 0.006 + 20k × 0.00075
             = 16 $ + 72 $ + 15 $ = 103 $/mois
             (vs 120 $ sans routing)

Quality : (0.4 × 92 Haiku) + (0.6 × 89 Sonnet) = 90.2 %

Verdict : routing complexe pour un gain modeste (~14 %). Skip (le caching fait mieux et plus simple).

Étape 4 : Caching system prompt

System prompt = 500 tokens (company rules, tone, product knowledge), réutilisé dans chaque email.

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=200,
    system=[
        {
            "type": "text",
            "text": """Tu es rédacteur d'emails commerciaux [company rules, tone, product knowledge, 500 tokens]""",
            "cache_control": {"type": "ephemeral"}
        }
    ],
    messages=[
        {
            "role": "user",
            "content": f"Client: {customer_data}\nGénère email"
        }
    ]
)

Impact :

  • Call 1 : 1 k input (500 system + 500 customer)
  • Call 2–20k : 500 input (juste customer, system cachée) + 200 output
Coût ≈ 1 × (1000 × 0.000003 + 200 × 0.000015)                            [call 1, cache write]
     + 19999 × (500 × 0.000003 × 0.1 + 500 × 0.000003 + 200 × 0.000015)  [cache hit : system caché, customer frais]
     = 0.006 + 19999 × (0.00015 + 0.0015 + 0.003)
     = 0.006 + 19999 × 0.00465
     ≈ 93 $/mois

Économie vs Sonnet sans cache : 120 → 93 $ = -22 %

Étape 5 : Batch processing (non-temps-réel)

Si tu dois générer 20 k emails, peux tu attendre 2 h pour résultat?

OUI → Batch API (20k requêtes, délai 2 h) : coût × 0.5
Nouveau coût = 93 × 0.5 = 46,50 $/mois

NON → Garder real-time (Sonnet + cache) = 93 $/mois

Résumé audit

KnobAvantAprèsGainQuality loss
Baseline$200 Opus0 %
Switch Sonnet$120 Sonnet-40 %3 %
+ Caching$93 Sonnet + cache-22 %3 %
+ Batch$46,50 Batch Sonnet + cache-50 %3 %
Scenario final$200$46,50 (batch) ou $93 (real-time)-77 % ou -53 %3 %

Décision : si délai 2 h acceptable (émail envoyé le lendemain matin) → Batch, coût $46,50. Sinon → Sonnet + cache, coût $93. Gain = 2–4 × par rapport baseline naïf.

Atelier : réduction 60–90 % (90 min)

Vous apportez un workflow Claude existant (production ou prototype). Vous audit et optimisez. Processus en 5 étapes :

Chargement du schéma…

Atelier 90 min : optimiser votre workflow

Étape 1 (15 min) : Baseline measurement

Documenter :

Workflow : [nom]
Modèle actuel : [Opus/Sonnet/Haiku]
Volume/mois : [N requêtes]
Input tokens (avg) : [?]
Output tokens (avg) : [?]
Coût/mois : [$ calculé]
Quality metric : [%, ou "not measured"]
Latency requirement : [temps réel / batch OK]

Exemple :

Workflow : CV ranking
Modèle : Opus
Volume : 5 k CVs/mois
Input : 2 k tokens (system + CV)
Output : 300 tokens (scoring JSON)
Coût/mois : 5k × (2000 × 0.000005 + 300 × 0.000025) = 5k × 0.0175 = 87,50 $/mois
Quality : 85 % agreement with HR manual ranking
Latency : Batch OK (RH reçoit ranking le matin)

Étape 2 (20 min) : Tester Sonnet

Sur 50 samples, comparer Sonnet vs Opus.

Résultat : 83 % agreement (vs 85 % Opus) = -2 % loss
Coût Sonnet : 5k × (2000 × 0.000003 + 300 × 0.000015) = 5k × 0.0105 = 52,50 $/mois
Économie : -40 %, loss acceptable

Étape 3 (15 min) : Ajouter caching

Caching system prompt (1 k tokens) :

Coût ≈ 1 × (2000 × 0.000003 + 300 × 0.000015)                            [call 1]
     + 4999 × (1000 × 0.000003 × 0.1 + 1000 × 0.000003 + 300 × 0.000015)  [cache hit : system caché]
     = 0.0105 + 4999 × (0.0003 + 0.003 + 0.0045)
     = 0.0105 + 4999 × 0.0078
     ≈ 39 $/mois

Économie vs Sonnet : 52,50 → 39 = -26 %

Étape 4 (20 min) : Batch processing

Délai acceptable ? OUI → Batch API (-50 % coût).

Coût final = 39 × 0.5 = 19,50 $/mois
Total gain = 87,50 → 19,50 $ = -78 % (loss 2 % quality)

Étape 5 (20 min) : Document résultats

Tableau final + recommendations :

| Stage | Cost | Quality | Latency | Recommendation |
|---|---|---|---|---|
| Current (Opus) | $87.50 | 85 % | 10 sec | Baseline |
| Switch Sonnet | $52.50 | 83 % | 10 sec | Do it now |
| + Cache | $39 | 83 % | 10 sec | Easy win |
| + Batch | $19.50 | 83 % | 2 h | If batch-OK |

**Recommendations** :
1. [IMMEDIATE] Switch to Sonnet (easy, -40 %, no quality loss)
2. [WEEK 1] Add caching for system prompt (code change, -26 %)
3. [WEEK 2] Test Batch API (setup + polling, -50 %, requires 2 h delay)
4. [ONGOING] Monitor quality on 100 samples/month (ensure no drift)

Pour aller plus loin