Pourquoi le LLMOps : ce qui change avec un LLM en production
Une API classique, mais en plus imprévisible
Une API classique est déterministe : même entrée, même sortie. Si elle répond 200 en 50 ms, tout va bien. Un appel LLM peut répondre 200 en 800 ms… avec une réponse fausse, ou dans un mauvais format. Trois différences changent la manière d'exploiter :
| API classique | Application LLM | |
|---|---|---|
| Correction | un code 200 suffit souvent | 200 ne dit rien de la qualité de la réponse |
| Coût | fixe (CPU, mémoire) | variable : au token, et la taille des prompts change tout |
| Changement | un déploiement de code | changer un mot du prompt, ou la version du modèle, change le comportement |
| Latence | stable | dépend du nombre de tokens générés, de la charge du fournisseur |
Le LLMOps (opérations des applications LLM) adapte les pratiques DevOps et MLOps à ces trois points : on observe chaque appel, on mesure coûts et qualité, on versionne prompts et modèles comme du code, et on teste avant de déployer.
flowchart LR O["Observer : traces, journaux"] --> M["Mesurer : latence, tokens, coût, erreurs, qualité"] M --> V["Versionner : prompts, modèles, paramètres"] V --> T["Tester : non-régression en CI"] T --> D["Déployer"] D --> O
Les quatre signaux
Les ingénieurs fiabilité de Google parlent de « signaux dorés » (latence, trafic, erreurs, saturation). Pour un LLM, on adapte :
- Latence : p50 (la valeur médiane) et p95 (95 % des appels sont plus rapides). Le p95 capte les appels lents que la moyenne cache.
- Tokens et coût : tokens d'entrée, de sortie (y compris la « réflexion » des modèles qui raisonnent), coût calculé.
- Erreurs : erreurs techniques (429 quota, 503 surcharge, délai dépassé) et erreurs de format (JSON invalide).
- Qualité : mesurée hors ligne sur un jeu de référence à chaque changement, et par échantillonnage en production.
Votre tableau de bord montre 0 % d'erreurs HTTP et une latence stable, mais les utilisateurs se plaignent de mauvais routages depuis hier. Que manque-t-il ?
Pour un LLM, une réponse fausse est un succès HTTP. Il faut journaliser la version du prompt et du modèle, et mesurer la qualité sur un jeu de référence pour relier la plainte à un changement.
L'architecture du lab : un seul point d'entrée
Toute l'application appelle le LLM via une seule fonction, call_llm. C'est là, et seulement là, qu'on trace, journalise et calcule le coût. Le code métier ne connaît ni OpenTelemetry ni les prix.
from llm_wrapper import call_llm
r = call_llm("router", "v1", demande="Mon PC ne démarre plus")
print(r["text"], r["latency_ms"], r["cost_usd"], r["trace_id"])Le cas d'usage : un routeur de demandes internes. Un salarié écrit une demande libre, le modèle renvoie {"service": "it|rh|achats|juridique", "urgence": "haute|normale"}. Le prompt est stocké dans un registre versionné (prompts.json), jamais en dur dans le code.
Pourquoi faire passer tous les appels LLM par une seule fonction call_llm ? (plusieurs réponses)
Un point d'entrée unique centralise l'instrumentation, garantit la traçabilité des versions et permet d'injecter un faux modèle (paramètre generate) dans les tests. Il ne change rien à la qualité du modèle.
Exercice : quels signaux pour quel incident ?
Pour chaque incident, quel signal l'aurait détecté en premier ?
- Le fournisseur renvoie des 429 pendant 10 minutes.
- Un développeur ajoute 3 pages de documentation dans le prompt système.
- Le passage à une nouvelle version du modèle change le format des réponses.
- 2 % des appels prennent 15 secondes.
Voir la solution
- Taux d'erreur (et le nombre de tentatives
attemptsdans les journaux, qui monte avant l'échec). - Tokens d'entrée et coût : les tokens par appel explosent du jour au lendemain.
- Qualité (test de non-régression) et erreurs de format : JSON invalide ou valeurs hors liste.
- Latence p95 ou p99 : la médiane ne bouge presque pas, le p95 ou p99 si.
Résultat obtenu
Rapport réel du 2026-10-15, produit par report.py à partir des 24 appels du lab (12 par version de prompt) :
| version | appels | taux_erreur | p50_ms | p95_ms | tokens_in_moy | tokens_out_moy | cout_1000_appels_usd |
| router@v1 (gemini-3.5-flash-lite) | 12 | 0.0 | 797 | 1050 | 102 | 19 | 0.0781 |
| router@v2 (gemini-3.5-flash-lite) | 12 | 0.0 | 763 | 1438 | 37 | 23 | 0.0695 |Les deux versions ont 0 % d'erreur technique ; v2 est 11 % moins chère. Pourtant v2 classe 0 demande sur 12 correctement (module 3). Sans le quatrième signal, la qualité, on l'aurait déployée.
Je sais faire
- Expliquer pourquoi un code 200 ne suffit pas pour un LLM
- Citer les quatre signaux à suivre et leur intérêt
- Justifier un point d'entrée unique pour les appels LLM
- Limiter les données personnelles dans l'observabilité