L'évaluation des LLM
Mesurer ce qui compte : benchmarks, LLM-as-a-judge, évaluation du RAG, et les pièges de l'évaluation des modèles génératifs.
Évaluer un modèle de classification, c'est facile : on compare la prédiction à l'étiquette attendue, on compte les bonnes réponses, et l'on obtient une exactitude (accuracy). Évaluer un LLM est d'une tout autre nature. Ses sorties sont du texte libre, il n'existe presque jamais de vérité unique (une question peut se répondre de mille façons correctes), et la même requête peut donner des résultats radicalement différents selon la formulation du prompt ou la stratégie de décodage. Iusztin et Labonne le posent d'emblée : il n'y a aujourd'hui aucune approche unifiée pour mesurer la performance d'un LLM, seulement des recettes à adapter à chaque cas d'usage.
Ce chapitre suit la progression du livre. On commence par l'évaluation d'un modèle isolé (sans prompt engineering ni RAG) — benchmarks généralistes, spécifiques au domaine, spécifiques à la tâche — puis on passe à l'évaluation d'un système entier construit autour d'un pipeline de génération augmentée par récupération (RAG, retrieval-augmented generation). On termine par le cas concret du projet fil rouge, l'évaluation du modèle fine-tuné TwinLlama-3.1-8B à l'aide d'un LLM-juge (LLM-as-a-judge). L'objectif n'est pas de retenir une métrique magique, mais de comprendre quand et pourquoi mobiliser chaque technique.
Pourquoi l'évaluation des LLM est difficile
L'évaluation des modèles de ML classiques (machine learning) et celle des LLM divergent sur trois points, et ces différences expliquent toute la difficulté.
- Métriques numériques. Un modèle de ML traite des données structurées et vise un objectif étroit (prédire un prix, détecter une anomalie) ; on dispose alors de mesures objectives — exactitude, précision (precision), rappel (recall), erreur quadratique moyenne. Un LLM gère plusieurs tâches à la fois et se prête rarement à une seule métrique numérique.
- Ingénierie des caractéristiques (feature engineering). En ML traditionnel, une part du travail consiste à sélectionner et transformer les variables d'entrée, et la qualité de ce travail fait partie de l'évaluation. Les LLM consomment du texte brut, ce qui dissout cette étape.
- Interprétabilité. On peut souvent expliquer pourquoi un modèle de ML a prédit telle classe. Avec un LLM, cette lecture directe disparaît — mais on peut lui demander de justifier sa réponse pendant la génération, ce qui ouvre une fenêtre précieuse sur son raisonnement.
Note
Cette différence de nature a une conséquence pratique : plus une tâche est ouverte (rédiger un article, tenir une conversation), plus l'évaluation devient subjective et qualitative. À l'inverse, plus elle est structurée (classer, extraire des entités), plus on peut réutiliser les métriques de ML traditionnel. Toute la stratégie d'évaluation se décide sur cet axe ouvert/structuré.
Les benchmarks généralistes et leurs limites
Les évaluations généralistes (general-purpose) mesurent un large éventail de capacités corrélées à la connaissance et à l'utilité, sans cibler une tâche précise. Elles servent à comparer des modèles entre eux et à repérer forces et faiblesses. Le livre les répartit en trois moments.
Pendant le pré-entraînement, on surveille des métriques bas niveau directement liées à l'apprentissage : la perte d'entraînement (training loss), fondée sur l'entropie croisée (cross-entropy) ; la perte de validation (validation loss), calculée sur un jeu mis de côté pour jauger la généralisation ; la perplexité (perplexity), exponentielle de l'entropie croisée, qui mesure à quel point le modèle est « surpris » par les données (plus c'est bas, mieux c'est) ; et la norme du gradient (gradient norm), pour détecter les instabilités.
Après le pré-entraînement, on évalue le modèle de base avec une batterie de benchmarks publics et internes.
| Benchmark | Ce qu'il mesure | Format |
|---|---|---|
| MMLU | Connaissances sur 57 matières, du primaire au niveau professionnel | QCM |
| HellaSwag | Raisonnement de sens commun (compléter une situation) | Choix multiple |
| ARC-C | Raisonnement causal sur des questions de sciences (niveau scolaire) | QCM |
| Winogrande | Sens commun via la résolution de pronoms | Phrases construites |
| PIQA | Sens commun physique du quotidien | Questions |
Après le fine-tuning (entendu ici comme SFT, supervised fine-tuning, suivi d'un alignement de préférences), on ajoute des benchmarks ciblant le suivi d'instructions, la conversation multi-tours et les capacités agentiques : IFEval (suivre des contraintes précises, par exemple ne produire aucune virgule), Chatbot Arena (des humains votent pour la meilleure réponse entre deux modèles), AlpacaEval (évaluation automatique fortement corrélée à Chatbot Arena), MT-Bench (conversations multi-tours) et GAIA (usage d'outils, navigation web, en plusieurs étapes).
Attention
Ces benchmarks souffrent de défauts intrinsèques. Les benchmarks publics peuvent être truqués (gamed) en entraînant le modèle sur les données de test ou des échantillons trop proches : c'est la contamination (contamination). Le signal révélateur donné par les auteurs : améliorer le score MMLU d'un modèle de base de 10 points pendant le fine-tuning est invraisemblable — c'est presque toujours le signe d'un jeu d'instructions contaminé. L'évaluation humaine elle-même est biaisée vers les réponses longues, assurées et bien formatées (Markdown). Et les jeux de test privés, moins scrutés, ont leurs propres travers.
La conclusion d'Iusztin et Labonne est centrale : un benchmark n'est pas une source unique de vérité, mais un signal. Ce n'est que lorsque plusieurs évaluations indépendantes convergent que la confiance dans les capacités réelles d'un modèle devient légitime.
Évaluations spécifiques au domaine et à la tâche
Les modèles spécifiques au domaine (domain-specific) appellent des benchmarks taillés pour le domaine en question : on cherche alors des suites d'évaluation reproductibles, qui couvrent plusieurs facettes. Le Hub de Hugging Face héberge par exemple l'Open Medical-LLM Leaderboard (questions d'examens médicaux), le BigCodeBench Leaderboard (génération de code, classé par score Pass@1), le Hallucinations Leaderboard (tendance à produire des informations fausses sur 16 tâches) ou l'Enterprise Scenarios Leaderboard (cas d'usage métier réels, dont certains jeux fermés pour empêcher la triche).
Ces classements illustrent deux philosophies opposées : BigCodeBench se contente de deux métriques qui capturent suffisamment le domaine, tandis que le Hallucinations Leaderboard en agrège seize, dont beaucoup d'évaluations généralistes réutilisées. Leçon : on peut compléter des benchmarks sur mesure avec des benchmarks généralistes existants. Les modèles propres à une langue, eux, réutilisent souvent des versions traduites des benchmarks généralistes — de préférence traduites par des humains plutôt que par machine, pour la qualité (voir les leaderboards coréen, portugais et arabe).
Le livre dégage trois principes de conception communs à toute bonne évaluation : elle doit être complexe (distinguer bons et mauvais modèles), diverse (couvrir un maximum de scénarios) et pratique (facile à exécuter). Pour ce dernier point, les auteurs recommandent deux bibliothèques : lm-evaluation-harness d'EleutherAI et lighteval de Hugging Face.
Quand la tâche est structurée : métriques de ML
Les modèles spécifiques à la tâche (task-specific) sortent souvent des réponses structurées, plus faciles à mesurer avec des métriques classiques. Un résumé peut s'évaluer avec ROUGE (Recall-Oriented Understudy for Gisting Evaluation), qui mesure le chevauchement en n-grammes entre le texte généré et un texte de référence ; une tâche de classification ou d'extraction d'entités nommées (NER) avec l'exactitude, la précision, le rappel et le score F1 (moyenne harmonique de la précision et du rappel).
from rouge_score import rouge_scorer
# ROUGE compare un resume genere a une reference humaine.
# Force : objectif, reproductible, sans LLM-juge.
# Faiblesse : recompense le chevauchement lexical, pas le sens.
# Une reformulation correcte mais avec d'autres mots est penalisee.
scorer = rouge_scorer.RougeScorer(
["rouge1", "rougeL"], use_stemmer=True
)
reference = "Le modele DPO ecrit dans un style plus accessible."
candidat = "Avec le DPO, le style devient nettement plus lisible."
scores = scorer.score(reference, candidat)
print(scores["rougeL"].fmeasure) # faible : peu de mots communs Piège courant
ROUGE et BLEU mesurent le chevauchement de surface entre tokens. Sur de la génération ouverte, c'est leur grande faiblesse : une excellente réponse formulée avec d'autres mots que la référence obtient un mauvais score, et une mauvaise réponse qui recopie le vocabulaire de la référence peut bien s'en tirer. Ces métriques restent utiles pour le résumé et la traduction contraints, mais elles ne capturent ni la justesse factuelle ni la pertinence d'un texte libre.
Le QCM, étalon des tâches sans dataset existant
Faute de dataset préexistant, on peut bâtir un benchmark maison, inspiré des évaluations généralistes. Le motif le plus robuste est le question-réponse à choix multiple (multiple-choice question answering) : une question, plusieurs options, une seule bonne réponse, comme cet exemple tiré de MMLU (algèbre abstraite) où le modèle doit produire la lettre B.
Deux façons de noter ce schéma : la génération de texte (le modèle écrit A, B, C ou D, que l'on compare à la solution) et l'évaluation par log-vraisemblance (on regarde la probabilité que le modèle attribue à chaque option, sans génération). Les auteurs recommandent la version par génération : plus simple à implémenter, plus discriminante, et plus fidèle à l'usage réel — les modèles faibles ont tendance à surperformer artificiellement sur les évaluations par probabilité.
LLM-as-a-judge : faire noter par un LLM puissant
Quand la tâche est trop ouverte pour un QCM ou des métriques de ML, la technique reine est le LLM-juge (LLM-as-a-judge) : on demande à un LLM puissant de noter la qualité des réponses. Le livre en distingue trois variantes :
- Score absolu : on attribue une note sur une échelle (par exemple de 1 à 4) selon une grille (rubric) précise.
- Comparaison par paires (pairwise) : on présente deux réponses au juge, qui désigne la meilleure — c'est l'esprit de Chatbot Arena.
- Dimensions ciblées : on note séparément la pertinence, la toxicité, la cohérence, etc., ce qui ancre l'évaluation dans des catégories interprétables.
Le principe pratique : une échelle bien définie, un format de sortie structuré (pour parser les notes — via une instruction explicite, le mode JSON d'OpenAI, ou une bibliothèque comme Outlines), et l'exigence d'une explication avant la note. Cette explication est précieuse : elle révèle les erreurs de raisonnement du juge et permet de corriger le prompt par itérations successives.
JUGE_PROMPT = """Vous etes un evaluateur qui juge la qualite
d'une reponse a une instruction.
Notez sur une echelle de 1 a 4 :
1. La reponse n'est pas pertinente.
2. Pertinente mais peu utile.
3. Pertinente et utile, mais pourrait etre plus detaillee.
4. Pertinente, utile et detaillee.
Repondez ainsi :
##Evaluation##
Explanation: (analysez pertinence, utilite, complexite)
Total rating: (note finale, nombre entre 1 et 4)
Instruction:
{instruction}
Answer:
{answer}
"""
# Bonnes pratiques tirees du livre :
# - utiliser un GROS modele comme juge ;
# - lui faire ecrire l'explication AVANT la note ;
# - fournir une reponse de reference si on en a une.
def juger(client, instruction, answer):
prompt = JUGE_PROMPT.format(
instruction=instruction, answer=answer
)
# ... appel au modele juge, puis parsing de "Total rating"
return prompt À retenir
Le LLM-juge n'est pas neutre. Iusztin et Labonne listent ses biais : préférence pour les réponses assertives ou verbeuses (qui sonnent confiantes mais peuvent être moins exactes), manque d'expertise sur les domaines pointus, incohérence (deux réponses similaires notées différemment) et préférences implicites pour certains styles d'écriture sans rapport avec la qualité réelle. La littérature ajoute le biais de position (favoriser la première réponse présentée) et l'auto-préférence (un juge sur-note les sorties de sa propre famille de modèles).
Les parades recommandées : combiner le LLM-juge avec d'autres métriques, utiliser plusieurs juges, et concevoir soigneusement les prompts pour neutraliser les biais (par exemple en alternant l'ordre des réponses pour contrer le biais de position, ou en imposant des grilles strictes pour brider la prime à la verbosité). Si une réponse de référence (ground truth) existe, la fournir au juge améliore nettement la fiabilité de l'évaluation.
L'évaluation du RAG
Dès que le modèle est intégré dans un système — typiquement un pipeline RAG — l'évaluation change de dimension. Il ne s'agit plus de juger les seules capacités du modèle, mais l'ensemble : le récupérateur (retriever), l'intégration du contexte et la génération finale. Le livre décompose l'évaluation RAG en trois axes :
- Exactitude de la récupération (retrieval accuracy) : le système remonte-t-il les bons documents ?
- Qualité de l'intégration (integration quality) : le contexte récupéré est-il bien exploité dans la réponse ? On peut la mesurer en évaluant l'écart entre les réponses avec et sans contexte.
- Factualité et pertinence : la sortie répond-elle à la question tout en restant ancrée dans les documents fournis ?
+--------------------+
Question ----> | Retriever | --> mesure : precision /
| (base vectorielle)| rappel de recuperation
+--------------------+
|
contexte recupere
|
v
Question + contexte --> LLM --> Reponse finale
|
v
mesures : fidelite (faithfulness),
pertinence de la reponse (answer relevancy) Concrètement, l'évaluation du RAG croise donc deux familles de métriques : celles de la récupération (précision et rappel des documents remontés) et celles de la génération (factualité et cohérence du texte produit au regard du contexte).
Le cadre Ragas
Ragas (Retrieval-Augmented Generation Assessment) est une boîte à outils open source bâtie sur l'idée de développement piloté par les métriques (metrics-driven development) : suivre dans la durée des métriques essentielles pour décider sur des données plutôt qu'à l'intuition. Atout majeur, Ragas sait générer synthétiquement des jeux de test variés (questions, réponses, contextes) selon une approche évolutive inspirée d'Evol-Instruct — ce qui évite le travail manuel fastidieux de rédaction de centaines de cas.
Ragas fournit quatre métriques assistées par LLM, deux pour la génération et deux pour la récupération.
| Métrique | Axe | Ce qu'elle mesure |
|---|---|---|
| Fidélité (faithfulness) | Génération | Cohérence factuelle de la réponse avec le contexte : on décompose la réponse en affirmations et l'on vérifie que chacune se déduit du contexte (ratio d'affirmations vérifiables) |
| Pertinence de la réponse (answer relevancy) | Génération | À quel point la réponse colle à la question : un LLM génère des questions à partir de la réponse, puis on calcule la similarité cosinus moyenne entre ces questions et la question d'origine |
| Précision du contexte (context precision) | Récupération | Les éléments pertinents sont-ils bien classés ? Récompense les systèmes qui placent l'information la plus utile en tête |
| Rappel du contexte (context recall) | Récupération | À quel point le contexte récupéré couvre la réponse de référence : chaque affirmation de la vérité terrain est-elle attribuable au contexte ? |
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import (
faithfulness, answer_relevancy,
context_precision, context_recall,
)
# Une evaluation RAG minimale avec Ragas.
# Chaque ligne = une question, le contexte recupere,
# la reponse generee et (si dispo) la verite terrain.
donnees = Dataset.from_dict({
"question": ["Quelle est la politique de retour des PC?"],
"contexts": [["Retour sous 60 jours pour les PC en solde."]],
"answer": ["Vous avez 60 jours pour retourner un PC en solde."],
"ground_truth": ["Les PC en solde sont retournables 60 jours."],
})
resultat = evaluate(
donnees,
metrics=[
faithfulness, answer_relevancy,
context_precision, context_recall,
],
)
print(resultat) # un score par metrique, entre 0 et 1 Ragas fournit en outre des briques pour surveiller la qualité du RAG en production, fermant la boucle d'amélioration continue : ajuster l'algorithme de récupération, retravailler les prompts, ou rééquilibrer la part du contexte récupéré et de la génération.
Le cadre ARES
ARES (Automated RAG Evaluation System) adopte une voie complémentaire : il s'appuie sur des classifieurs fine-tunés plutôt que sur un LLM-juge à chaque appel. Son processus comporte trois étapes : génération de données synthétiques (modèle google/flan-t5-xxl par défaut), entraînement de classifieurs haute précision (microsoft/deberta-v3-large par défaut) pour juger pertinence et fidélité, puis évaluation du RAG à l'aide de ces classifieurs, avec intervalles de confiance.
| Critère | Ragas | ARES |
|---|---|---|
| Mécanisme de jugement | Métriques assistées par LLM | Classifieurs fine-tunés |
| Point fort | Évaluations nuancées, monitoring en production | Évaluation rapide et consistante une fois les classifieurs entraînés |
| Coût récurrent | Appels LLM à chaque évaluation | Coût d'entraînement initial, puis inférence bon marché |
| Génération de données synthétiques | Oui (approche évolutive) | Oui (configurable) |
Les deux outils ne s'opposent pas : le livre suggère de les combiner — itérer vite avec Ragas, puis lancer des évaluations approfondies et personnalisées avec ARES aux étapes clés.
Évaluer un modèle sur mesure : le cas TwinLlama
Le projet fil rouge a produit deux modèles fine-tunés pour rédiger posts et articles : TwinLlama-3.1-8B (SFT) et TwinLlama-3.1-8B-DPO. L'objectif est qu'ils écrivent un texte à la fois exact et bien écrit, dans un style naturel — là où les modèles instruct généralistes sont précis mais souvent verbeux et trop formels. Le problème étant ouvert, c'est un LLM-juge (ici GPT-4o-mini) qui notera sur une échelle de 1 à 3 selon deux critères : l'exactitude (correction factuelle) et le style (ton adapté au blog et aux réseaux sociaux, sans tournures académiques).
La démarche se déroule en trois temps. Générer les réponses d'abord : on charge le split de test du dataset d'instructions, on formate chaque instruction avec le bon template de chat, et l'on génère en lot avec vLLM — bien plus rapide que transformers pour la génération par lots de modèles locaux. On ajoute en référence le modèle officiel Meta-Llama-3.1-8B-Instruct pour mesurer les compromis.
from vllm import LLM, SamplingParams
from datasets import load_dataset
def generate_answers(model_id, dataset_name):
dataset = load_dataset(dataset_name, split="test")
# On reutilise le meme template pour tous les modeles.
dataset = dataset.map(lambda s: {"prompt": format_prompt(s)})
llm = LLM(model=model_id, max_model_len=4096)
# Temperature elevee pour la diversite, top_p/min_p pour
# ecarter les tokens improbables : un compromis qualite/variete.
params = SamplingParams(
temperature=0.8, top_p=0.95, min_p=0.05, max_tokens=4096
)
outputs = llm.generate(dataset["prompt"], params)
answers = [o.outputs[0].text for o in outputs]
dataset = dataset.add_column("answers", answers)
return dataset # puis push_to_hub() pour journaliser Évaluer les réponses ensuite : le prompt du juge décrit chaque critère avec une échelle de Likert à trois points précisément définie (1 = pauvre, 2 = correct, 3 = excellent), inclut deux exemples illustrant ce qu'est un « mauvais style » contre un « excellent style », et exige une sortie JSON ({"accuracy": {...}, "style": {...}}). Les appels sont parallélisés via un ThreadPoolExecutor, et le parsing se fait en mode best-effort : en cas d'erreur JSON, on retombe sur None plutôt que de planter.
import json, concurrent.futures
from openai import OpenAI
def evaluate_batch(batch, start_index):
client = OpenAI(api_key=OPENAI_KEY)
return [
(i, evaluate_answer(instr, ans, client))
for i, (instr, ans) in enumerate(batch, start=start_index)
]
# Parsing robuste : un JSON mal forme ne doit pas tout casser.
def parse_score(evaluation):
try:
d = (json.loads(evaluation)
if isinstance(evaluation, str) else evaluation)
return d["accuracy"]["score"], d["style"]["score"]
except (json.JSONDecodeError, KeyError, TypeError):
return None, None # repli silencieux Astuce
En sauvegardant les résultats intermédiaires (réponses, évaluations, scores poussés sur le Hub à chaque étape), le cadre d'évaluation devient robuste aux pannes et trivialement extensible à d'autres modèles, datasets ou critères. C'est l'équivalent d'un test de régression : on relance la même batterie après chaque itération de fine-tuning pour vérifier qu'on a progressé sans rien casser.
Analyser les résultats enfin, sur trois plans : les réponses, les explications du juge et les scores. La lecture manuelle, non scalable, reste cruciale pour débusquer les bugs grossiers (mauvais template, mauvais modèle). Sur l'exemple analysé, le modèle DPO simplifie le style du modèle SFT sans en altérer le contenu — exactement le comportement visé — tandis que Llama-3.1-8B-Instruct se révèle correct mais excessivement verbeux. Les scores moyens confirment le compromis :
| Modèle | Exactitude | Style |
|---|---|---|
| TwinLlama-3.1-8B (SFT) | 2,45 | 2,04 |
| TwinLlama-3.1-8B-DPO | 2,46 | 2,12 |
| Llama-3.1-8B-Instruct | 2,62 | 1,86 |
Lecture des chiffres : Llama-3.1-8B-Instruct l'emporte en exactitude (2,62), sans doute grâce à son post-entraînement massif (plus de 10 millions d'échantillons contre 13 000 ici) ; mais le modèle DPO domine en style (2,12), atteignant un ton plus accessible sans sacrifier le contenu. Le fine-tuning a donc réussi son pari : modifier le style sans dégrader le fond. Ce diagnostic précis — impossible à obtenir avec un simple score global — guide la prochaine itération (filtrage ou enrichissement du dataset).
Synthèse des méthodes d'évaluation
| Méthode | Ce qu'elle mesure | Forces | Limites |
|---|---|---|---|
| Perplexité / loss | Surprise du modèle face aux données | Bas niveau, suit l'entraînement en continu | Mal corrélée à l'utilité ressentie |
| MMLU et benchmarks généralistes | Connaissances, raisonnement, suivi d'instructions | Comparables, standardisés, larges | Contamination, faible représentativité de votre tâche |
| ROUGE / BLEU | Chevauchement n-grammes avec une référence | Objectif, reproductible, sans LLM | Aveugle au sens ; mauvais sur le génératif ouvert |
| F1 / précision / rappel | Exactitude sur tâches structurées | Rigoureux, interprétable | Inapplicable aux sorties libres |
| QCM maison | Capacité sur une tâche précise | Simple, discriminant, personnalisable | Demande de construire le dataset |
| LLM-as-a-judge | Qualité de texte libre (note, paire, dimensions) | Flexible, gère l'ouvert, fournit des explications | Biais (verbosité, position, auto-préférence), coût |
| Ragas / ARES | Récupération + génération d'un RAG | Couvre tout le système, données synthétiques | Dépend d'un LLM-juge ou de classifieurs à entraîner |
À retenir
- Évaluer un LLM est intrinsèquement difficile : sorties ouvertes, absence de vérité unique, sensibilité au prompt. La stratégie se choisit sur l'axe ouvert / structuré de la tâche.
- Les benchmarks (MMLU et consorts) sont des signaux, pas une vérité : méfiez-vous de la contamination et de leur faible représentativité de votre cas réel ; ne montez en confiance que lorsque plusieurs évaluations convergent.
- Les métriques de surface (ROUGE, BLEU) conviennent aux tâches contraintes mais ratent le sens du texte libre ; pour ce dernier, le QCM maison et le LLM-juge prennent le relais.
- Le LLM-as-a-judge est puissant mais biaisé (verbosité, position, auto-préférence) : atténuez avec une grille stricte, plusieurs juges, une référence terrain et l'exigence d'une explication avant la note.
- Évaluer un RAG suppose de mesurer séparément la récupération (précision, rappel du contexte) et la génération (fidélité, pertinence) ; Ragas (LLM-assisté, monitoring) et ARES (classifieurs) sont complémentaires.
- Bâtissez un cadre d'évaluation propre à votre tâche, avec un jeu de test interne, des résultats journalisés et des tests de régression : c'est ce qui transforme chaque itération de fine-tuning en progrès mesurable.