Cursus
Votre pipeline RAG renvoie une réponse à la question d’un utilisateur. Elle paraît raisonnable, se lit bien et sonne convaincante. Mais en la comparant aux documents effectivement retrouvés, vous commencez à remarquer des éléments comme une date absente du contexte ou une recommandation qui contredit la source.
Détecter ces problèmes à grande échelle complique les choses. C’est précisément pour cela que des métriques comme BLEU et ROUGE ont été conçues pour la traduction automatique et le résumé, mais elles ne vous disent pas si la réponse du modèle est réellement fondée sur le contexte retrouvé ou si elle contredit la source.
L’évaluation humaine détecte ces subtilités, mais elle coûte trop cher à l’échelle (pensez à 10 000 requêtes ou plus). Il y a donc un fossé : les métriques automatisées sont rapides mais superficielles, tandis que la revue humaine est approfondie mais coûteuse et lente.
Utiliser un LLM comme juge se situe entre les deux. Vous prenez un modèle performant, vous lui fournissez un barème que vous avez rédigé et vous lui demandez d’évaluer les sorties de votre système comme le ferait un réviseur humain. Ce n’est pas parfait (je détaillerai plus loin les limites), mais cela vous offre un moyen pragmatique de suivre la qualité à une échelle qu’aucune métrique traditionnelle ni annotation manuelle ne peut atteindre seule.
Dans ce tutoriel, je vous guide pas à pas pour construire un juge LLM afin d’évaluer un système RAG, avec du code exécutable tout du long pour que vous puissiez tout reproduire sur votre machine.
Qu’est-ce que LLM as a judge ?
Le principe de LLM-as-a-judge consiste à demander à un modèle de langage d’évaluer des textes selon des critères que vous explicitez dans un prompt. Autrement dit, vous utilisez un LLM pour vérifier si le contenu généré par un autre modèle est satisfaisant ou non.
La raison pour laquelle cela fonctionne (j’étais moi-même sceptique au départ), c’est que l’évaluation est fondamentalement plus simple que la génération. Lorsqu’un modèle génère une réponse à partir de rien, il jongle entre de multiples contraintes à la fois :
- Exactitude
- Tonalité
- Respect des consignes
- Appui sur le contexte
- Ne pas suraffirmer en cas d’incertitude
Mais lorsqu’on fournit à ce même modèle une réponse finalisée et qu’on lui demande de vérifier des propriétés spécifiques, la tâche devient beaucoup plus ciblée : il s’agit d’évaluer, pas de créer. Et les modèles ont tendance à être plus constants sur cette tâche plus étroite.
Comparer les approches LLM-as-a-judge
En pratique, les équipes choisissent l’une de ces approches selon ce qu’elles cherchent à mesurer :
- Score direct : le juge note une sortie sur une échelle numérique (1 à 5, 1 à 10, selon votre barème). Vous obtenez un nombre et, si vous le demandez, une explication écrite du raisonnement. C’est le point de départ le plus courant, mais il existe un problème de calibration auquel je reviendrai.
- Comparaison par paires : deux réponses candidates sont évaluées côte à côte et le juge choisit la meilleure. Cela contourne totalement la calibration numérique car le juge rend un jugement relatif, pas un score absolu. Les équipes y ont souvent recours pour comparer des variantes de prompt ou des versions de modèle.
- Évaluation avec référence : on fournit au juge à la fois la sortie du modèle et une réponse de référence, puis on lui demande dans quelle mesure elles correspondent. Cela marche mieux pour les Q&R factuelles et les sorties structurées, lorsque vous disposez déjà d’un jeu de vérité terrain annoté.
- Classification binaire : on réduit le jugement à un succès/échec sur une propriété donnée. Cette réponse est-elle fidèle au contexte ? Contient-elle des informations personnelles identifiables ? Est-elle positive ? Ces contrôles binaires sont plus rapides, moins coûteux par évaluation et donnent des résultats plus réguliers que les approches numériques.

Image de l’auteur. Quatre approches de LLM as a judge.
Pour une synthèse directe des atouts, cas d’usage et limites, j’ai comparé les quatre approches dans le tableau suivant :
|
Approche |
Quand l’utiliser |
Forces |
Points de vigilance |
|
Score direct |
Suivi global de la qualité, monitoring continu |
Facile à analyser dans le temps, fonctionne sur des sorties unitaires |
Drift de calibration des juges |
|
Comparaison par paires |
A/B testing de modèles, comparaison de variantes de prompt |
Classements plus fiables que les scores absolus |
Double les appels API, pas de signal de qualité absolue |
|
Avec référence |
Q&R factuelles, sorties structurées |
Vérité terrain claire, évaluation facilitée |
Nécessite des données labellisées, pénalise des formulations valides alternatives |
|
Classification binaire |
Sécurité, détection d’hallucinations, conformité |
Ambiguïté faible, alertes faciles à automatiser |
Perte de nuance sur les cas limites |
Pour une vue d’ensemble plus large des approches d’évaluation au-delà du schéma du juge, LLM Benchmarks Explained couvre l’ensemble du sujet.
Comment fonctionne un juge LLM ?
Sous le capot, il s’agit d’un simple appel d’API : vous regroupez le contenu à évaluer (la sortie du modèle, la requête d’origine et le contexte retrouvé utilisé lors de la génération) et vous l’encapsulez dans un prompt indiquant au modèle juge ce qui vous importe et le format de réponse attendu.
Le juge traite le tout et renvoie une réponse structurée, généralement un score accompagné d’un raisonnement écrit expliquant l’attribution. La qualité de votre évaluation dépend presque entièrement de la qualité de votre barème. Je ne saurais trop insister.
Un prompt basique du type « notez cette réponse de 1 à 5 » produira des scores incohérents, car le juge ne sait pas précisément ce qui distingue un 3 d’un 4. Vous devez donc décrire concrètement à quoi correspond chaque niveau et, si possible, fournir des exemples.
Mettre en place LLM as a judge
Passons à la pratique : nous allons construire une chaîne d’évaluation complète depuis zero : un système RAG qui répond à partir d’une petite base de connaissances, un jeu de requêtes de test conçues pour déclencher différents modes d’échec, et un juge LLM qui note les sorties sur la fidélité et la pertinence.
Préparer l’environnement
Vous aurez besoin de Python 3.9+ et d’une clé API OpenAI, disponible dans la console OpenAI. Installez les dépendances :
pip install openai chromadb langchain langchain-openai langchain-community deepeval
Définissez votre clé API :
import os
os.environ["OPENAI_API_KEY"] = "your-key-here"
Nous utilisons OpenAI pour le générateur RAG et pour le juge LLM, avec des modèles différents (GPT-4o-mini pour la génération, GPT-4o pour le jugement). Pour les embeddings, text-embedding-3-small convient au cadre de ce tutoriel. En production, il est préférable de benchmarker plusieurs modèles d’embeddings sur vos données métier avant d’arrêter votre choix.
Si vous souhaitez consolider vos bases sur RAG avant de plonger dans l’évaluation, notre cours Retrieval Augmented Generation (RAG) with LangChain parcourt les fondamentaux.
Préparer les données et le magasin vectoriel
Il nous faut une petite base de connaissances pour que le système RAG y puise. J’utiliserai un ensemble d’extraits sur la politique de retour d’une entreprise fictive. Le contenu n’est pas l’objet principal ici, mais avoir un corpus limité facilite l’identification des moments où le modèle sort du contexte fourni (c’est précisément ce que le juge doit détecter).
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.schema import Document
# Sample knowledge base
documents = [
Document(
page_content="All customers are eligible for a full refund within 30 days of purchase. "
"The item must be in its original packaging and unused condition. Refunds are "
"processed to the original payment method within 5-7 business days.",
metadata={"source": "return_policy.pdf", "section": "refund_eligibility"}
),
Document(
page_content="Exchanges can be requested within 45 days of purchase for items of "
"equal or lesser value. Size exchanges on clothing are free of charge. "
"For items of greater value, the customer pays the difference.",
metadata={"source": "return_policy.pdf", "section": "exchanges"}
),
Document(
page_content="Electronics have a 15-day return window due to rapid depreciation. "
"Opened software and digital downloads are non-refundable. Defective electronics "
"can be returned within 90 days with proof of defect from an authorized service center.",
metadata={"source": "return_policy.pdf", "section": "electronics"}
),
Document(
page_content="Shipping costs for returns are covered by the company for defective items. "
"For non-defective returns, the customer is responsible for return shipping. "
"Free return shipping labels are available for loyalty program members regardless of reason.",
metadata={"source": "return_policy.pdf", "section": "shipping"}
),
Document(
page_content="Gift purchases can be returned with the gift receipt for store credit only. "
"Without a gift receipt, returns are processed at the lowest sale price in the last 90 days. "
"Gift cards and prepaid cards are non-refundable and cannot be exchanged.",
metadata={"source": "return_policy.pdf", "section": "gifts"}
),
]
# Create vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(documents, embeddings, persist_directory="./chroma_db")
print(f"Indexed {len(documents)} documents")
Cinq documents sur des politiques de retour : ce n’est pas énorme, mais suffisant pour illustrer les problèmes de récupération qui nous intéressent : contexte incomplet, segments hors sujet, et occasions d’hallucination lorsque le modèle se sent obligé de fournir une réponse complète alors que le contexte ne la justifie pas.
Construire un pipeline RAG basique
Le pipeline RAG récupère les segments pertinents puis génère une réponse. Rien de sophistiqué ici : le schéma standard retrieve-then-generate.
from openai import OpenAI
client = OpenAI()
def rag_query(question: str, top_k: int = 2) -> dict:
"""Run a RAG query: retrieve context, generate answer."""
# Retrieve
results = vectorstore.similarity_search(question, k=top_k)
context = "\n\n".join([doc.page_content for doc in results])
# Generate
system_prompt = """You are a helpful customer support assistant. Answer the
customer's question based ONLY on the provided context. If the context doesn't
contain enough information to answer fully, say so."""
user_prompt = f"""
Context: {context}
Question: {question}
Answer:
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.3
)
answer = response.choices[0].message.content
return {
"question": question,
"context": context,
"answer": answer,
"sources": [doc.metadata for doc in results]
}
J’ai choisi GPT-4o-mini comme générateur car il est économique et rapide, et nous voulons concentrer l’attention sur l’évaluation. La température est fixée à 0,3 pour réduire l’aléa sans le supprimer.
Le prompt système demande explicitement au modèle d’utiliser uniquement le contexte fourni, ce qui est la pratique standard en RAG, même si les modèles s’en écartent plus souvent qu’on ne le pense. C’est précisément ce que le juge doit signaler.
Testons :
result = rag_query("Can I return opened software?")
print(f"Question: {result['question']}")
print(f"Answer: {result['answer']}")
print(f"Sources: {result['sources']}")
Générer un jeu de données d’évaluation
Vous avez besoin de cas de test qui sollicitent différentes parties du pipeline. En production, vous les recueilleriez à partir des requêtes réelles d’utilisateurs. Pour ce tutoriel, je construis un mélange qui inclut délibérément des questions où les systèmes RAG trébuchent souvent.
eval_questions = [
# Straightforward questions (should be easy)
"What is the refund window for regular purchases?",
"Are exchanges free for clothing size changes?",
# Questions requiring synthesis across chunks
"What are my options if I received a defective laptop 60 days ago?",
# Edge cases likely to cause hallucination
"Can I get a refund for a digital download I purchased yesterday?",
"What happens if I return a gift without the gift receipt?",
# Questions where context might be incomplete
"Do you offer refunds for international orders?",
"Can I return an item I bought on sale?",
# Adversarial or tricky questions
"If I'm a loyalty member, do I get free return shipping even for electronics?",
]
# Generate RAG responses for all questions
eval_results = []
for q in eval_questions:
result = rag_query(q)
eval_results.append(result)
print(f"Q: {q}")
print(f"A: {result['answer'][:150]}...")
print()
Le mix est important. Certaines questions ont une réponse directe et claire dans les documents, tandis que d’autres exigent de combiner des informations issues de plusieurs segments (le cas de l’ordinateur portable défectueux mobilise la politique de remboursement à 30 jours et la clause électronique à 90 jours en cas de défaut prouvé).
Et quelques-unes, comme la question sur les commandes internationales, portent sur des sujets absents de la base de connaissances. Ce sont précisément celles où vous verrez le plus d’hallucinations : le modèle veut être utile et comble les lacunes avec des informations plausibles mais non fondées sur le contexte.
Pour aller plus loin sur la construction et le test de systèmes RAG, notre sélection Top 30 RAG Interview Questions and Answers est une référence utile.
Configurer le juge LLM
C’est ici que cela devient intéressant. Nous allons créer deux juges distincts :
- Juge de fidélité : la réponse reste-t-elle dans les limites du contexte retrouvé ?
- Juge de pertinence : la réponse traite-t-elle réellement la question posée ?
def judge_faithfulness(question: str, context: str, answer: str) -> dict:
"""Judge whether the answer is faithful to the retrieved context."""
eval_prompt = f"""
You are an impartial judge evaluating whether an AI assistant's
answer is faithful to the provided context.
Faithfulness means every claim in the answer can be traced back to
information in the context. The answer should not contain information
that isn't supported by or inferable from the context.
Score on a scale of 1 to 5:
1 - The answer contains multiple claims not supported by the context
2 - The answer contains at least one significant unsupported claim
3 - The answer is mostly faithful but includes minor unsupported details
4 - The answer is faithful with only trivial extrapolations
5 - Every claim in the answer is directly supported by the context
Context: {context}
Question: {question}
Answer to evaluate: {answer}
Respond in this exact JSON format: {{"score": <int 1-5>, "reason": "<one paragraph explanation>"}}
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": eval_prompt}],
temperature=0.0,
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
def judge_relevance(question: str, answer: str) -> dict:
"""Judge whether the answer is relevant to the question."""
eval_prompt = f"""
You are an impartial judge evaluating whether an AI assistant's answer
is relevant to the user's question.
Relevance means the answer directly addresses what the user asked.
A relevant answer may acknowledge limitations in available information,
but it should not go off-topic or provide unrelated information.
Score on a scale of 1 to 5:
1 - The answer does not address the question at all
2 - The answer partially addresses the question but misses the main point
3 - The answer addresses the question but includes significant irrelevant content
4 - The answer addresses the question well with minor tangents
5 - The answer directly and completely addresses the question
Question: {question}
Answer to evaluate: {answer}
Respond in this exact JSON format: {{"score": <int 1-5>, "reason": "<one paragraph explanation>"}}
"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": eval_prompt}],
temperature=0.0,
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
Quelques choix de conception à noter. La temperature est à 0.0 pour une régularité maximale. Nous utilisons response_format={"type": "json_object"} afin d’obtenir une sortie toujours analysable.
Le barème décrit concrètement chaque niveau de score plutôt que d’utiliser des étiquettes vagues comme « bon » ou « mauvais ». Sans ce niveau de précision, les juges ont tendance à attribuer 3 ou 4 à tout, ce qui n’apporte rien d’utile.
Notez que GPT-4o juge tandis que GPT-4o-mini génère. Avoir un juge plus capable que le générateur est courant : il faut une forte capacité de suivi d’instructions pour appliquer le barème de manière cohérente.
Si vous utilisez le même modèle pour les deux rôles, vous introduisez aussi un biais de préférence pour soi, documenté, où le modèle surévalue ses propres sorties.
Exécuter la boucle d’évaluation
Il est temps de tout lancer et de collecter les résultats.
import json
evaluation_report = []
for result in eval_results:
# Run both judges
faithfulness = judge_faithfulness(
result["question"], result["context"], result["answer"]
)
relevance = judge_relevance(
result["question"], result["answer"]
)
evaluation_report.append({
"question": result["question"],
"answer": result["answer"][:200],
"faithfulness_score": faithfulness["score"],
"faithfulness_reason": faithfulness["reason"],
"relevance_score": relevance["score"],
"relevance_reason": relevance["reason"],
})
print(f"Q: {result['question']}")
print(f" Faithfulness: {faithfulness['score']}/5 | Relevance: {relevance['score']}/5")
print(f" Faith reason: {faithfulness['reason'][:100]}...")
print()
# Summary statistics
faith_scores = [r["faithfulness_score"] for r in evaluation_report]
rel_scores = [r["relevance_score"] for r in evaluation_report]
print(f"Average faithfulness: {sum(faith_scores)/len(faith_scores):.2f}")
print(f"Average relevance: {sum(rel_scores)/len(rel_scores):.2f}")
print(f"Questions with faithfulness < 3: {sum(1 for s in faith_scores if s < 3)}")
Chaque question déclenche deux appels API à GPT-4o, un par juge. Pour nos huit requêtes de test, cela représente seize évaluations au total, ce qui reste gérable. En production avec des milliers de requêtes quotidiennes, vous voudrez les traiter par lot, de façon asynchrone, et probablement n’évaluer qu’un échantillon plutôt que chaque réponse.
Analyser les résultats et itérer
Les scores donnent une vue d’ensemble, mais c’est le raisonnement qui vous indique quoi corriger.
# Find problematic responses
print("=== LOW FAITHFULNESS (score < 4) ===")
for r in evaluation_report:
if r["faithfulness_score"] < 4:
print(f"\nQ: {r['question']}")
print(f"Score: {r['faithfulness_score']}")
print(f"Reason: {r['faithfulness_reason']}")
print(f"Answer preview: {r['answer'][:150]}...")
print("\n=== LOW RELEVANCE (score < 4) ===")
for r in evaluation_report:
if r["relevance_score"] < 4:
print(f"\nQ: {r['question']}")
print(f"Score: {r['relevance_score']}")
print(f"Reason: {r['relevance_reason']}")
Les questions sur les commandes internationales et les articles soldés obtiendront presque à coup sûr un faible score de fidélité, car la base de connaissances ne les couvre pas et le modèle aura probablement improvisé une réponse.
La question sur l’ordinateur défectueux est intéressante aussi : elle nécessite de synthétiser la politique générale de remboursement (30 jours) avec la clause électronique (90 jours pour défaut prouvé), et selon les segments récupérés, le modèle peut ou non avoir la vision complète.
La marche à suivre dépend des constats. Une faible fidélité sur certaines catégories de questions renvoie généralement à deux causes : soit le récupérateur extrait les mauvais segments (problème de retrieval), soit le générateur dépasse le contexte fourni (problème de génération).
Examiner le contexte extrait en regard de la réponse vous dira de quel côté chercher. Des scores de pertinence bas indiquent plutôt que le prompt système doit être ajusté, ou que le contexte récupéré est tellement hors sujet que le modèle n’a rien d’exploitable.
Pour l’opérationnalisation des évaluations dans votre pipeline de déploiement, le cours LLMOps Concepts couvre l’infrastructure et les schémas de workflow.
Utiliser DeepEval pour une évaluation structurée
Écrire des fonctions de juge personnalisées fonctionne, mais en production vous voudrez sans doute un framework pour gérer le boilerplate. DeepEval est l’une des options les plus mûres, avec des implémentations de métriques éprouvées couvrant les critères les plus courants.
from deepeval import evaluate
from deepeval.test_case import LLMTestCase
from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric
# Configure metrics
faithfulness_metric = FaithfulnessMetric(
threshold=0.7,
model="gpt-4o",
include_reason=True
)
relevance_metric = AnswerRelevancyMetric(
threshold=0.7,
model="gpt-4o",
include_reason=True
)
# Create test cases from our RAG results
test_cases = []
for result in eval_results:
test_case = LLMTestCase(
input=result["question"],
actual_output=result["answer"],
retrieval_context=[result["context"]]
)
test_cases.append(test_case)
# Run evaluation
evaluate(
test_cases=test_cases,
metrics=[faithfulness_metric, relevance_metric]
)
Ce que DeepEval apporte et qui est fastidieux à reconstruire vous-même :
- Mécanismes de retry quand le juge renvoie un JSON mal formé (plus fréquent qu’on ne le pense)
- Mise en cache des résultats pour éviter de doubler les coûts API lors des relances
- Intégration à Pytest pour brancher directement les évaluations LLM dans votre CI/CD.
Chaque métrique génère aussi une auto-explication : chaque score est accompagné d’un détail écrit du raisonnement du juge, à inspecter si quelque chose paraît anormal.
Pour une exploration approfondie des capacités de DeepEval, voir Evaluate LLMs Effectively Using DeepEval.
Bonnes pratiques pour LLM as a judge
Obtenir des chiffres d’un juge LLM est simple. Faire en sorte que ces chiffres aient un sens pour votre équipe demande plus de rigueur qu’on ne l’anticipe.
Frameworks et métriques d’évaluation
Au-delà de DeepEval, plusieurs frameworks existent et l’écosystème évolue vite. Voici une comparaison pratique selon l’usage cible de chacun :
|
Framework |
Idéal pour |
Support LLM judge |
Métriques spécifiques RAG |
Intégration |
|
DeepEval |
Suite d’évaluation complète, intégration CI/CD |
Oui, avec scores auto-explicatifs |
Fidélité, précision/rappel contextuels, pertinence |
pytest, LangChain |
|
RAGAS |
Évaluation de pipeline RAG spécifiquement |
Oui |
Fidélité, pertinence de la réponse, précision du contexte, rappel du contexte |
LangChain, LlamaIndex |
|
MLflow |
Suivi d’expériences avec évaluation |
Oui (natif ; peut aussi s’intégrer à DeepEval/RAGAS) |
Via intégrations tierces |
Écosystème MLflow |
|
Evidently |
Monitoring de production et détection de drift |
Oui, avec suivi continu |
Via évaluateurs personnalisés |
Tableaux de bord de monitoring |
|
LangSmith |
Traçage et évaluation natifs LangChain |
Oui |
Via évaluateurs personnalisés |
LangChain |
Pour les systèmes RAG, quatre métriques couvrent l’essentiel en pratique.
- Fidélité : indique si la réponse générée reste ancrée dans le contexte retrouvé. Un score à 0,6 signifie qu’environ 40 % des affirmations ne sont pas étayées par les documents fournis. C’est votre détecteur principal d’hallucinations et, d’expérience, la métrique la plus importante à suivre dans la durée.
- Pertinence de la réponse : évalue si la réponse traite réellement la question posée, ce qui est un sujet distinct. Une réponse peut être parfaitement fidèle au contexte et passer totalement à côté du sujet.
- Précision du contexte : côté retrieval : les documents pertinents sont-ils bien classés en tête ? Si le document contenant la réponse est récupéré en position 5 sur 5, votre retrieval fonctionne techniquement, mais le ranking est faible, ce qui dégrade la génération car les modèles prêtent plus d’attention à ce qui apparaît en premier.
- Rappel du contexte : à l’inverse, mesure la part d’informations nécessaires effectivement retrouvées. Un rappel faible est un problème d’infrastructure de retrieval, et aucun prompt engineering ne compensera un contexte absent.
Exécutez-les ensemble car différentes combinaisons de scores orientent vers des causes racines distinctes.
- Fidélité élevée et pertinence faible : le modèle reflète correctement le contexte, mais le contexte n’était pas pertinent pour la question.
- Fidélité faible et pertinence élevée : le modèle a compris la question mais a dépassé le contexte fourni pour y répondre.
Chaque combinaison indique où concentrer la correction.
Pour pratiquer le suivi d’évaluation dans MLflow, Evaluating LLMs with MLflow détaille l’integration.
Bonnes pratiques de déploiement en production
Le déploiement en production demande plus que d’exécuter des évaluations dans un notebook. À l’échelle, cinq catégories de problèmes pratiques méritent d’être anticipées avant de s’engager.
- Anticipez les biais connus. Les juges LLM notent systématiquement mieux les réponses plus longues (biais de verbosité) et favorisent légèrement la réponse affichée en premier en comparaison par paires (biais de position). L’atténuation standard du biais de position consiste à inverser l’ordre et ne compter le résultat que si le juge est cohérent dans les deux sens. Pour la verbosité, ajoutez dans le barème que la concision est acceptable, voire préférée ; l’effet diminue sans disparaître.
- Calibrez face au jugement humain avant de faire confiance aux scores. Rassemblez 50 à 100 exemples notés par des réviseurs humains dans votre domaine, faites-les passer au juge et mesurez le taux d’accord. En dessous de 75 %, votre barème nécessite un affinage. Répétez périodiquement, car le modèle juge et votre application évoluent.
- Vérifiez la constance séparément de l’exactitude. Exécutez deux fois les mêmes entrées et comparez les sorties. Si une réponse obtient 3 puis 5, votre barème laisse trop de place à l’interprétation. Dans ce cas, des évaluations binaires passent/échouent sont souvent plus fiables que des échelles à 5 points pour le monitoring, en réservant le détail numérique à l’analyse hors ligne.
- Maîtrisez les coûts à l’échelle. Les prompts d’évaluation sont bien plus longs (question, contexte, réponse, barème complet). À fort volume, une approche économique consiste à exécuter des évaluations LLM détaillées sur un échantillon aléatoire de 10 % des requêtes, tout en appliquant des contrôles automatisés simples (longueur, conformité de format, mots-clés) sur les 90 % restants.
- Gardez des humains dans la boucle. Même avec un juge fonctionnel en production, mettez en place une revue hebdomadaire aléatoire des évaluations. Surveillez particulièrement les 5/5 : ce sont précisément les cas où un raté créerait le plus de confiance mal placée.
Pour aller plus loin sur l’opérationnalisation de bout en bout, le parcours Associate AI Engineer for Data Scientists couvre le déploiement complet.
Conclusion
LLM-as-a-judge répond à un besoin pratique que ni les métriques automatisées traditionnelles ni la revue humaine ne couvrent seules à l’échelle. Les métriques automatiques passent à côté de ce qui compte réellement pour les applications LLM ; la revue humaine capte l’essentiel mais ne suit pas le rythme d’un système en production.
Un juge LLM entre les deux vous permet de suivre en continu la qualité des sorties avec une nuance que de simples métriques ne peuvent offrir.
Dans ce tutoriel, nous avons bâti une chaîne complète : un système RAG avec une petite base de connaissances, des requêtes de test conçues pour déclencher différents modes d’échec, des juges personnalisés pour la fidélité et la pertinence, et une approche outillée avec DeepEval plus proche de la production.
S’il y a une seule leçon à retenir, c’est que le barème fait tout. Investissez du temps pour écrire des critères spécifiques et concrets, avec des exemples clairs pour chaque niveau. Un barème bien conçu avec un modèle moyen surperformera toujours un barème vague avec le meilleur modèle.
Si vous souhaitez continuer à partir d’ici :
- Building a RAG System with LangChain and FastAPI fait passer le pipeline RAG du notebook au service de production.
- Developing LLM Applications with LangChain couvre le cycle de développement applicatif plus large, incluant chains, agents et mémoire.
- Introduction to LLMs in Python vaut la peine d’être revue pour consolider les bases avant d’aller plus loin.
- 12 LLM Projects For All Levels vous donne d’autres idées de projets pour vous entraîner.
- What is Retrieval Augmented Generation (RAG)? approfondit les fondements conceptuels de RAG.
FAQ sur LLM as a judge
Qu’est-ce que LLM-as-a-judge, concrètement ?
En bref : vous demandez à un modèle performant comme GPT-4 ou Claude d’attribuer un score ou de classifier la sortie d’un autre modèle, selon un barème que vous rédigez en langage clair. Cela ne remplace pas totalement la revue humaine, mais face à des milliers de réponses par jour, c’est le seul moyen pratique de suivre la qualité sans embaucher une armée d’annotateurs.
Que peut évaluer un juge LLM ?
Pratiquement tout ce que vous pouvez formuler comme critère. Fidélité aux documents source, tonalité, sécurité, capacité de la réponse à traiter la question, détection d’hallucinations, etc. Certaines équipes font aussi des comparaisons par paires, où le juge choisit la meilleure des deux réponses candidates. La flexibilité est le vrai atout.
Quelle est la précision des juges LLM par rapport aux humains ?
Environ 80 % d’accord avec les évaluateurs humains, selon la recherche, ce qui est proche du taux d’accord entre deux humains. Les juges LLM ont toutefois des biais : ils favorisent les réponses longues et détaillées même lorsqu’une réponse plus courte serait préférable, d’où la nécessité de concevoir le barème en conséquence.
Quels frameworks prennent en charge LLM-as-a-judge ?
DeepEval est apprécié car il s’intègre à pytest et traite les évaluations comme des tests unitaires, ce qui s’insère naturellement dans les workflows CI/CD. RAGAS a été conçu spécifiquement pour évaluer les pipelines RAG. MLflow a récemment ajouté des intégrations avec ces deux outils, afin de centraliser les métriques dans un même système de suivi. LangSmith et Evidently complètent les options principales.
Josep est data scientist et chef de projet à l'Office du tourisme de Catalogne, où il utilise les données pour améliorer l'expérience des touristes en Catalogne. Son expertise comprend la gestion du stockage et du traitement des données, associée à des analyses avancées et à la communication efficace des données.
Il est également un éducateur dévoué, enseignant le programme de Master Big Data à l'Université de Navarre, et contribuant régulièrement à des articles perspicaces sur la science des données sur Medium et KDNuggets.
Il est titulaire d'une licence en ingénierie physique de l'université polytechnique de Catalogne et d'une maîtrise en systèmes interactifs intelligents de l'université Pompeu Fabra.
Actuellement, il s'engage avec passion à rendre les technologies liées aux données plus accessibles à un public plus large par le biais de la publication ForCode'Sake sur Medium.
