Le framework Evals d'OpenAI
Pourquoi évaluer systématiquement
Vous ne pouvez pas améliorer ce que vous ne mesurez pas. Quand vous changez un prompt, un modèle ou un paramètre, comment savez-vous que la qualité s’est améliorée ? Les évaluations (evals) transforment l’intuition en mesure objective. OpenAI fournit un framework d’évaluation intégré à la plateforme.
Le framework Evals
Accéder aux Evals
Les Evals sont accessibles sur platform.openai.com dans la section dédiée. Vous pouvez :
- Créer des jeux de données de test
- Définir des critères d’évaluation
- Exécuter des évaluations automatiques
- Comparer les résultats entre modèles et prompts
Concepts fondamentaux
- Dataset : un ensemble de cas de test avec entrées et sorties attendues
- Grader : un critère d’évaluation (correspondance exacte, LLM-as-judge, score)
- Run : une exécution d’évaluation sur un dataset avec un modèle/prompt donné
Créer un dataset de test
Structure du dataset
import json
# Un dataset est une liste de cas de test
dataset = [
{
"input": "Quelle est la capitale de la France ?",
"expected": "Paris",
"metadata": {"categorie": "geographie", "difficulte": "facile"},
},
{
"input": "Expliquez le théorème de Bayes en une phrase.",
"expected": "Le théorème de Bayes permet de calculer la probabilité "
"d'un événement en fonction de probabilités conditionnelles "
"connues.",
"metadata": {"categorie": "mathematiques", "difficulte": "moyen"},
},
{
"input": "Écrivez une fonction Python qui inverse une liste.",
"expected": "def inverser(lst): return lst[::-1]",
"metadata": {"categorie": "code", "difficulte": "facile"},
},
]
# Sauvegarder en JSONL
with open("eval_dataset.jsonl", "w") as f:
for cas in dataset:
f.write(json.dumps(cas, ensure_ascii=False) + "\n")
Générer un dataset à partir de la production
import openai
import random
client = openai.OpenAI()
def creer_dataset_depuis_logs(
logs_production: list[dict],
taille_echantillon: int = 100,
) -> list[dict]:
"""Crée un dataset d'évaluation à partir des logs de production."""
# Échantillonner
echantillon = random.sample(
logs_production,
min(taille_echantillon, len(logs_production)),
)
dataset = []
for log in echantillon:
dataset.append({
"input": log["prompt"],
"expected": log["reponse_validee"], # Réponse validée par un humain
"metadata": {
"source": "production",
"date": log["date"],
"modele_original": log["modele"],
},
})
return dataset
Types de graders
Grader à correspondance exacte
def grader_exact(reponse: str, attendu: str) -> dict:
"""Évalue si la réponse correspond exactement."""
score = 1.0 if reponse.strip().lower() == attendu.strip().lower() else 0.0
return {"score": score, "type": "exact"}
Grader par inclusion
def grader_inclusion(reponse: str, mots_cles: list[str]) -> dict:
"""Vérifie que la réponse contient les mots-clés attendus."""
reponse_lower = reponse.lower()
trouves = sum(1 for mot in mots_cles if mot.lower() in reponse_lower)
score = trouves / len(mots_cles) if mots_cles else 0.0
return {
"score": score,
"trouves": trouves,
"total": len(mots_cles),
"type": "inclusion",
}
Grader LLM-as-Judge
Le plus puissant : un autre LLM évalue la qualité de la réponse :
def grader_llm_juge(
question: str,
reponse: str,
attendu: str,
criteres: str = "exactitude, complétude, clarté",
) -> dict:
"""Utilise un LLM pour évaluer la qualité de la réponse."""
prompt_juge = f"""Évaluez la qualité de cette réponse sur une échelle de 1 à 5.
Question : {question}
Réponse attendue : {attendu}
Réponse à évaluer : {reponse}
Critères : {criteres}
Répondez UNIQUEMENT avec un JSON :
{{"score": <1-5>, "justification": "<explication courte>"}}"""
response = client.responses.create(
model="gpt-5.3",
input=prompt_juge,
temperature=0.0,
)
import json
try:
resultat = json.loads(response.output_text)
resultat["score_normalise"] = resultat["score"] / 5.0
return resultat
except json.JSONDecodeError:
return {"score": 0, "justification": "Erreur de parsing", "score_normalise": 0}
Exécuter une évaluation complète
async def executer_eval(
dataset: list[dict],
modele: str,
prompt_systeme: str,
grader_fn,
) -> dict:
"""Exécute une évaluation complète sur un dataset."""
resultats = []
for cas in dataset:
response = client.responses.create(
model=modele,
instructions=prompt_systeme,
input=cas["input"],
)
score = grader_fn(response.output_text, cas["expected"])
resultats.append({
"input": cas["input"],
"attendu": cas["expected"],
"obtenu": response.output_text,
**score,
})
# Calculer les métriques agrégées
scores = [r["score"] for r in resultats if "score" in r]
return {
"modele": modele,
"nb_cas": len(dataset),
"score_moyen": sum(scores) / len(scores) if scores else 0,
"score_min": min(scores) if scores else 0,
"score_max": max(scores) if scores else 0,
"resultats": resultats,
}
Points clés à retenir
- Les evals transforment l’intuition en mesure objective de la qualité
- Créez vos datasets à partir de cas réels de production
- Utilisez le grader LLM-as-Judge pour les évaluations nuancées
- Exécutez les evals avant chaque changement de prompt ou de modèle