Comment tester les agents IA non déterministes (quand la température=0 ne suffit pas)

Réglez la température à zéro et un agent d'IA ne renverra toujours pas de texte identique. Testez les agents non déterministes en vérifiant la structure, le schéma et les plages, et non les chaînes exactes.

Ashley Innocent

Ashley Innocent

20 July 2026

Comment tester les agents IA non déterministes (quand la température=0 ne suffit pas)

Apidog pour les entreprises

Déploiement sur site

SSO & RBAC

Conforme SOC 2

Découvrir Apidog Enterprise

Votre test a réussi lundi. Même entrée, même code, temperature=0. Mardi, il a échoué, et vous n'avez rien changé. L'assertion vérifiait une chaîne exacte, et le modèle a renvoyé la même réponse formulée un peu différemment. Le test est rouge, l'agent va bien, et maintenant vous déboguez votre suite de tests au lieu de votre produit.

C'est le coût de tester tout ce qui appelle un modèle linguistique. La sortie bouge, même quand vous lui avez dit de ne pas le faire. Réglez la température à zéro et vous n'obtiendrez toujours pas de réponses identiques au bit près d'une exécution à l'autre. La plupart des développeurs l'apprennent à leurs dépens, une fois, puis réécrivent leur façon de tester. Ce guide vous montre comment écrire des assertions qui tiennent la route lorsque le texte sous-jacent continue de changer. C'est l'examen approfondi du troisième mode de défaillance de notre guide sur les raisons pour lesquelles les agents IA tombent en panne en production.

bouton

Pourquoi temperature=0 ne signifie pas déterministe

La température contrôle la façon dont le modèle échantillonne le prochain jeton. À zéro, il prend le jeton le plus probable à chaque fois, ce qui semble devoir être reproductible. Ce n'est pas le cas, et les raisons se situent en dessous du modèle.

Le calcul en virgule flottante n'est pas associatif sur un GPU. Additionnez les mêmes nombres dans un ordre différent et vous obtiendrez un résultat légèrement différent à la dernière décimale. Cette infime différence peut faire pencher la balance vers un jeton plutôt qu'un autre, et un jeton différent change tout ce qui suit. L'ordre de ces additions dépend de la façon dont le fournisseur regroupe votre requête avec d'autre trafic, du matériel qui l'exécute et de la version du noyau déployée ce jour-là. Vous ne contrôlez rien de tout cela.

Les fournisseurs changent également des choses de leur côté. Ils échangent des GPU, mettent à jour les bibliothèques d'inférence, re-quantifient les poids et acheminent votre appel vers une autre région. Une longue discussion vLLM explique pourquoi un seed fixe et une température=0 ne suffisent toujours pas pour une reproductibilité bit à bit. La version courte : le déterminisme est une propriété de l'ensemble de la pile de service, pas un indicateur que vous définissez dans votre requête.

Alors, arrêtez de considérer une sortie identique comme la base. Le modèle vous donne une réponse qui signifie la même chose, formulée comme elle se présente lors de cette exécution. Vos tests doivent accepter cela.

Les assertions de chaîne exacte rendent votre suite instable

Voici le piège. Vous écrivez assert response == "Votre total de commande est de 42,00 $." parce que c'est ce qui est revenu la première fois. Ça passe. Puis le modèle renvoie "Votre total s'élève à 42,00 $" et le test échoue sur une bonne réponse.

Un test qui échoue sur une bonne réponse est pire que pas de test du tout. L'équipe apprend que cette suite crie au loup. Les gens la relancent jusqu'à ce qu'elle devienne verte, puis ils arrêtent de lire les échecs, puis ils ratent la vraie régression enfouie dans le bruit. Les tests instables ne font pas seulement perdre du temps, ils érodent la confiance dans toute la suite, et nous avons déjà écrit sur les causes des tests instables et pourquoi ils se propagent. Une sortie non déterministe est l'un des moyens les plus rapides de les créer.

L'instinct est de figer la sortie plus fermement : capturer la chaîne exacte, la prendre en instantané, la comparer. Cela aggrave l'instabilité, car vous avez couplé votre test à la seule chose qui est garantie de changer. Vous avez besoin du mouvement inverse.

Affirmer la structure et la signification, pas le texte exact

La sortie varie, mais le contrat sous-jacent ne devrait pas. Un agent de support pourrait formuler une confirmation de remboursement de cent manières, mais chaque réponse valide contient les mêmes faits : un montant de remboursement, un identifiant de commande, un statut. Testez les faits, pas la formulation.

C'est tout le changement. Arrêtez de demander "le modèle a-t-il dit exactement ceci" et commencez à demander "la réponse a-t-elle la bonne forme, les bons champs et les valeurs dans la bonne plage". Ces propriétés survivent aux reformulations. Une vraie régression, un champ manquant, un nombre hors limites, une charge utile mal formée, déclenche toujours l'assertion. Voici les stratégies qui mettent cela en pratique.

Valider la réponse par rapport à un schéma JSON

Si votre agent renvoie des données structurées, définissez un schéma JSON pour celles-ci et validez chaque réponse par rapport à ce schéma. Le schéma vérifie les types, les champs obligatoires, les énumérations autorisées et les formats sans se soucier des valeurs spécifiques. Un champ status doit être l'un des suivants : refunded, pending ou denied. Un order_id doit correspondre à votre modèle d'identifiant. Un amount doit être un nombre, pas une chaîne de caractères.

C'est la seule assertion la plus forte que vous puissiez écrire contre une réponse non déterministe, car elle détecte les échecs qui nuisent : le modèle a supprimé un champ, a mal imbriqué l'objet, ou a renvoyé du texte là où vous attendiez du JSON. Chargez votre schéma de réponse dans Apidog et validez les réponses en direct de l'agent par rapport à celui-ci. Une non-concordance nomme le champ exact qui a échoué, et non une différence de chaîne de 400 caractères.

Affirmer que l'appel d'outil a la bonne forme et la bonne cible

Lorsque votre agent décide d'appeler un outil, testez l'appel, pas la phrase qui y a conduit. Affirmez trois choses : il a choisi le bon outil, il a ciblé la bonne cible, et la charge utile correspond au schéma de l'outil. Un agent de réservation appelant POST /reservations devrait envoyer guests comme un entier et une date valide, quelle que soit la raison en langage naturel qui a produit cet appel.

C'est la même discipline que la validation d'un corps de réponse, appliquée à la requête sortante. Vérifiez que les paramètres requis existent, que les types sont corrects et qu'aucun champ inventé ne s'est faufilé. La méthode de bout en bout pour tester les appels API d'un agent IA explique comment capturer ces schémas d'outils et les affirmer. Une charge utile d'appel d'outil a un contrat même lorsque la formulation qui l'entoure n'en a pas.

Utiliser des plages numériques au lieu de valeurs exactes

Pour tout nombre que le modèle produit ou transmet, affirmez une plage, pas une valeur. Un agent de panier d'achat calcule un total. Vous ne connaissez pas le chiffre exact pour chaque exécution, panier et règle fiscale, mais vous savez qu'il ne peut pas être négatif et ne peut pas dépasser la valeur du panier plus les frais de port et taxes maximaux. Affirmez donc cela : la réponse contient un total entre 0 et ce plafond.

Cette seule borne détecte les échecs qui importent, un total négatif, un total dix fois trop élevé, un total de zéro sur un panier plein, tout en ignorant les variations qui ne vous intéressent pas. Les plages fonctionnent pour les scores de confiance, les nombres d'articles, l'utilisation des jetons, les budgets de latence et toute autre valeur dérivée. Choisissez la borne la plus large qui échoue toujours sur un véritable bug.

Vérifier que les clés requises existent et que les champs interdits sont absents

Deux assertions peu coûteuses ont beaucoup de poids. Premièrement, les clés dont vous dépendez sont présentes et non nulles. Deuxièmement, les clés qui ne doivent jamais apparaître sont absentes. Un agent traitant un ticket de support devrait renvoyer une résolution, et il ne devrait jamais divulguer un champ internal_notes ou raw_prompt au client.

Les vérifications de présence et d'absence sont à l'abri des reformulations par conception, car elles testent le squelette de la réponse, et non son contenu. Elles sont également votre garde-fou le moins cher contre toute une catégorie de fuites de confidentialité, où le modèle inclut utilement un champ qu'il aurait dû garder privé.

Utiliser des vérifications sémantiques et de seuil pour le texte libre

Parfois, la charge utile est un texte en prose et vous devez toujours le tester. Une correspondance exacte ne fonctionnera pas, alors vérifiez plutôt les propriétés. La réponse contient-elle le numéro de commande que vous avez transmis ? Reste-t-elle sous une limite de longueur ? Évite-t-elle une liste noire de phrases que vous ne voulez jamais envoyer à un utilisateur ?

Lorsque vous avez réellement besoin de tester le sens, comparez par similarité d'intégration (embedding similarity) par rapport à une réponse de référence et affirmez que le score dépasse un seuil, plutôt que d'exiger que les chaînes correspondent. Traitez ces vérifications sémantiques comme une porte grossière, pas précise. Elles détectent une réponse qui s'est éloignée du sujet. Elles ne détecteront pas une erreur factuelle subtile, alors associez-les aux assertions structurelles ci-dessus.

Capturer des plages, pas des instantanés exacts

Les tests d'instantané ont toujours leur place, tant que vous capturez les parties stables. Figez la forme de la réponse, l'ensemble des clés, les types, les valeurs énumérées, et laissez les champs libres varier dans des limites. En pratique, votre instantané enregistre "cette réponse a les clés a, b, c, avec b dans cette plage et c de cet ensemble" plutôt qu'un bloc figé de texte exact. Lorsque l'instantané se rompt, il se rompt sur un changement structurel qui mérite d'être examiné, et non sur un synonyme.

L'état et la mémoire rendent cela plus difficile

Tout ce qui précède suppose une requête entrante, une réponse sortante. Les agents ne fonctionnent pas ainsi. Ils conservent la mémoire d'un tour à l'autre, et cet état multiplie les sources de variation.

La réponse d'un agent avec état dépend de ce qu'il a récupéré, de ce qu'il a stocké précédemment et de l'ordre dans lequel les tours précédents se sont déroulés. Deux exécutions de la même conversation peuvent diverger parce qu'une étape de récupération a classé les documents différemment, ou parce qu'un résumé écrit au deuxième tour a influencé le raisonnement au cinquième tour. Maintenant, votre sortie varie pour deux raisons cumulées : le non-déterminisme propre du modèle et un état de départ différent. Notre explication sur le fonctionnement de la mémoire des agents IA décrit où cet état vit et comment il est construit.

Deux habitudes permettent de maintenir cette testabilité. Premièrement, contrôlez l'état que vous pouvez. Initialisez la mémoire de l'agent à un point de départ connu avant chaque test, afin de ne faire varier qu'une seule chose et non deux. Deuxièmement, affirmez des invariants qui tiennent quel que soit le chemin. Un solde courant ne devrait jamais devenir négatif. Une conversation qui a réservé un vol devrait se terminer par exactement une réservation, quel que soit le nombre de tours nécessaires. Les assertions indépendantes du chemin sont celles qui survivent à un agent avec état et non déterministe.

Simuler les dépendances pour que le test se répète

Vous ne pouvez pas répéter tout cela avec des API tierces en direct. Elles vous limitent en débit, elles changent leurs données et elles ajoutent une deuxième source d'aléatoire en plus du modèle. Pour obtenir un test reproductible, figez tout ce qui n'est pas le comportement que vous testez.

Simulez les API que l'agent appelle et programmez des réponses fixes. Maintenant, l'API de paiement renvoie toujours le même reçu, l'API de recherche renvoie toujours les trois mêmes résultats, et la seule chose qui bouge est le raisonnement propre de l'agent, ce que vous voulez observer. Une dépendance simulée vous permet également de forcer les cas limites qu'une API saine ne produirait pas à la demande, puis d'affirmer que l'agent les gère. Pointez Apidog vers les dépendances de l'agent pour mettre en place ces simulations avec des corps stables et contrôlables, et associez-les aux assertions de schéma ci-dessus. Cela s'inscrit dans la pratique plus large des tests IA agentiques, où la simulation et l'assertion fonctionnent ensemble.

Où Apidog s'intègre (et où il ne s'intègre pas)

Soyez précis sur le rôle de l'outil. Apidog est une plateforme de conception, de test et de simulation d'API. Ce n'est pas un framework d'agent, un hébergeur de modèle, un runtime d'agent, ou une plateforme d'évaluation et d'observabilité. Il ne construit pas votre agent, ne l'exécute pas, n'orchestre pas ses étapes, ni ne note son raisonnement.

Ce qu'il possède, c'est la couche API à laquelle votre agent s'adresse, et c'est là que ces tests vivent. Deux adéquations honnêtes. Vous écrivez des assertions sur les réponses API de l'agent (validation de schéma, forme de réponse, plages numériques, clés requises et interdites, forme de la charge utile d'appel d'outil) qui survivent à une sortie non déterministe. Et vous simulez les dépendances de l'agent afin qu'un test s'exécute de la même manière deux fois. C'est la couture qu'Apidog remplit : le contrat sur les requêtes et les réponses, pas le modèle qui les produit.

Testez le contrat, pas la formulation

Le non-déterminisme n'est pas un bug que l'on peut contourner par la configuration. C'est une propriété de l'exécution d'un modèle linguistique, et temperature=0 ne l'annule pas. Les équipes qui livrent des agents fiables ont cessé de le combattre. Elles testent les choses qui restent constantes, le schéma, la forme, les plages, les champs requis, et elles laissent la formulation bouger. Faites cela et votre suite se taira de la bonne manière : elle restera verte pendant que le texte dérive, et elle ne deviendra rouge que lorsque quelque chose est cassé.

Choisissez une assertion instable dans votre suite cette semaine et réécrivez-la comme une vérification de schéma et de plage. Téléchargez Apidog pour valider les réponses de votre agent par rapport à un contrat et simuler les dépendances qui rendent les tests reproductibles.

bouton

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API