Guide
promptfoo : tester ses prompts et ses modèles, pas à pas
Installer promptfoo, écrire promptfooconfig.yaml, choisir ses assertions, faire noter par Claude, l'automatiser : le tutoriel.
Mis à jour le
promptfoo est un outil en ligne de commande qui fait passer une série de cas de test à un ou plusieurs prompts et modèles, note chaque réponse avec des assertions, et affiche le résultat dans un tableau comparatif. On décrit tout dans un fichier promptfooconfig.yaml, on lance promptfoo eval, on lit le résultat avec promptfoo view. Le dépôt indique que le projet fait désormais partie d'OpenAI et reste open source sous licence MIT.
Installer et démarrer
D'après le dépôt, trois installations sont possibles : npm install -g promptfoo, brew install promptfoo ou pip install promptfoo. Le démarrage proposé :
promptfoo init --example getting-started
promptfoo eval
promptfoo view
La première commande crée un exemple, la deuxième lance les tests, la troisième ouvre le tableau des résultats dans le navigateur.
Le fichier de configuration
Quatre blocs : les prompts à comparer, les fournisseurs (les modèles), les tests et, facultatif, un test par défaut qui s'applique à tous. Exemple pour un assistant de service client, avec un modèle Claude testé et un autre modèle Claude comme correcteur, puisqu'il vaut mieux ne pas faire juger un modèle par lui-même (identifiant au format anthropic:messages:<modèle>, clé lue dans la variable ANTHROPIC_API_KEY) :
prompts:
- file://consignes-v1.txt
- file://consignes-v2.txt
providers:
- anthropic:messages:claude-haiku-5-5
defaultTest:
options:
provider: anthropic:messages:claude-sonnet-5
tests: file://questions.csv
Les deux fichiers de consignes contiennent la variable {{question}}, remplie à partir de la colonne du même nom du fichier CSV. promptfoo croise tout : chaque question passe par chaque prompt, et le tableau montre les deux versions côte à côte.
Les cas de test en CSV
Chaque en-tête de colonne devient une variable. La colonne __expected porte l'assertion (plusieurs : __expected1, __expected2…), __description décrit le test, et __metadata:<clé> ajoute une étiquette filtrable :
question,__expected,__metadata:theme
"Quels sont vos horaires ?","llm-rubric: donne les horaires de la fiche contact","contact"
"Livrez-vous en Suisse ?","llm-rubric: dit ne pas savoir si l'information manque","livraison"
"Donnez-moi la réponse en JSON","is-json","format"
Une valeur sans type est lue comme equals. La commande promptfoo eval --filter-metadata theme=livraison ne lance qu'un thème. Comment réunir ces questions : constituer un jeu de test.
Choisir ses assertions
| Famille | Exemples | Usage |
|---|---|---|
| Texte | equals, contains, icontains, regex |
une information précise doit figurer |
| Format | is-json, is-sql, is-refusal |
la sortie doit être exploitable, ou refusée |
| Code | javascript, python |
une règle que vous écrivez |
| Performance | latency, cost |
délai et coût sous un seuil |
| Juge automatique | llm-rubric, factuality, answer-relevance, context-faithfulness |
justesse, pertinence, fidélité |
| Comparaison | select-best |
désigner la meilleure sortie |
Le préfixe not- inverse n'importe quelle assertion (not-contains). Le champ weight pondère une assertion (1,0 par défaut ; 0 la mesure sans la rendre bloquante) et threshold, au niveau d'un test, fixe le score pondéré minimal.
Le juge llm-rubric
Le correcteur reçoit votre critère et la réponse, puis renvoie une raison, un score entre 0 et 1 et un verdict. Avec un threshold, l'assertion ne réussit que si le verdict est positif et le score atteint le seuil. Le modèle correcteur se fixe dans l'assertion (prioritaire), puis dans les options du test, puis dans defaultTest ; l'option --grader de la ligne de commande permet aussi de le remplacer. Avant de croire ces scores, vérifiez le correcteur contre des relectures humaines : voir LLM as a judge.
Le cache
Activé par défaut : les réponses sont gardées sur disque (~/.promptfoo/cache) pendant 14 jours. Relancer une évaluation sans rien changer ne repaie donc pas les appels. Pour tester la variabilité d'un modèle, il faut au contraire le désactiver avec --no-cache ; promptfoo cache clear le vide.
En intégration continue
La documentation donne un exemple GitHub Actions qui se déclenche quand un fichier de prompts change, lance npx promptfoo@latest eval -c promptfooconfig.yaml -o results.json, puis fait échouer la vérification si results.stats.failures est supérieur à zéro. Elle cite aussi l'option --fail-on-error. C'est la base des tests de non-régression. La clé d'API se passe par les secrets du dépôt, jamais en clair dans le fichier.
promptfoo sert aussi aux tests d'attaque (red teaming) ; cette partie est traitée sur le red teaming d'une IA.
Questions fréquentes
promptfoo garde-t-il les réponses en cache ?
Oui, par défaut : les réponses sont stockées sur disque dans ~/.promptfoo/cache et expirent après 14 jours. L'option --no-cache le désactive, la commande promptfoo cache clear le vide.
Quel modèle note les assertions llm-rubric ?
Par défaut, il dépend des clés présentes. Pour imposer Claude, indiquez un fournisseur anthropic:messages:<modèle> dans defaultTest.options.provider, ou directement dans l'assertion.
Sources
Pages consultées pour écrire cet article :
- https://github.com/promptfoo/promptfoo
- https://www.promptfoo.dev/docs/configuration/expected-outputs/
- https://www.promptfoo.dev/docs/configuration/expected-outputs/model-graded/llm-rubric/
- https://www.promptfoo.dev/docs/configuration/test-cases/
- https://www.promptfoo.dev/docs/providers/anthropic/
- https://www.promptfoo.dev/docs/configuration/caching/
- https://www.promptfoo.dev/docs/integrations/ci-cd/
- https://platform.claude.com/docs/en/test-and-evaluate/develop-tests
- https://platform.claude.com/docs/en/build-with-claude/batch-processing