Construire un agent RAG qui sait dire « je ne sais pas »
- RAG
- LangChain
- Fiabilité
La plupart des démos RAG (Retrieval-Augmented Generation) fonctionnent bien sur les cas faciles : la question ressemble à un passage du corpus, la récupération renvoie le bon document, et le modèle répond correctement. Le problème arrive sur les 20 % de questions restantes — celles où le corpus ne contient pas vraiment la réponse.
Le vrai problème n’est pas la génération
On a tendance à traiter les hallucinations comme un problème de modèle de langage. En pratique, dans un pipeline RAG, c’est souvent un problème de récupération silencieuse : le retriever renvoie toujours des documents, même quand aucun n’est pertinent, et le modèle fait de son mieux avec ce qu’on lui donne.
Un LLM à qui on fournit trois passages non pertinents ne va (presque) jamais répondre « je ne sais pas » — il va essayer d’être utile, et donc inventer un pont entre la question et les passages.
Trois leviers qui changent vraiment le comportement
1. Un seuil de pertinence explicite, pas juste un top-k
Récupérer les k documents les plus proches n’est pas la même chose que récupérer des documents pertinents. Ajouter un seuil de score minimal — et accepter de retourner zéro document — est la modification la plus simple avec le plus d’impact :
def retrieve(query: str, k: int = 5, min_score: float = 0.72):
hits = vector_store.similarity_search_with_score(query, k=k)
return [doc for doc, score in hits if score >= min_score]
2. Faire du contexte vide un cas normal, pas une exception
Si retrieve() peut renvoyer une liste vide, le prompt doit gérer ce cas explicitement plutôt que de le traiter comme une erreur en amont :
Contexte : {context or "Aucun document pertinent trouvé."}
Si le contexte ne permet pas de répondre avec certitude,
réponds explicitement que tu ne sais pas plutôt que de deviner.
3. Une étape de vérification qui relit la réponse contre les sources
Un agent séparé, dont le seul rôle est de vérifier que chaque affirmation de la réponse est bien appuyée par au moins un passage récupéré, attrape une bonne partie des cas restants — au prix d’un aller-retour supplémentaire, généralement acceptable pour un usage qui n’est pas du temps réel strict.
Ce que ça change en pratique
Le résultat n’est pas un système parfait — il reste des faux négatifs (le système dit « je ne sais pas » alors que la réponse existait, mal formulée dans la requête). Mais le compromis est le bon pour la plupart des usages métier : mieux vaut un agent qui admet ses limites que celui qui invente avec assurance.