Skip to content
··8 min de lecture

Un seul paramètre IA m'a coûté 54 $/mois

Je pensais que ma migration vers Cloud Run était parfaite — jusqu'à ce qu'un seul paramètre IA (temperature réglée à 0,7 au lieu de 0) provoque 30 % d'appels API en échec et me coûte 54 $/mois en tokens gaspillés.

J'ai fait confiance à Claude pour m'aider à migrer d'AWS Lambda vers Google Cloud Run. La migration s'est passée parfaitement — services déployés, workflows exécutés, utilisateurs satisfaits. Puis j'ai vérifié nos factures API et j'ai failli tomber de ma chaise.

*Ceci est la partie 3 de ma série d'ingénierie DIALØGUE. Si tu les as ratées : [Partie 1 : Introduction à DIALØGUE] et [Partie 2 : De la publicité à l'ingénierie] couvrent les fondements.*

Voici l'histoire de ce qui arrive quand tu laisses une IA écrire du code de production sans être explicite sur les contraintes de production. Spoiler : "faire en sorte que ça marche" et "faire en sorte que ce soit prêt pour la production" sont des requêtes très différentes.

La migration qui s'est trop bien passée

Après des mois à me battre avec AWS Lambda (cold starts, limites des layers, tout le reste), j'ai décidé de tout migrer vers Google Cloud Run. En développeur pragmatique (comprends : fainéant), j'ai recruté Claude comme pair programmeur.

"Aide-moi à migrer ces fonctions Lambda vers Cloud Run", ai-je dit. "Voici le code existant."

Claude a livré magnifiquement. Des Dockerfiles propres, des configurations de services correctes, des Cloud Workflows fonctionnels. La migration a pris seulement une journée au lieu des semaines que j'attendais. J'étais ravi !

Tout s'est déployé sans accroc. Les services ont démarré rapidement. Les utilisateurs créaient des podcasts sans problème. Succès, non ?

Puis j'ai remarqué quelque chose d'étrange dans nos logs :

```
[ERROR] Segment generation failed: Unexpected token in JSON
[RETRY] Attempting segment generation again...
[SUCCESS] Segment generated successfully
```

Environ 30 % de nos appels IA échouaient au premier essai mais réussissaient à la relance. Pas la fin du monde — ma logique de retry fonctionnait ! Les utilisateurs n'ont remarqué aucun problème. Mais bon sang, ces appels API supplémentaires s'accumulaient.

L'enquête : blâmer la migration ?

Ma première pensée était que quelque chose s'était mal passé pendant la migration. Peut-être que le nouvel environnement Cloud Run était différent ? Des problèmes de réseau dans le container ? J'ai passé des heures à comparer les configurations AWS et GCP.

Tout semblait identique. Mêmes prompts, même logique de retry, même gestion des erreurs. Alors pourquoi obtenions-nous soudainement des réponses JSON malformées ?

J'ai alors commencé à comparer le code réel. Voici ce que j'ai trouvé :

Version AWS Lambda (qui fonctionnait bien depuis des mois) :

```python
response = anthropic.messages.create(
      model="claude-3-7-sonnet-20250219",
      temperature=0,  # Deterministic for JSON
      response_format=\{"type": "json_object"\},  # JSON mode
      system="You are a JSON generation assistant. Output only valid JSON.",
      messages=[\{"role": "user", "content": prompt\}]
)
```

Version GCP Cloud Run (migration de Claude) :

```python
response = anthropic.messages.create(
    model="claude-3-7-sonnet-20250219",
    temperature=0.7,  # <-- Attends, quoi ?
    messages=[\{"role": "user", "content": prompt\}]
)
```

Et voilà. Temperature 0,7.

"Mais c'est une valeur par défaut raisonnable !" pourrais-tu dire. Et tu aurais raison. Pour l'écriture créative, l'exploration, le brainstorming — 0,7 est parfaitement sensé. Mais pour la génération de JSON structuré ? C'est un désastre.

Le smoking gun : le JSON créatif

Après avoir ajouté des logs détaillés pour capturer les réponses IA réelles, j'ai trouvé exactement ce qui se passait. Voici ce que Claude retournait avec une temperature de 0,7 :

```
Here's the podcast segment you requested:

\{
  "title": "The Rise of AI Podcasting",
  "content": "Welcome back, listeners! Today we're diving into something really fascinating...",
  "duration": 120
\}

I hope this segment captures what you were looking for!
```

Tu vois le problème ? Claude était créatif avec le format de réponse. Parfois juste du JSON, parfois du JSON avec des commentaires utiles, parfois du JSON enveloppé dans des blocs de code markdown. Avec une temperature de 0,7, il improvisait comme un musicien de jazz alors que j'avais besoin d'un métronome.

Le point aveugle du pair programming avec IA

Voilà la chose avec le travail avec une IA comme pair programmeur : elle est incroyablement bonne pour faire fonctionner le code, mais elle n'optimise pas nécessairement pour les contraintes de production à moins que tu ne le demandes spécifiquement.

Quand j'ai dit "migre cette fonction Lambda vers Cloud Run", Claude s'est concentré sur les exigences de migration :

- ✅ La faire fonctionner sur Cloud Run

- ✅ Gérer les mêmes entrées et sorties

- ✅ Maintenir la même fonctionnalité

- ❌ Optimiser pour l'efficacité en production

Claude a choisi temperature 0,7 parce que c'est une "valeur par défaut raisonnable" pour les applications IA. Et c'est le cas ! Pour la plupart des cas d'usage, 0,7 te donne un bon équilibre entre créativité et cohérence.

Mais voici ce que j'ai appris : **l'IA ne connaît pas tes contraintes de production spécifiques à moins que tu ne le lui dises.**

Mon code AWS original utilisait temperature 0 ET le mode JSON parce que j'avais appris (à la dure) que la génération de JSON nécessite à la fois des sorties déterministes et un formatage explicite. Mais pendant la migration, je n'ai jamais dit explicitement "c'est pour la génération de données structurées" ou "maintiens toutes les optimisations spécifiques au JSON."

Alors Claude a écrit du code parfaitement fonctionnel avec des valeurs par défaut sensées. Le problème n'était pas l'IA — c'était mes exigences incomplètes.

Le correctif : être précis avec l'IA

Une fois que j'ai identifié le problème, je suis retourné voir Claude avec de meilleures exigences :

"Aide-moi à corriger ce code. C'est pour la génération JSON en production. J'ai besoin d'une fiabilité à 100 %, zéro créativité. Utilise temperature 0 et toutes les autres optimisations pour les données structurées."

Claude a immédiatement suggéré :

```python
response = anthropic.messages.create(
    model="claude-3-5-sonnet",
    temperature=0,  # Deterministic outputs
    response_format=\{"type": "json_object"\},  # JSON mode
    system="You are a JSON generation assistant. Output only valid JSON.",
    messages=[\{"role": "user", "content": prompt\}]
)
```

Attends, Claude a oublié le mode JSON que nous avions ! (C'est ce qui arrive quand tu ne mentionnes pas explicitement chaque exigence de production pendant la migration !)

Le taux de succès a bondi de 70 % à 99,9 %. Les 0,1 % restants ? Des timeouts réseau. Je ne peux pas blâmer Claude pour ça.

La différence ? Cette fois, j'étais explicite sur les contraintes de production. Je n'ai pas juste demandé une migration — j'ai demandé du code optimisé pour la production, axé sur la fiabilité.

Le vrai coût des valeurs par défaut "raisonnables"

Laisse-moi décomposer ce que ce réglage de temperature "raisonnable" nous a vraiment coûté :

- **Générations de podcasts quotidiennes** : ~200

- **Taux d'échec** : 30 % nécessitant des relances

- **Appels API supplémentaires par jour** : 60 appels en échec nécessitant des relances

- **Gaspillage mensuel** : ~1 800 appels API inutiles

- **Tarification Claude 3.7 Sonnet** : 3 $ input + 15 $ output par million de tokens

- **Tokens moyens par appel** : ~2 000 input + 1 500 output

- **Coût par relance** : ~0,03 $ par tentative en échec

- **Surcoût mensuel** : ~54 $ en appels API gaspillés

Mais le vrai coût n'était pas seulement les 54 $/mois. Chaque relance ajoutait 3 à 5 secondes au temps de génération. Les utilisateurs attendaient plus longtemps, mes instances Cloud Run démarraient plus souvent, et je brûlais mon quota plus vite.

Le comble ? Tout ça s'est passé parce que j'avais fait confiance à l'IA pour prendre des décisions de production sans lui donner le contexte de production. Cas classique de "ça fonctionne" vs "ça fonctionne efficacement".

Ce que j'ai appris sur le pair programming avec IA

1. Sois explicite sur les exigences de production

"Fais-le fonctionner" te donne du code fonctionnel. "Fais-le fonctionner efficacement en production avec ces contraintes" te donne du code optimisé. L'IA est douée pour résoudre le problème que tu décris, pas le problème que tu as en tête.

2. L'IA utilise des valeurs par défaut "raisonnables", pas "optimales"

Temperature 0,7 est raisonnable pour la plupart des applications IA. Mais les systèmes de production ont souvent besoin d'optimisations spécifiques comme temperature 0 ET le mode JSON. L'IA ne les préservera pas à moins que tu ne les mentionnes explicitement.

3. La revue de code s'applique aussi au code généré par l'IA

Le fait que l'IA l'ait écrit ne signifie pas qu'il est prêt pour la production. J'aurais dû le détecter lors de la revue de code, mais j'étais tellement concentré sur le fait que la migration fonctionnait que je n'ai pas audité les paramètres.

4. Le contexte compte plus que tu ne le penses

Mon code AWS original avait temperature 0 ET le mode JSON pour de bonnes raisons — apprises par une expérience douloureuse. Pendant la migration, ce contexte a été perdu parce que je ne l'ai pas mentionné explicitement. Maintenant, je documente le "pourquoi" derrière chaque paramètre et fonctionnalité.

Mon nouveau workflow de pair programming avec IA

Maintenant quand je travaille avec une IA sur du code de production, je suis beaucoup plus explicite sur les contraintes :

**Avant :**

"Migre cette fonction Lambda vers Cloud Run"

**Maintenant :**

"Migre cette fonction Lambda vers Cloud Run. C'est pour la génération JSON en production — priorise la fiabilité sur la créativité. Utilise temperature 0, le mode JSON si disponible, et toutes les autres optimisations pour la sortie de données structurées."

Voici la config optimisée pour la production que Claude m'a aidé à construire :

```python
def get_ai_json_response(prompt: str) -> dict:
    """Production-optimized JSON generation with AI"""
    response = anthropic.messages.create(
        model="claude-sonnet-4-20250514",
        temperature=0,  # Zero creativity for structured data
        response_format=\{"type": "json_object"\},  # Force JSON mode
        system="You are a JSON generation assistant. Output only valid JSON.",
        messages=[\{
            "role": "user",
            "content": f"{prompt\}\n\nRespond with valid JSON only."
        }]
    )

    # Explicit error handling for production
    try:
        return json.loads(response.content[0].text)
    except json.JSONDecodeError as e:
        logger.error(f"JSON parse failed: \{e\}")
        logger.error(f"Raw response: {response.content[0].text}")
        raise
```

La différence ? J'ai donné à l'IA le contexte dont elle avait besoin pour optimiser pour mon cas d'usage spécifique.

Les résultats

30 % de coûts API en moins, 40 % de génération plus rapide. Tout ça d'une conversation où j'étais enfin précis sur ce que "prêt pour la production" signifiait.

La partie drôle ? Même notre génération de dialogue "créatif" utilise temperature 0. Il s'avère que déterministe ne signifie pas ennuyeux — ça signifie fiable. Les conversations sonnent toujours naturellement parce que les prompts et la recherche de contenu apportent la variété, pas les fluctuations aléatoires de temperature.

Il s'avère que le pair programming avec IA fonctionne très bien quand tu te souviens que c'est toujours de la programmation — la précision dans les exigences te donne la précision dans les résultats.

As-tu déjà eu un assistant IA qui faisait un choix "raisonnable" qui s'est avéré complètement faux pour ton cas d'usage ? J'adorerais entendre tes histoires de guerre — je soupçonne qu'on a tous été piégés par des valeurs par défaut sensées à un moment ou un autre :)

Cordialement,

Chandler

Tu veux créer tes propres podcasts IA avec du JSON valide garanti ? Essaie DIALØGUE — 2 crédits gratuits pour commencer ! :P

Partie 3 de la série d'ingénierie DIALØGUE. Encore en train d'apprendre que "faire en sorte que ça marche" et "faire en sorte que ça marche efficacement" sont des requêtes complètement différentes. Suis plus d'aventures de pair programming IA sur chandlernguyen.com.

**Prochain dans la série** : dans environ 7 jours — "De 3 minutes à 500 ms : le bug d'inscription qui n'avait aucun sens"

Continuer la lecture

Mon parcours
Me suivre
Langue
Preferences