Aller au contenu principal
Leçon 17 sur 67 · Claude sur Amazon Bedrock

Ingénierie de prompt

Leçon 17 sur 67 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Le cycle d’amélioration
  2. Un évaluateur réutilisable
  3. Générer le jeu de test
  4. Le prompt naïf
  5. Lancer l’évaluation
  6. Ce que donnent les techniques
  7. À vous de jouer
  8. Points clés à retenir

Le pipeline d’évaluation est construit ; cette section s’en sert. L’ingénierie de prompt consiste à prendre un prompt existant et à l’améliorer pour obtenir des réponses plus fiables et de meilleure qualité. Le mot décisif est améliorer, au sens mesurable : chaque technique de la section devra prouver son gain à la note, sur le même fil rouge.

Le cycle d’amélioration

Le cycle d'amélioration d'un prompt Cinq étapes : fixer l'objectif, écrire un premier jet simple, l'évaluer pour obtenir une note de référence, appliquer une seule technique, réévaluer ; on répète les deux dernières étapes. INGÉNIERIE DE PROMPT Le cycle d'amélioration d'un prompt 1 Objectif ce que le prompt doit faire 2 Premier jet volontairement simple 3 Évaluation une note de référence 4 Technique un seul changement 5 Réévaluation le gain est-il réel ? on répète les étapes 4 et 5 Démonstration du cours officiel : 2,32 au départ, 7,86 après clarté et spécificité.
D'après la leçon « Prompt engineering » (Claude Academy, Claude with Amazon Bedrock).

Le cycle est simple : fixer un objectif, écrire un premier prompt, l’évaluer, appliquer une technique, puis réévaluer pour vérifier le gain. On répète les deux dernières étapes jusqu’à obtenir le niveau voulu. Règle d’or : un seul changement à la fois. Si vous modifiez trois choses et que la note monte, vous ne saurez pas laquelle a compté.

Le fil rouge de la section, repris du cours officiel : un prompt qui produit le plan de repas d’une journée pour un athlète, à partir de sa taille, de son poids, de son objectif et de ses restrictions alimentaires. La tâche est assez riche pour exercer toutes les techniques, et assez cadrée pour être évaluée proprement.

Un évaluateur réutilisable

Le cours officiel fournit une classe PromptEvaluator, dans le notebook de ses ressources, qui génère le jeu de test, exécute les cas en parallèle et note les réponses avec un modèle. Voici une version compacte qui assemble les pièces de la section 2 : sorties structurées pour le jeu de test et pour le verdict, et un pool de threads pour lancer plusieurs cas à la fois. Elle réutilise add_user_message, chat (leçon 10) et SCHEMA_EVAL (leçon 15).

import json
from concurrent.futures import ThreadPoolExecutor
from statistics import mean


class PromptEvaluator:
    def __init__(self, max_concurrent_tasks=3):
        self.max_concurrent_tasks = max_concurrent_tasks

    def generate_dataset(self, task_description, prompt_inputs_spec, num_cases=3, output_file="dataset.json"):
        schema = {
            "type": "object",
            "properties": {
                "cases": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "prompt_inputs": {
                                "type": "object",
                                "properties": {name: {"type": "string"} for name in prompt_inputs_spec},
                                "required": list(prompt_inputs_spec),
                                "additionalProperties": False,
                            },
                            "solution_criteria": {"type": "array", "items": {"type": "string"}},
                        },
                        "required": ["prompt_inputs", "solution_criteria"],
                        "additionalProperties": False,
                    },
                }
            },
            "required": ["cases"],
            "additionalProperties": False,
        }
        spec = "\n".join(f"- {name} : {description}" for name, description in prompt_inputs_spec.items())
        prompt = f"""Génère {num_cases} cas de test variés pour évaluer un prompt.

<tache>
{task_description}
</tache>

<entrees>
{spec}
</entrees>

Pour chaque cas, donne une valeur réaliste à chaque entrée,
et 1 à 3 critères qu'une bonne réponse doit remplir."""
        messages = []
        add_user_message(messages, prompt)
        dataset = json.loads(chat(messages, output_schema=schema))["cases"]
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(dataset, f, indent=2, ensure_ascii=False)
        return dataset

    def grade(self, test_case, output, extra_criteria):
        inputs = json.dumps(test_case["prompt_inputs"], indent=2, ensure_ascii=False)
        criteria = "\n".join(f"- {c}" for c in test_case["solution_criteria"])
        prompt = f"""Évalue la réponse d'une IA à partir des entrées et des critères suivants.

<entrees>
{inputs}
</entrees>

<criteres>
{criteria}
{extra_criteria}
</criteres>

<reponse>
{output}
</reponse>

Donne 1 à 3 points forts, 1 à 3 points faibles, une courte justification et une note de 1 à 10."""
        messages = []
        add_user_message(messages, prompt)
        return json.loads(chat(messages, output_schema=SCHEMA_EVAL))

    def run_evaluation(self, run_prompt_function, dataset_file="dataset.json", extra_criteria=""):
        with open(dataset_file, encoding="utf-8") as f:
            dataset = json.load(f)

        def run_case(test_case):
            output = run_prompt_function(test_case["prompt_inputs"])
            verdict = self.grade(test_case, output, extra_criteria)
            return {"test_case": test_case, "output": output,
                    "score": verdict["score"], "reasoning": verdict["reasoning"]}

        with ThreadPoolExecutor(max_workers=self.max_concurrent_tasks) as pool:
            results = list(pool.map(run_case, dataset))
        print(f"Note moyenne : {mean(r['score'] for r in results):.2f}")
        return results

Le client boto3 peut être partagé entre threads : la documentation de boto3 indique que les clients sont en général sûrs dans ce cas. Commencez avec une concurrence basse, 3 appels simultanés comme le conseille le cours officiel, pour ne pas déclencher les limites de débit de Bedrock ; augmentez-la selon vos quotas. La classe du cours officiel produit aussi un rapport output.html ; la nôtre renvoie les résultats, que vous pouvez enregistrer en JSON pour les relire.

Générer le jeu de test

evaluator = PromptEvaluator(max_concurrent_tasks=3)

dataset = evaluator.generate_dataset(
    task_description="Écrire le plan de repas compact d'une journée pour un athlète",
    prompt_inputs_spec={
        "height": "Taille de l'athlète en cm",
        "weight": "Poids de l'athlète en kg",
        "goal": "Objectif de l'athlète",
        "restrictions": "Restrictions alimentaires de l'athlète",
    },
    num_cases=3,
)

Chaque entrée du prompt est décrite une fois, et le générateur produit des combinaisons variées : tailles, objectifs et restrictions différents. Peu de cas pendant la mise au point, pour itérer vite ; davantage pour la validation finale.

Le prompt naïf

def run_prompt(prompt_inputs):
    prompt = f"""
Que devrait manger cette personne ?

- Taille : {prompt_inputs["height"]}
- Poids : {prompt_inputs["weight"]}
- Objectif : {prompt_inputs["goal"]}
- Restrictions alimentaires : {prompt_inputs["restrictions"]}
"""
    messages = []
    add_user_message(messages, prompt)
    return chat(messages)

« Que devrait manger cette personne ? » est volontairement vague : ni format, ni exigences, ni niveau de détail. C’est la version que chaque technique viendra améliorer.

Lancer l’évaluation

results = evaluator.run_evaluation(
    run_prompt_function=run_prompt,
    dataset_file="dataset.json",
    extra_criteria="""La réponse doit comprendre :
- le total calorique de la journée ;
- la répartition des macronutriments ;
- les repas, avec aliments exacts, portions et horaires.""",
)

extra_criteria dit ce que « bon » signifie pour cette tâche, et l’évaluateur note chaque réponse à cette aune. Dans le cours officiel, ce premier prompt obtient 2,32 sur 10. Une note de départ basse est normale : elle sert de point de comparaison.

Ce que donnent les techniques

ÉtapeTechniqueNote dans la démonstration du cours officiel
DépartPrompt naïf2,32
1Être clair et direct (leçon 18)3,92
2Être spécifique (leçon 19)7,86
3Structurer avec des balises XML (leçon 20)gain modeste sur ce prompt court
4Fournir des exemples (leçon 21)les meilleures réponses de l’évaluation deviennent des exemples

Ces chiffres valent pour la démonstration du cours officiel, avec son modèle et son jeu de test. Sur votre tâche, l’ordre d’efficacité peut changer, et c’est précisément ce que l’évaluation vous dira.

À vous de jouer

Votre point de départ. Choisissez un prompt de votre travail, décrivez ses entrées comme ci-dessus, générez trois cas avec generate_dataset, et mesurez sa note de départ.

Un journal de bord. Notez dans un tableau chaque modification que vous ferez au fil de cette section et la note obtenue après chacune. À la fin, vous saurez ce qui a vraiment compté pour votre tâche.

Sources officielles : Prompt engineering (Claude Academy) · Prompting best practices (documentation Claude) · Clients, multithreading (documentation boto3) · concurrent.futures (documentation Python)

Points clés à retenir

  • L’ingénierie de prompt est un cycle mesuré : objectif, premier jet, évaluation, technique, réévaluation.
  • Un seul changement à la fois, pour savoir ce qui a compté.
  • Un évaluateur réutilisable génère le jeu, exécute les cas en parallèle et note avec un modèle.
  • Concurrence basse au départ : les limites de débit de Bedrock s’appliquent.
  • Dans la démonstration du cours officiel, clarté puis spécificité font passer le plan de repas de 2,32 à 7,86.