Vous avez conçu un outil interne qui permet à une équipe d'exécuter 28 tests unitaires sur une fonctionnalité pilotée par un LLM sans jamais appeler l'API du modèle. Vous y êtes parvenu en enveloppant le modèle dans une interface falsifiable et en ajoutant trois couches d'évaluation : déterministe, heuristique et basée sur un LLM.
Les assertions standards échouent dès qu'un LLM génère de la prose. Le même prompt peut produire une phrase différente à chaque exécution, de sorte que assertEqual(output, expected) signale un échec même si le modèle s'est comporté correctement. La plupart des équipes d'ingénierie livrent soit la fonctionnalité sans vérification, soit tentent de tester le modèle lui-même, traitant une cible en constante évolution comme s'il s'agissait d'une bibliothèque statique.
Pourquoi le problème est important
Les LLM sont désormais intégrés dans des flux de travail orientés client : prospection par e-mail, réponses au support, génération de contenu. Un seul fait halluciné ou un identifiant divulgué peut nuire à la réputation de la marque, exposer des données privées ou entraîner des violations de conformité. Sans une stratégie de test fiable, les équipes perdent du temps à traquer des échecs instables ou livrent des bugs qui ne se manifestent qu'en production.
L'approche : réduire la responsabilité du modèle
La première étape a consisté à limiter ce que le LLM fait réellement. Dans le système de l'auteur, le modèle ne rédige que des messages de prospection. Toute la logique de routage, la gestion d'état et les contrôles de sécurité restent dans le code ordinaire. En confinant le modèle à une sortie unique et bien définie, le système environnant reste déterministe et testable.
Pour rendre cela possible, le LLM se trouve derrière une interface de fournisseur, permettant d'utiliser une version simulée (mock) lors des tests. En production, l'implémentation appelle l'API externe ; dans la suite de tests, un mock léger renvoie une réponse préenregistrée. Comme le reste du code interagit uniquement avec l'interface, l'ensemble du flux de travail peut être exercé par des tests unitaires qui ne touchent jamais au réseau. Le résultat est un cœur prévisible que les 28 tests vérifient.
Un dispositif d'évaluation honnête
Même avec un périmètre réduit, la sortie du modèle reste non déterministe. L'auteur a donc construit un dispositif d'évaluation à trois couches, chaque couche gérant une classe de risque différente.
Couche 1 – Contrôles déterministes Des règles simples d'expressions régulières capturent les erreurs concrètes, comme un mauvais ID de bâtiment ou des jetons (tokens) interdits. Ces contrôles sont rapides et fournissent un résultat binaire (réussite/échec).
Couche 2 – Contrôles heuristiques Des scripts recherchent des nombres ou des dates hallucinés, signalant les fabrications factuelles évidentes. Ils passent à côté des fausses affirmations qui manquent d'indices numériques, et l'auteur reconnaît ouvertement cette limitation.
Couche 3 – Juge LLM Un modèle secondaire évalue le ton et le professionnalisme. Comme cette étape repose sur un autre système probabiliste, elle n'est utilisée que pour les aspects subjectifs où des règles déterministes seraient impossibles.
La clé du dispositif est le jeu de données utilisé pour l'évaluation. L'auteur a encodé des schémas d'échec connus — des pièges spécifiques et des connaissances métier — afin que le dispositif teste précisément les erreurs qui sont apparues en pratique. Il ne s'agit pas d'un "filet magique" universel, mais d'un filet de sécurité ciblé.
Ce que cela signifie pour les équipes
- Limitez les tâches du LLM. Moins de responsabilités facilitent l'isolation et les tests.
- Placez le routage, l'état et la sécurité dans le code. La logique traditionnelle reste déterministe et entièrement testable.
- Exposez le modèle via une interface falsifiable. Les tests unitaires s'exécutent sans appels externes, ce qui permet de garder la suite de tests rapide et fiable.
- Superposez vos évaluations. Commencez par des règles déterministes, ajoutez des heuristiques pour les hallucinations connues, et réservez les juges LLM pour les contrôles de qualité subjectifs.
- Énoncez les limites. Aucune couche ne garantit la perfection ; le dispositif ne capture que ce que vous programmez explicitement pour détecter.
Contre-argument : vous ne pouvez toujours pas tester le modèle lui-même par des tests unitaires
L'auteur concède qu'un modèle est une cible mouvante. Même la couche du juge LLM hérite du même non-déterminisme qu'elle tente d'évaluer. Par conséquent, le système ne peut jamais garantir que chaque hallucination ou violation de politique sera détectée avant la mise en production. L'approche réduit le risque, elle ne l'élimine pas, et elle repose sur la capacité de l'équipe à maintenir les données d'évaluation à jour à mesure que de nouveaux modes d'échec apparaissent.
À retenir
Vous ne pouvez pas écrire un test unitaire classique qui affirme la sortie exacte d'un LLM, mais vous pouvez construire un système où l'influence du modèle est limitée, son interface est remplaçable et sa sortie est filtrée par des contrôles multicouches et transparents. Cette combinaison transforme un composant par ailleurs instable en une partie prévisible d'une application plus large et testable.
