La version conférence d'un produit LLM, c'est un seul appel à GPT-4 avec un prompt astucieux. La version production, c'est quinze briques d'infrastructure, trois fournisseurs, deux bases de données, et une politique de retry qui a pris six semaines à régler. Cette série parle de la deuxième.
Dans cet article : les sept couches que tout système LLM en production possède, les outils qu'on a utilisés à chaque niveau, et les chiffres qui comptent pour choisir entre eux. La partie 2 (déjà publiée) traite de l'arbitrage RAG / fine-tuning / prompt seul. La partie 3 couvrira les évaluations. À lire dans l'ordre que vous voulez.
Les pièces dont personne ne parle
Un démo, c'est un appel API. Un système en production a besoin, sous une forme ou une autre :
- D'un registre de prompts
- D'une suite d'évaluation avec des exemples canoniques
- D'un cache de réponses
- D'une passerelle modèle avec fallback
- D'un rate limiter côté entrée
- D'un pipeline d'observabilité qui capture les entrées, pas seulement les sorties
- D'une politique de retry et timeout qui n'amplifie pas les incidents fournisseur
Chacun est une couche de la stack. Chacun a des outils bien connus qu'on peut acheter, construire ou récupérer gratuitement. Chacun a un défaut qu'on choisit instinctivement en premier, et qui est généralement faux.
Registre de prompts
Les prompts sont du code. Ils ont des versions, ils sont relus, ils sont rollbackables. Ils vivent dans votre repo (ou dans un registre managé qui vous offre des APIs lecture-écriture), et un changement de prompt déclenche une re-évaluation avant merge. Si vos prompts sont des chaînes littérales éparpillées dans vos composants React, vous avez un problème de junior déguisé en décision technique.
Option gratuite : un dossier YAML ou Markdown dans votre repo, chargé au build, versionné par Git. C'est ce qu'on fait tourner pour le pipeline de publication de cybercloud.ma. Huit prompts, un seul dossier.
Options managées à connaître : Langfuse (open source, auto-hébergeable, free tier), PromptLayer, Pezzo, Braintrust. L'argument du managé, c'est l'UI d'édition en direct pour qu'un non-ingénieur puisse itérer les prompts. Si aucun non-ingénieur ne touchera jamais à vos prompts, économisez l'argent.
Suite d'évaluation
Sans elle, chaque modification de prompt est une supposition. Avec elle, vous livrez 20 itérations par semaine en sachant lesquelles ont régressé.
Le minimum qu'on impose sur les projets sérieux : 50 exemples par prompt, dont la moitié adversariaux. Adversarial signifie des exemples qui ont cassé une version antérieure du prompt, ou qui imitent les modes d'échec qu'on a vus en logs. Les exemples adversariaux synthétiques (générés par un autre LLM) valent 30 pour cent d'un vrai exemple. Pondérez votre set en conséquence.
La règle qui nous a le plus souvent sauvés : tout nouveau cas limite trouvé en production devient un exemple d'évaluation permanent avant la fin de la semaine. Le set ne rétrécit jamais.
Outils qu'on a utilisés et qu'on recommande pour les évaluations : Braintrust (payant, focus eval), Langfuse evals (open source), Arize Phoenix (open source, voisin observabilité), LangSmith (payant, écosystème LangChain). Pour les très petits projets, un script Python avec pytest parametrize et assert llm_output_passes(critères) suffit. Les outils managés deviennent rentables au-delà d'environ 200 cas d'éval.
Cache de réponses
Même question, même réponse, 10 à 90 pour cent moins cher. Le levier numéro un de réduction de coûts pour presque toutes les apps LLM en production.
Deux variantes à connaître :
-
Prompt caching côté fournisseur. Anthropic vous donne environ 90 pour cent de réduction sur la portion en cache d'un prompt, après la première lecture dans une fenêtre de 5 minutes. OpenAI vous donne 50 pour cent de réduction sur l'entrée en cache. Si vous réutilisez le même system prompt ou les mêmes chunks récupérés sur de nombreux appels, c'est de l'argent gratuit que vous devriez déjà prendre.
-
Votre propre cache sémantique. Une requête arrive. Vous l'embeddez, cherchez le match le plus proche dans un index de cache, et si la similarité est suffisante (cosine > 0.95 environ) vous renvoyez la réponse précédente. Économise le coût d'inférence complet mais introduit un risque qualité. On l'a livré une fois en production et on a des regrets : le mode d'échec, c'est l'utilisateur qui voit des réponses légèrement fausses sortir du cache et perd confiance. À utiliser pour des endpoints à fort volume et faible enjeu (autocomplete, "vouliez-vous dire"), pas pour des réponses primaires.
Passerelle modèle avec fallback
Le fournisseur A tombe environ une fois par trimestre. Parfois 20 minutes, parfois 4 heures. Le fournisseur B existe. Votre code doit savoir quel template de prompt fonctionne pour les deux, et votre trafic doit pouvoir basculer sans déploiement.
Outils qu'on a utilisés :
- LiteLLM (proxy open source, très populaire en 2026). Vous écrivez votre code contre la forme d'API OpenAI et LiteLLM traduit vers Anthropic, Gemini, Bedrock, Together, et 90 autres fournisseurs. Ajoutez une politique de fallback en YAML.
- Portkey (passerelle managée). Routing à la LiteLLM plus cache, retries, clés virtuelles, et une UI pour l'ops.
- Helicone (passerelle plus observabilité). Lié à leur produit d'observabilité.
Pour la plupart des équipes qui passent au multi-fournisseur, LiteLLM dans un pod Kubernetes (ou comme librairie importée dans votre app) est le bon point de départ. Portkey et Helicone deviennent rentables quand l'interface ops compte plus que le coût.
Rate limiter côté entrée
Les limites de débit d'OpenAI ne se soucient pas de la forme de votre trafic. C'est à vous de le modeler. Sinon, le trafic en pic du 11h dû à une campagne marketing rate-limite le trafic régulier de la file de support client.
Le bon pattern : mettre en file d'attente avec priorité. Priorité 1 (client payant en action primaire) passe en premier. Priorité 2 (batch en arrière-plan) est reportée. Priorité 3 (endpoint expérimental que personne ne regarde) est lâchée au-delà d'un seuil.
Outils : une file Redis que vous écrivez vous-même tient en 80 lignes de Python et fonctionne à la plupart des échelles. BullMQ pour Node. RQ ou Celery pour Python si vous avez déjà l'un des deux. Spécifiques au LLM : LiteLLM et Portkey livrent tous les deux des fonctionnalités de queue et rate-limit.
Observabilité qui capture les entrées
Vous instrumentez la latence, le coût en tokens, le statut de la réponse. Vous n'instrumentez pas la distribution des entrées, et c'est là que le drift se cache. Six mois plus tard, le phrasing de vos utilisateurs change, votre prompt était calibré pour la distribution d'origine, la qualité se dégrade, vous n'avez aucun signal.
Exemple concret : on a livré un assistant interne calibré sur des questions du type "Comment je fais X ?". Deux mois plus tard, les utilisateurs avaient compris que l'assistant était fiable et commencé à demander "Faut-il faire X ou Y ?". Des questions de délibération ouverte, c'est une distribution différente, le prompt n'était pas construit pour ça, les réponses sont devenues molles. On ne l'a remarqué que parce qu'un utilisateur sceptique s'est plaint. À ce moment, 8 pour cent du trafic était de cette nouvelle forme. Avec une observabilité des entrées correcte, on l'aurait su en deux jours.
Outils : Langfuse (open source, notre défaut), Helicone, LangSmith, Arize Phoenix. Tous capturent des traces complètes avec métadonnées. Le travail à faire, c'est décider quels champs attacher : palier utilisateur, endpoint appelant, session ID, nombre de chunks récupérés, version du modèle, version du prompt, budget de latence, nombre de retries. Une trace sans métadonnées, c'est juste une ligne de log qu'on ne peut pas requêter.
Politique de retry et timeout qui n'amplifie pas les incidents
Quand un fournisseur passe en mode dégradé (lent mais pas down), une logique de retry naïve transforme un appel lent en trois appels lents et un troupeau tonnant. On a appris ça deux fois à la dure.
Les règles qu'on applique maintenant :
- Timeout par appel : 30 secondes. Plus haut, vous gaspillez la patience des utilisateurs et votre propre budget latence.
- Nombre de retries : 2. Trois retries ou plus sur un fournisseur dégradé transforment un taux d'erreur de 10 pour cent en tempête de retry à 30 pour cent.
- Backoff exponentiel avec jitter. 1s, 2s, 4s avec plus ou moins 30 pour cent de bruit. Le jitter empêche votre code de synchroniser ses retries avec ceux de tout le monde.
- Circuit breaker sur le fournisseur. Au-delà de 20 pour cent d'erreurs pendant 60 secondes, arrêtez d'appeler le fournisseur pendant 2 minutes et basculez sur le fallback. C'est la politique qui nous a sauvés d'être tombés par accident en même temps qu'un fournisseur.
La plupart des clients HTTP (axios, httpx, le retry intégré de l'anthropic-sdk) supportent presque tout ça. Il faut généralement ajouter le circuit breaker soi-même.
Là où la plupart des équipes sous-investissent
D'après notre expérience, deux zones.
Couverture des évaluations
Les équipes livrent une douzaine de prompts en production avec des suites d'éval à un seul chiffre. Puis un upgrade de modèle (ou pire, une dépréciation forcée par le fournisseur) casse la moitié silencieusement parce que la suite ne contenait pas les cas limites importants.
Le minimum, c'est la règle des 50 exemples par prompt mentionnée plus haut. Le mieux : chaque incident en production devient un eval. Chaque bug reporté devient un eval. En six mois après le premier déploiement, votre set d'évaluation est assez grand pour qu'on lui fasse plus confiance qu'à votre intuition sur la sûreté d'un changement.
Traiter le prompt comme de la documentation
Les prompts écrits pour le modèle servent souvent aussi de spécification canonique du comportement attendu de la feature. Si votre product manager veut savoir "que fait le système quand un client demande X ?", le prompt devrait être la réponse autoritaire.
Ça marche si le prompt est lisible, structuré, et vit en version control avec des diffs propres. Ça casse complètement si le prompt est une chaîne de 4 000 caractères dans un fichier TypeScript sans commentaire. Traitez le prompt comme une spec, écrivez-le comme une spec, et revue les changements de prompt avec autant d'attention que les migrations de schéma.
Ce qu'on va couvrir
La partie 2, RAG, fine-tuning, ou juste un prompt ?, entre dans les arbitrages entre les trois approches honnêtes pour ancrer un LLM dans vos propres données. La partie 3 (autre article, pas encore publié) couvrira les évaluations : les trois techniques auxquelles on fait confiance, pourquoi ROC, précision et rappel mentent sur la qualité d'un LLM, et comment faire tourner 1 000 évaluations en 90 secondes.
Le but de cette série n'est pas d'être exhaustif. C'est de court-circuiter quelques-unes des leçons coûteuses qu'on a payées pour que vous n'ayez pas à le faire.



