Aller au contenu principal

Exercice : évaluations de prompts

Mis à jour le 30 juillet 2026

Objectif

Construire un pipeline d’évaluation complet pour un prompt de résumé de CV. Vous allez :

  1. Écrire un prompt initial
  2. Créer un jeu de données de test
  3. Implémenter les fonctions d’évaluation
  4. Ajouter un notateur par modèle
  5. Mesurer un score de référence
  6. Améliorer le prompt et comparer les scores

Contexte

Vous développez un outil qui prend un CV professionnel et produit un résumé en 3 points clés. L’outil doit extraire les informations les plus importantes de manière concise et précise.


Étape 1 : Le prompt initial (naïf)

Commencez avec un prompt simple, sans optimisation :

PROMPT_V1 = "Resume ce CV en 3 points."

Étape 2 : Créer le jeu de données de test

Créez 3 CV fictifs couvrant des profils différents. Vous pouvez les écrire vous-même ou demander à Claude de les générer.

test_cases = [
    {
        "input": """CV - Sophie Martin
Poste actuel : Directrice Marketing chez TechVision (2020-present)
Experience precedente : Responsable Communication chez DataCorp (2015-2020)
Formation : Master Marketing Digital, HEC Paris (2014)
Competences : SEO/SEA, gestion d'equipe (12 personnes), budget 2M EUR/an
Realisations : +45% de leads qualifies en 2 ans, lancement de 3 produits SaaS
Langues : Francais (natif), Anglais (C1), Espagnol (B2)""",

        "expected_focus": "Marketing digital, management, résultats chiffres"
    },
    {
        "input": """CV - Ahmed Benali
Poste actuel : Developpeur Full-Stack Senior chez CloudNine (2021-present)
Experience precedente : Developpeur Backend chez StartupFlow (2018-2021), Stage chez IBM (2017)
Formation : Ingenieur Informatique, INSA Lyon (2018)
Competences : Python, TypeScript, React, AWS, Docker, Kubernetes, PostgreSQL
Realisations : Architecture microservices servant 2M utilisateurs, reduction latence de 60%
Certifications : AWS Solutions Architect, Kubernetes CKA
Langues : Francais (natif), Anglais (C1), Arabe (B1)""",

        "expected_focus": "Full-stack senior, cloud/DevOps, performance a grande echelle"
    },
    {
        "input": """CV - Marie Dupont
Poste actuel : Recherche d'emploi (disponible immediatement)
Derniere experience : Assistante de direction chez Groupe Renard (2019-2024)
Experiences precedentes : Assistante administrative chez PME Martin (2016-2019), Hotesse d'accueil chez EventPro (2014-2016)
Formation : BTS Assistant de Manager, Lycee Condorcet (2014)
Competences : Pack Office avance, gestion d'agenda, organisation d'evenements, redaction de comptes-rendus
Realisations : Organisation de 50+ evenements corporate, gestion simultanee de 3 directeurs
Langues : Francais (natif), Anglais (B1)""",

        "expected_focus": "Assistanat de direction, organisation, polyvalence"
    }
]

Étape 3 : Implémenter le pipeline d’évaluation

import anthropic

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

def run_prompt(cv_text: str, prompt_template: str) -> str:
    """Envoie le CV a Claude avec le prompt donne et retourne la réponse."""
    full_prompt = f"{prompt_template}\n\n{cv_text}"
    response = client.messages.create(
        model=MODEL,
        max_tokens=512,
        messages=[{"role": "user", "content": full_prompt}]
    )
    return response.content[0].text

def run_test_case(test_case: dict, prompt_template: str) -> dict:
    """Exécute un cas de test et retourne la réponse avec les métadonnées."""
    output = run_prompt(test_case["input"], prompt_template)
    return {
        "input": test_case["input"],
        "expected_focus": test_case["expected_focus"],
        "output": output
    }

Étape 4 : Le notateur par modèle

Le notateur évalue chaque résumé sur trois critères : exactitude, concision et couverture des informations clés.

def model_grader(result: dict) -> dict:
    """Note le resume sur 3 critères via un appel a Claude."""
    grading_prompt = f"""Tu es un evaluateur de resumes de CV. Évalue le resume suivant sur 3 critères, chacun note de 0 a 10.

CV original :
{result['input']}

Resume produit :
{result['output']}

Informations cles attendues : {result['expected_focus']}

Criteres :
1. **Exactitude** : Les informations du resume sont-elles correctes et fideles au CV ?
2. **Concision** : Le resume est-il court et va-t-il a l'essentiel (3 points, pas de superflu) ?
3. **Couverture** : Les informations les plus importantes sont-elles presentes (poste, competences cles, realisations) ?

Réponds UNIQUEMENT au format JSON :
{{"exactitude": X, "concision": X, "couverture": X}}"""

    response = client.messages.create(
        model=MODEL,
        max_tokens=100,
        messages=[{"role": "user", "content": grading_prompt}]
    )

    import json
    try:
        scores = json.loads(response.content[0].text)
        scores["moyenne"] = round(
            (scores["exactitude"] + scores["concision"] + scores["couverture"]) / 3, 2
        )
        return scores
    except (json.JSONDecodeError, KeyError):
        return {"exactitude": 0, "concision": 0, "couverture": 0, "moyenne": 0}

Étape 5 : La fonction d’évaluation complète

def run_eval(test_cases: list, prompt_template: str) -> dict:
    """Exécute l'évaluation complete et retourne les résultats."""
    print(f"\n{'='*60}")
    print(f"EVALUATION DU PROMPT")
    print(f"{'='*60}")
    print(f"Prompt : {prompt_template[:80]}...")
    print(f"Nombre de cas de test : {len(test_cases)}\n")

    all_scores = []

    for i, case in enumerate(test_cases):
        print(f"--- Cas de test {i+1} ---")
        result = run_test_case(case, prompt_template)
        scores = model_grader(result)

        print(f"Resume produit :\n{result['output']}\n")
        print(f"Scores : Exactitude={scores['exactitude']}, "
              f"Concision={scores['concision']}, "
              f"Couverture={scores['couverture']}, "
              f"Moyenne={scores['moyenne']}")
        print()

        all_scores.append(scores)

    # Score global
    avg_exactitude = round(sum(s["exactitude"] for s in all_scores) / len(all_scores), 2)
    avg_concision = round(sum(s["concision"] for s in all_scores) / len(all_scores), 2)
    avg_couverture = round(sum(s["couverture"] for s in all_scores) / len(all_scores), 2)
    avg_global = round(sum(s["moyenne"] for s in all_scores) / len(all_scores), 2)

    print(f"{'='*60}")
    print(f"SCORES GLOBAUX")
    print(f"  Exactitude : {avg_exactitude}/10")
    print(f"  Concision  : {avg_concision}/10")
    print(f"  Couverture : {avg_couverture}/10")
    print(f"  MOYENNE    : {avg_global}/10")
    print(f"{'='*60}")

    return {
        "detail": all_scores,
        "average": avg_global,
        "by_criteria": {
            "exactitude": avg_exactitude,
            "concision": avg_concision,
            "couverture": avg_couverture
        }
    }

Étape 6 : Exécuter, améliorer, comparer

Baseline (prompt naïf)

PROMPT_V1 = "Resume ce CV en 3 points."
results_v1 = run_eval(test_cases, PROMPT_V1)

Prompt améliore

PROMPT_V2 = """Tu es un expert en recrutement. Analyse le CV ci-dessous et produis un resume en exactement 3 points cles.

Regles :
- Chaque point commence par un tiret (-)
- Point 1 : Poste actuel et niveau d'experience (junior/confirme/senior)
- Point 2 : Competences techniques ou metier les plus differenciantes
- Point 3 : Realisation chiffree la plus marquante
- Maximum 25 mots par point
- Pas d'introduction ni de conclusion, uniquement les 3 points"""

results_v2 = run_eval(test_cases, PROMPT_V2)

Comparaison des résultats

print(f"\n{'='*60}")
print(f"COMPARAISON")
print(f"{'='*60}")
print(f"Prompt V1 (naif)    : {results_v1['average']}/10")
print(f"Prompt V2 (ameliore): {results_v2['average']}/10")
print(f"Amelioration        : {results_v2['average'] - results_v1['average']:+.2f} points")

Solution complète

Voici le code complet en un seul fichier :

"""
Pipeline d'évaluation complet pour un resume de CV.
Necessite : pip install anthropic
Variable d'environnement : ANTHROPIC_API_KEY
"""

import anthropic
import json

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

# --- Jeu de données ---
test_cases = [
    {
        "input": """CV - Sophie Martin
Poste actuel : Directrice Marketing chez TechVision (2020-present)
Experience precedente : Responsable Communication chez DataCorp (2015-2020)
Formation : Master Marketing Digital, HEC Paris (2014)
Competences : SEO/SEA, gestion d'equipe (12 personnes), budget 2M EUR/an
Realisations : +45% de leads qualifies en 2 ans, lancement de 3 produits SaaS
Langues : Francais (natif), Anglais (C1), Espagnol (B2)""",
        "expected_focus": "Marketing digital, management, résultats chiffres"
    },
    {
        "input": """CV - Ahmed Benali
Poste actuel : Developpeur Full-Stack Senior chez CloudNine (2021-present)
Experience precedente : Developpeur Backend chez StartupFlow (2018-2021), Stage chez IBM (2017)
Formation : Ingenieur Informatique, INSA Lyon (2018)
Competences : Python, TypeScript, React, AWS, Docker, Kubernetes, PostgreSQL
Realisations : Architecture microservices servant 2M utilisateurs, reduction latence de 60%
Certifications : AWS Solutions Architect, Kubernetes CKA
Langues : Francais (natif), Anglais (C1), Arabe (B1)""",
        "expected_focus": "Full-stack senior, cloud/DevOps, performance a grande echelle"
    },
    {
        "input": """CV - Marie Dupont
Poste actuel : Recherche d'emploi (disponible immediatement)
Derniere experience : Assistante de direction chez Groupe Renard (2019-2024)
Experiences precedentes : Assistante administrative chez PME Martin (2016-2019), Hotesse d'accueil chez EventPro (2014-2016)
Formation : BTS Assistant de Manager, Lycee Condorcet (2014)
Competences : Pack Office avance, gestion d'agenda, organisation d'evenements, redaction de comptes-rendus
Realisations : Organisation de 50+ evenements corporate, gestion simultanee de 3 directeurs
Langues : Francais (natif), Anglais (B1)""",
        "expected_focus": "Assistanat de direction, organisation, polyvalence"
    }
]

# --- Fonctions du pipeline ---
def run_prompt(cv_text: str, prompt_template: str) -> str:
    full_prompt = f"{prompt_template}\n\n{cv_text}"
    response = client.messages.create(
        model=MODEL,
        max_tokens=512,
        messages=[{"role": "user", "content": full_prompt}]
    )
    return response.content[0].text

def run_test_case(test_case: dict, prompt_template: str) -> dict:
    output = run_prompt(test_case["input"], prompt_template)
    return {
        "input": test_case["input"],
        "expected_focus": test_case["expected_focus"],
        "output": output
    }

def model_grader(result: dict) -> dict:
    grading_prompt = f"""Tu es un evaluateur de resumes de CV. Évalue le resume suivant sur 3 critères, chacun note de 0 a 10.

CV original :
{result['input']}

Resume produit :
{result['output']}

Informations cles attendues : {result['expected_focus']}

Criteres :
1. Exactitude : Les informations sont-elles correctes et fideles au CV ?
2. Concision : Le resume va-t-il a l'essentiel (3 points, pas de superflu) ?
3. Couverture : Les informations les plus importantes sont-elles presentes ?

Réponds UNIQUEMENT au format JSON :
{{"exactitude": X, "concision": X, "couverture": X}}"""

    response = client.messages.create(
        model=MODEL,
        max_tokens=100,
        messages=[{"role": "user", "content": grading_prompt}]
    )
    try:
        scores = json.loads(response.content[0].text)
        scores["moyenne"] = round(
            (scores["exactitude"] + scores["concision"] + scores["couverture"]) / 3, 2
        )
        return scores
    except (json.JSONDecodeError, KeyError):
        return {"exactitude": 0, "concision": 0, "couverture": 0, "moyenne": 0}

def run_eval(test_cases: list, prompt_template: str) -> dict:
    print(f"\n{'='*60}")
    print(f"EVALUATION")
    print(f"{'='*60}\n")

    all_scores = []
    for i, case in enumerate(test_cases):
        result = run_test_case(case, prompt_template)
        scores = model_grader(result)
        print(f"Cas {i+1} — Moyenne: {scores['moyenne']}/10")
        print(f"  Resume: {result['output'][:120]}...\n")
        all_scores.append(scores)

    avg = round(sum(s["moyenne"] for s in all_scores) / len(all_scores), 2)
    print(f"SCORE MOYEN : {avg}/10\n")
    return {"detail": all_scores, "average": avg}

# --- Execution ---
PROMPT_V1 = "Resume ce CV en 3 points."

PROMPT_V2 = """Tu es un expert en recrutement. Analyse le CV ci-dessous et produis un resume en exactement 3 points cles.

Regles :
- Chaque point commence par un tiret (-)
- Point 1 : Poste actuel et niveau d'experience
- Point 2 : Competences les plus differenciantes
- Point 3 : Realisation chiffree la plus marquante
- Maximum 25 mots par point
- Pas d'introduction ni de conclusion"""

print("=== PROMPT V1 (naif) ===")
r1 = run_eval(test_cases, PROMPT_V1)

print("=== PROMPT V2 (ameliore) ===")
r2 = run_eval(test_cases, PROMPT_V2)

print(f"\nCOMPARAISON : V1={r1['average']}/10 → V2={r2['average']}/10 ({r2['average']-r1['average']:+.2f})")

Ce que vous apprenez

  • Structurer un pipeline d’évaluation avec des fonctions réutilisables
  • Définir des critères de notation adaptés à votre cas d’usage
  • Mesurer l’impact d’un changement de prompt avec des métriques chiffrées
  • Itérer sur un prompt de manière méthodique plutôt qu’au feeling