Aller au contenu principal

Introduction à l'ingénierie de prompts

Mis à jour le 30 juillet 2026

Le processus itératif

L’ingénierie de prompts n’est pas de l’inspiration — c’est une méthode, et sa particularité est qu’elle emprunte au protocole expérimental plutôt qu’à l’écriture. On part d’une mesure, on modifie une variable, on remesure. Tout ce qui suit dans ce chapitre découle de cette discipline.

Le cycle est rigoureux :

  1. Définir l’objectif — Que doit faire le prompt, précisément ?
  2. Écrire un premier prompt — Version naïve, sans optimisation
  3. Évaluer — Mesurer les performances avec un pipeline d’évaluation
  4. Appliquer une technique — Une seule modification à la fois
  5. Re-évaluer — Mesurer l’impact de cette modification

Puis on répète les étapes 4 et 5 jusqu’à atteindre le score souhaité.

La règle d’or : un seul changement à la fois. Si vous modifiez trois choses en même temps et que le score monte, vous ne saurez pas laquelle a eu l’effet positif.

Mise en place de l’évaluateur

Sans évaluateur, les techniques des leçons suivantes resteraient des conseils qu’on applique de confiance. Avec lui, chacune devient une hypothèse vérifiable sur vos données — et vous découvrirez que leur ordre d’efficacité n’est pas le même selon les tâches. Le classement du tableau plus bas est celui observé sur cet exemple, pas une loi générale.

import anthropic
import json

client = anthropic.Anthropic()
MODEL = "claude-sonnet-5"

def evaluate_prompt(prompt_template: str, test_cases: list, criteria: list) -> dict:
    """Évalue un prompt sur un jeu de données avec des critères definis."""
    all_scores = []

    for case in test_cases:
        # Générer la réponse
        response = client.messages.create(
            model=MODEL,
            max_tokens=1024,
            messages=[{"role": "user", "content": prompt_template.format(**case["inputs"])}]
        )
        output = response.content[0].text

        # Noter la réponse
        scores = grade_response(output, case, criteria)
        all_scores.append(scores)

    # Calculer les moyennes
    avg = round(sum(s["moyenne"] for s in all_scores) / len(all_scores), 2)
    return {"detail": all_scores, "average": avg}

Générer des données de test

Plutôt que d’écrire manuellement chaque cas de test, on peut spécifier le format attendu et laisser Claude générer les données :

prompt_inputs_spec = {
    "nom_athlete": "Nom d'un athlete fictif",
    "sport": "Un sport parmi : course, natation, cyclisme, musculation",
    "objectif": "Un objectif sportif précis (ex: marathon en moins de 3h30)",
    "restrictions": "Restrictions alimentaires eventuelles (vegetarien, sans gluten, etc.)"
}

def generate_test_data(spec: dict, n: int = 5) -> list:
    """Génère n cas de test a partir d'une specification."""
    prompt = f"""Génère {n} cas de test varies au format JSON.
Chaque cas doit avoir une cle "inputs" contenant les champs suivants :
{json.dumps(spec, indent=2, ensure_ascii=False)}

Réponds uniquement avec un tableau JSON."""

    response = client.messages.create(
        model=MODEL,
        max_tokens=2048,
        messages=[{"role": "user", "content": prompt}]
    )
    return json.loads(response.content[0].text)

Exemple concret : plan alimentaire pour athlètes

Le prompt naïf (baseline)

PROMPT_V1 = "Cree un plan alimentaire pour {nom_athlete} qui fait du {sport}."

Ce prompt va “fonctionner” — Claude va générer quelque chose. Mais sans contraintes, le résultat sera imprévisible : parfois trop long, parfois trop court, parfois sans macronutriments, parfois avec des aliments inappropriés pour le sport en question.

Les critères d’évaluation

criteria = [
    {
        "nom": "pertinence_sport",
        "description": "Le plan est-il adapte au sport et a l'objectif de l'athlete ?",
        "poids": 3
    },
    {
        "nom": "completude",
        "description": "Le plan couvre-t-il tous les repas de la journée avec des quantités ?",
        "poids": 2
    },
    {
        "nom": "precision_nutritionnelle",
        "description": "Les calories, macros et timing sont-ils précises ?",
        "poids": 3
    },
    {
        "nom": "respect_restrictions",
        "description": "Les restrictions alimentaires sont-elles respectées ?",
        "poids": 2
    }
]

Premier résultat

Un mot sur ce premier score, car il est plus important qu’il n’y paraît : sa valeur absolue n’a aucune importance. Il ne sert qu’à donner un point de comparaison. Un baseline à 2 sur 10 n’est pas un mauvais départ, c’est un départ mesuré — et c’est ce qui permettra d’attribuer chaque gain à une technique précise. Avec le prompt naïf, attendez-vous à un score faible — probablement entre 2 et 4 sur 10. C’est normal et c’est le point de départ. Ne soyez pas découragé par un mauvais score initial : il sert de référence pour mesurer les progrès.

results_v1 = evaluate_prompt(PROMPT_V1, test_cases, criteria)
print(f"Score baseline : {results_v1['average']}/10")
# Score typique : ~3/10

La méthode en pratique

À partir de cette baseline, on va appliquer les techniques des leçons suivantes, une par une :

ÉtapeTechniqueImpact attendu
1Être clair et directScore passe de ~3 à ~4
2Être spécifiqueScore passe de ~4 à ~7-8
3Structurer avec XMLScore passe de ~7-8 à ~8-9
4Fournir des exemplesScore passe de ~8-9 à ~9+

Chaque technique a un impact mesurable. Les plus gros gains viennent des deux premières (clarté et spécificité). Les suivantes affinent les résultats.

Points clés

  • L’ingénierie de prompts est un processus itératif mesurable, pas de l’intuition
  • Commencez toujours par un prompt naïf pour établir une baseline
  • Un seul changement à la fois pour isoler l’impact de chaque modification
  • Les scores bas au départ sont normaux — c’est le point de référence
  • Générez vos données de test avec Claude pour gagner du temps, mais vérifiez-les
  • Définissez vos critères d’évaluation avant de commencer à optimiser