Aller au contenu principal
Leçon 5 sur 9 · Évaluation de prompts

Première évaluation avec promptfoo

Leçon 5 sur 9 Mis à jour le 5 novembre 2026 Intermédiaire
Sur cette page
  1. Pourquoi un outil
  2. Initialiser
  3. Le fournisseur
  4. Les prompts
  5. Les tests
  6. Exécuter et regarder
  7. Un troisième prompt et une transformation
  8. Comparer deux modèles
  9. À vous de jouer
  10. Points clés à retenir

Cette leçon porte l’évaluation des pattes d’animaux dans promptfoo, un outil libre qui exécute des prompts sur des fournisseurs et des tests, puis compare les résultats dans un tableau de bord. L’objectif n’est pas le prompt, déjà connu, mais l’outillage : un fichier de configuration, des prompts en Python, des tests en CSV, une transformation de sortie, deux modèles comparés d’une ligne. Toute la syntaxe a été relue sur la documentation de promptfoo le 5 novembre 2026 ; elle diffère par endroits du carnet de 2024, et la leçon le signale.

Pourquoi un outil

Le carnet cite plusieurs outils d’évaluation (promptfoo, Vellum, Scale, PromptLayer, ChainForge) et en choisit un, libre et simple : promptfoo. Il fournit, prêts à l’emploi, l’exécution en série, la comparaison entre prompts, modèles et fournisseurs, la mise en cache des réponses, et une interface web pour inspecter chaque résultat. Ce qu’on écrivait à la main à la leçon 4 (collecter, noter, afficher) devient de la configuration.

Dossier prompt_evaluations du dépôt anthropics/courses sur GitHub, bandeau indiquant que le dépôt est archivé depuis le 15 septembre 2026, neuf sous-dossiers de leçons
Capture réelle du 5 novembre 2026 : le dossier du cours original sur GitHub. À partir de cette leçon, chaque dossier contient les fichiers de l'évaluation (configuration, prompts, données) à télécharger pour reproduire les résultats.

Initialiser

Dans un dossier vide :

npx promptfoo@latest init

La commande crée un fichier promptfooconfig.yaml, où tout se configure : les fournisseurs (les modèles à interroger), les prompts à évaluer, les tests à exécuter. On peut en vider le contenu d’exemple. Promptfoo lit la clé d’API dans la variable d’environnement ANTHROPIC_API_KEY :

export ANTHROPIC_API_KEY=votre_cle

Le fournisseur

Les modèles Anthropic se désignent par un identifiant anthropic:messages:<modèle>. La liste de 2024 (Claude 3 Haiku, Claude 3.5 Sonnet, Claude 2…) ne vaut plus : ces modèles sont retirés de l’API, et promptfoo documente pour chacun un remplaçant. Au 5 novembre 2026, sa page sur le fournisseur Anthropic liste notamment anthropic:messages:claude-opus-5-5, anthropic:messages:claude-sonnet-5-5, anthropic:messages:claude-opus-5, anthropic:messages:claude-sonnet-5 et anthropic:messages:claude-haiku-4-5, et précise pour les modèles de la famille 5 ce qu’il retire des requêtes de lui-même (temperature, top_p, top_k, que ces modèles refusent) et comment il convertit un ancien réglage de réflexion en réflexion adaptative. Claude Haiku 5.5, utilisé aux leçons 3 et 4, n’y figure pas encore (promptfoo 0.125.1, publiée le 25 octobre 2026) : l’outil l’accepte en signalant un modèle inconnu, mais ne sait pas calculer son coût, sauf si vous renseignez inputCost et outputCost dans la configuration du fournisseur. Pour garder la colonne des coûts, on commence avec le plus économique de la liste :

description: "Animal Legs Eval"

providers:
  - anthropic:messages:claude-haiku-4-5

Les prompts

Promptfoo accepte des prompts en texte dans le YAML, dans des fichiers texte, JSON ou YAML, ou dans des fonctions Python. Le carnet préfère les fonctions Python, une par prompt, dans un seul fichier. Les fichiers du dossier archivé prennent directement la variable (def simple_prompt(animal_statement)) et se déclarent sans préfixe (prompts.py:simple_prompt) ; la documentation actuelle de promptfoo décrit des fonctions qui reçoivent un dictionnaire context, dont la clé vars contient les variables du test, et des déclarations préfixées par file://. Le code ci-dessous suit la documentation actuelle.

# prompts.py
def simple_prompt(context):
    animal_statement = context["vars"]["animal_statement"]
    return f"""You will be provided a statement about an animal and your job is to determine how many legs that animal has.

    Here is the animal statement.
    <animal_statement>{animal_statement}</animal_statement>

    How many legs does the animal have? Please respond with a number"""

def better_prompt(context):
    animal_statement = context["vars"]["animal_statement"]
    return f"""You will be provided a statement about an animal and your job is to determine how many legs that animal has.

    Here is the animal statement.
    <animal_statement>{animal_statement}</animal_statement>

    How many legs does the animal have? Please only respond with a single digit like 2 or 9"""

On les déclare dans la configuration avec le préfixe file://, le nom du fichier et celui de la fonction :

prompts:
  - file://prompts.py:simple_prompt
  - file://prompts.py:better_prompt

Les tests

Promptfoo offre plusieurs façons de définir les tests ; la plus courante est un fichier CSV dont les colonnes deviennent des variables. Une colonne spéciale, __expected, porte la logique de notation. Sans préfixe, sa valeur est comparée par égalité exacte à la sortie, ce qui est tout ce dont cette évaluation a besoin.

animal_statement,__expected
"The animal is a human.","2"
"The animal is a snake.","0"
"The fox lost a leg, but then magically grew back the leg he lost and a mysterious extra leg on top of that.","5"
"The animal is a dog.","4"
"The animal is a cat with two extra legs.","6"
"The animal is an elephant.","4"
"The animal is a bird.","2"
"The animal is a fish.","0"
"The animal is a spider with two extra legs","10"
"The animal is an octopus.","8"
"The animal is an octopus that lost two legs and then regrew three legs.","9"
"The animal is a two-headed, eight-legged mythical creature.","8"
tests: file://dataset.csv
Les quatre blocs de promptfooconfig.yaml Quatre tuiles : providers (les modèles, anthropic:messages:…), prompts (fonctions Python déclarées par file://), tests (un CSV avec la colonne __expected), defaultTest (réglages communs : transformation, assertions, juge). PROMPTFOO Les quatre blocs de promptfooconfig.yaml 01 providers Les modèles à interroger : anthropic:messages:claude-haiku-4-5, …claude-sonnet-5-5. Une ligne de plus, un modèle de plus. ANTHROPIC_API_KEY 02 prompts file://prompts.py:simple_prompt : une fonction qui reçoit context et renvoie la chaîne ; ou du texte avec {{variables}}. Python YAML fichiers 03 tests file://dataset.csv : une colonne par variable, __expected pour la notation ; ou des tests en YAML avec leurs vars. CSV YAML 04 defaultTest Ce qui s'applique à tous les tests : options.transform, assert, options.provider pour le juge. transform assert npx promptfoo@latest init crée le fichier ; eval exécute ; view ouvre le tableau de bord, où la loupe montre chaque sortie et la raison de son verdict.
D'après le carnet « Introducing promptfoo » (anthropics/courses, carnet archivé) et la documentation promptfoo (relue le 5 novembre 2026).

Exécuter et regarder

npx promptfoo@latest eval

Pour chaque prompt, promptfoo prend chaque phrase du CSV, construit le prompt complet, envoie la requête, et compare la sortie à la valeur attendue. Les résultats s’affichent dans le terminal, une colonne par prompt ; dans le carnet, simple_prompt échouait sur chaque ligne et better_prompt réussissait tout sauf les cas qui demandent un raisonnement. Le tableau de bord en dit plus :

npx promptfoo@latest view

Une loupe dans chaque cellule ouvre le détail : on y voit que simple_prompt trouvait la bonne réponse, noyée dans du texte explicatif, ce qui fait échouer l’égalité exacte. La leçon 3 avait montré la même chose en lisant des listes Python ; ici, c’est un clic.

Un troisième prompt et une transformation

Le carnet ajoute le prompt à raisonnement de la leçon 3, qui demandait de raisonner dans des balises <thinking> puis de répondre dans des balises <answer>. Les modèles actuels raisonnent nativement et peuvent décliner la première consigne ; on garde la seconde, qui isole la réponse finale :

def chain_of_thought_prompt(context):
    animal_statement = context["vars"]["animal_statement"]
    return f"""You will be provided a statement about an animal and your job is to determine how many legs that animal has.

    Here is the animal statement.
    <animal_statement>{animal_statement}</animal_statement>

    How many legs does the animal have?
    Account for any legs lost, regrown or added in the statement.
    Output your final answer inside of <answer> tags.
    Inside the <answer> tags return just the number of legs as an integer and nothing else."""

Pour noter cette sortie, il faut extraire le contenu de la balise avant la comparaison : promptfoo appelle cela une transformation. On l’écrit en Python dans un fichier dont la fonction get_transform reçoit la sortie et le contexte. Le carnet déclenchait l’extraction sur la présence de <thinking> ; on la déclenche ici sur <answer>, la seule balise demandée :

# transform.py
def get_transform(output, context):
    if "<answer>" in output:
        try:
            return output.split("<answer>")[1].split("</answer>")[0].strip()
        except Exception as e:
            print(f"Error in get_transform: {e}")
            return output
    return output
defaultTest:
  options:
    transform: file://transform.py

defaultTest applique le réglage à tous les tests, et le prompt s’ajoute à la liste par file://prompts.py:chain_of_thought_prompt. Dans le carnet, le prompt à raisonnement obtenait 100 % sur Claude 3 Haiku. Vous pouvez aussi déclarer une sortie structurée dans la configuration du fournisseur (config.output_format, avec un JSON Schema) ; la page du fournisseur Anthropic chez promptfoo en donne la syntaxe.

Comparer deux modèles

C’est l’un des atouts de promptfoo : une ligne de plus dans providers, et toute l’évaluation tourne sur un second modèle.

providers:
  - anthropic:messages:claude-haiku-4-5
  - anthropic:messages:claude-sonnet-5-5

Le carnet comparait Claude 3 Haiku et Claude 3.5 Sonnet, et observait que le modèle le plus capable passait l’évaluation à 100 % même avec simple_prompt, qui faisait 0 % sur Haiku. Il notait aussi une surprise instructive : avec le prompt à raisonnement, Sonnet se trompait sur la pieuvre, parce qu’il raisonnait que ses appendices sont des bras et non des pattes. Un modèle plus « intelligent » peut faire baisser un score si le prompt laisse une ambiguïté ; la correction est dans le prompt (préciser ce qui compte comme patte), et c’est l’évaluation qui l’a révélé. Avec les modèles de 2026, relancez la comparaison vous-même plutôt que de supposer ces résultats.

À vous de jouer

Reproduire le dossier. Téléchargez le dossier de la leçon dans le dépôt archivé, remplacez les identifiants de modèles par ceux de la liste actuelle, adaptez les fonctions de prompt à la signature context, et lancez eval puis view. Comparez vos colonnes à celles décrites dans le carnet.

Fermer l’ambiguïté. Ajoutez au prompt à raisonnement une phrase qui définit ce qui compte comme une patte, et vérifiez sur les deux modèles que le cas de la pieuvre passe sans faire échouer un autre cas. C’est votre première régression surveillée.

Sources officielles : 05_prompt_foo_code_graded_animals/lesson.ipynb (anthropics/courses, archivé) · Getting started, Prompts, Test cases et Anthropic provider (documentation promptfoo, relue le 5 novembre 2026)

Points clés à retenir

  • promptfooconfig.yaml réunit fournisseurs, prompts et tests ; eval exécute, view ouvre le tableau de bord.
  • Les modèles Anthropic se désignent par anthropic:messages:<modèle> ; la liste de 2024 est retirée, la page du fournisseur donne les identifiants actuels.
  • Une fonction de prompt Python reçoit context et lit ses variables dans context["vars"] ; on la déclare par file://prompts.py:fonction.
  • Dans un CSV, la colonne __expected porte la notation ; sans préfixe, c’est une égalité exacte.
  • Une transformation (get_transform) prépare la sortie avant la notation ; une ligne de plus dans providers compare un second modèle.