Aller au contenu principal

Executer l'evaluation

Les 3 fonctions du pipeline

Le pipeline d’evaluation repose sur trois fonctions qui s’enchainent :

  1. run_prompt() : fusionne un cas de test avec le template de prompt et appelle Claude
  2. run_test_case() : execute le prompt puis note le resultat
  3. run_eval() : orchestre l’evaluation sur tous les cas de test

Le prompt a evaluer

On reprend le contexte de la lecon precedente : un assistant qui genere du code AWS.

PROMPT_TEMPLATE = """Tu es un expert AWS. Genere du code propre et fonctionnel.

Contexte : {context}
Type de sortie attendu : {type}

Requete : {input}"""

Les champs entre accolades ({context}, {type}, {input}) seront remplaces par les donnees de chaque cas de test.

Fonction 1 : run_prompt()

Cette fonction prend un cas de test et le template de prompt, fusionne les deux, et envoie a Claude :

import anthropic
import json

client = anthropic.Anthropic()

def run_prompt(test_case, prompt_template):
    """
    Fusionne le cas de test avec le template et appelle Claude.
    Retourne la reponse brute de Claude.
    """
    # Remplir le template avec les donnees du cas de test
    prompt = prompt_template.format(
        context=test_case["context"],
        type=test_case["type"],
        input=test_case["input"]
    )

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        temperature=0,  # Deterministe pour la reproductibilite
        messages=[{"role": "user", "content": prompt}]
    )

    return response.content[0].text

Note : temperature=0 est important pour l’evaluation. On veut des resultats reproductibles, pas de la creativite.

Fonction 2 : run_test_case()

Cette fonction execute le prompt et note le resultat. Pour l’instant, on met un score placeholder (on implementera la notation par modele dans la lecon suivante) :

def run_test_case(test_case, prompt_template):
    """
    Execute un cas de test : appelle Claude puis note la reponse.
    Retourne un dictionnaire avec l'input, la reponse et le score.
    """
    # Obtenir la reponse de Claude
    response = run_prompt(test_case, prompt_template)

    # Notation placeholder (sera remplacee par notation par modele)
    score = 10  # Score temporaire

    return {
        "input": test_case["input"],
        "type": test_case["type"],
        "context": test_case["context"],
        "difficulty": test_case.get("difficulty", "non specifie"),
        "response": response,
        "score": score
    }

Fonction 3 : run_eval()

La fonction principale qui orchestre l’ensemble :

def run_eval(dataset, prompt_template):
    """
    Execute l'evaluation complete sur tout le dataset.
    Retourne la liste des resultats et le score moyen.
    """
    results = []

    for i, test_case in enumerate(dataset):
        print(f"Cas {i+1}/{len(dataset)} : {test_case['input'][:50]}...")

        result = run_test_case(test_case, prompt_template)
        results.append(result)

        print(f"  Score : {result['score']}/10")

    # Calcul du score moyen
    avg_score = sum(r["score"] for r in results) / len(results)

    print(f"\n{'='*50}")
    print(f"Score moyen : {avg_score:.2f}/10")
    print(f"Cas evalues : {len(results)}")

    return results, avg_score

Charger le dataset et lancer

# Charger le dataset genere precedemment
with open("dataset.json", "r", encoding="utf-8") as f:
    dataset = json.load(f)

print(f"Dataset charge : {len(dataset)} cas de test\n")

# Lancer l'evaluation
results, avg_score = run_eval(dataset, PROMPT_TEMPLATE)

Sortie typique :

Dataset charge : 30 cas de test

Cas 1/30 : Ecris un script qui cree un bucket S3 avec un nom ...
  Score : 10/10
Cas 2/30 : Ecris une fonction Lambda qui declenche une notifi...
  Score : 10/10
...
Cas 30/30 : Genere une regex qui valide un ARN AWS avec region...
  Score : 10/10

==================================================
Score moyen : 10.00/10
Cas evalues : 30

Evidemment, avec le score placeholder a 10, tous les resultats sont parfaits. La prochaine lecon introduit la notation par modele pour obtenir des scores reels.

Examiner les resultats en detail

# Sauvegarder les resultats
with open("eval_results.json", "w", encoding="utf-8") as f:
    json.dump(results, f, indent=2, ensure_ascii=False)

# Analyser par categorie
from collections import defaultdict

scores_par_type = defaultdict(list)
for r in results:
    scores_par_type[r["type"]].append(r["score"])

print("\nScores par type :")
for type_code, scores in scores_par_type.items():
    avg = sum(scores) / len(scores)
    print(f"  {type_code:10s} : {avg:.2f}/10 ({len(scores)} cas)")

# Analyser par difficulte
scores_par_diff = defaultdict(list)
for r in results:
    scores_par_diff[r["difficulty"]].append(r["score"])

print("\nScores par difficulte :")
for diff, scores in scores_par_diff.items():
    avg = sum(scores) / len(scores)
    print(f"  {diff:10s} : {avg:.2f}/10 ({len(scores)} cas)")

Comparer deux prompts

Le but final : evaluer deux versions du prompt sur le meme dataset :

PROMPT_V1 = """Tu es un expert AWS. Genere du code propre et fonctionnel.

Contexte : {context}
Type de sortie attendu : {type}

Requete : {input}"""

PROMPT_V2 = """Tu es un ingenieur cloud AWS senior. Genere du code de qualite production.

Regles :
- Code commente et lisible
- Gestion des erreurs incluse
- Respecte les bonnes pratiques AWS

Contexte : {context}
Type de sortie : {type}

Requete : {input}"""

# Evaluer les deux versions
print("=== Evaluation V1 ===")
results_v1, score_v1 = run_eval(dataset, PROMPT_V1)

print("\n=== Evaluation V2 ===")
results_v2, score_v2 = run_eval(dataset, PROMPT_V2)

print(f"\nComparaison :")
print(f"  V1 : {score_v1:.2f}/10")
print(f"  V2 : {score_v2:.2f}/10")
print(f"  Delta : {score_v2 - score_v1:+.2f}")

Resume

Le pipeline est en place. Les trois fonctions se decomposent clairement :

FonctionRoleEntreeSortie
run_prompt()Appeler Claudecas + templatetexte brut
run_test_case()Executer + notercas + templateresultat + score
run_eval()Orchestrerdataset + templateresultats + moyenne

Il ne manque qu’une piece : remplacer le score placeholder par une notation reelle. C’est l’objet de la prochaine lecon.