Optimiser un système RAG : équilibrer précision de retrieval et qualité de génération

L’utilisateur demande « comment réinitialiser le mot de passe », le système renvoie « exigences de complexité du mot de passe » et « paramètres de sécurité du compte » — une erreur de retrieval RAG typique. Cause : le fossé sémantique entre « réinitialiser le mot de passe » (oral) et « procédure de réinitialisation du mot de passe » (formel). Trois goulots : fossé sémantique, faiblesse sur la correspondance exacte, contexte fragmenté par le découpage.
La réécriture de requête peut augmenter la précision de 15 % à 25 % ; Hybrid Search (BM25 + vecteurs + RRF) le rappel de 30 % à 50 % ; le chunking sémantique dépasse le fixe d’environ 11 points. Cet article décompose cinq volets — traitement des requêtes, recherche hybride, reranking, chunking, boucle d’évaluation — avec un cadre précision/latence.
I. Les trois goulots d’un système RAG
Avant de toucher aux réglages, clarifions ce contre quoi on lutte. Changer d’Embedding ou de base vectorielle sans effet ? Souvent ce n’est pas un seul maillon, mais plusieurs effets cumulés.
Fossé sémantique : l’utilisateur et le document ne parlent pas pareil
C’est probablement le cas le plus frustrant.
« Le système est tombé, que faire ? » dans la base : « procédure de reprise après incident de service ». Sémantiquement liés, le modèle vectoriel peut rater le lien — oral d’un côté, ton professionnel de l’autre.
Chez une banque, « ma carte est gelée, je fais quoi ? » renvoyait « procédure de perte de carte ». L’utilisateur voulait le déblocage, pas la déclaration de perte. Après réécriture de requête (« gelé » → « traitement de compte gelé »), le rappel s’est nettement amélioré.
En bref : un fossé entre la formulation de la question et celle des documents. L’Embedding fait de la similarité, pas de la télépathie.
Correspondance exacte : la limite du retrieval vectoriel
Fort en sémantique, faible quand il faut une correspondance stricte.
« Chiffre d’affaires Q3 2024 » vs « troisième trimestre 2024, 3,2 milliards » — souvent OK. « Quel trimestre a le plus vendu ? » — ce n’est plus de la similarité, c’est du calcul.
Autre piège : « OAuth 2.0 » et « OAuth 1.0 » proches en espace vectoriel mais protocoles différents. Mélanger les deux = mauvaise réponse.
D’après un rapport technique Tencent Cloud 2026, le retrieval vectoriel seul tourne autour de 60-70 % en domaine pro ; hybride avec mots-clés, souvent au-delà de 80 %.
Contexte fragmenté : le découpage coupe le sens
Comme déchirer un livre en feuillets — certains se recollent, d’autres non.
Chunk fixe : signature de fonction dans un bloc, corps dans un autre — l’utilisateur ne voit pas l’implémentation.
Même doc technique : fixe 500 tokens ≈ 62 %, sémantique (paragraphes, sections) ≈ 73 % — 11 points, une variable changée.
Pire : « Les inconvénients de cette approche sont… » en début de section, le détail au paragraphe suivant. Si seul le début est récupéré, le modèle dit qu’il y a des inconvénients sans les nommer.
Diagnostiquer avant d’ajuster — comme chez le médecin.
II. Traitement des requêtes : l’entrée fixe le plancher
Les questions varient, mais le retrieval part d’une seule chose : la requête brute. Mal traitée, tout le reste coûte double.
Comprendre ce que l’utilisateur veut vraiment
« Comment ça marche » sans contexte — « ça » reste flou. En Q&R sur base de connaissances, l’historique et la page courante aident.
Structurer l’intention en dimensions :
- Intention centrale : quoi savoir ? (fonction, composition, usage, dépannage)
- Entités : produit, version, période
- Contexte implicite : rôle, environnement
« Échec de réinitialisation du mot de passe » → dépannage / entité : réinitialisation / condition : tentative déjà faite. Plus précis que la phrase brute.
Étiqueter les questions
La classification d’intention en RAG réduit le bruit.
Tags prédéfinis : « compte », « paiement », « incident technique », « fonctionnalité ». Petit modèle ou LLM pour taguer, puis retrieval dans le sous-ensemble.
Moins de bruit, meilleure précision — VectorHub cite +15 % à +25 % ; mes tests, ~20 %.
Avec LangChain :
from langchain_core.runnables import RunnableLambda
def classify_intent(query: str) -> str:
# Exemple simple : correspondance par mots-clés
if "mot de passe" in query or "connexion" in query:
return "compte"
elif "paiement" in query or "remboursement" in query:
return "paiement"
# ... autres règles
return "general"
# Intégration dans la chaîne de retrieval
intent_chain = RunnableLambda(classify_intent)
En pratique, LLM pour l’intention = plus précis, plus cher.
Réécriture de requête par modèles
Transformer l’oral en style document.
| Question brute | Après réécriture |
|---|---|
| Comment ça marche | Méthode et étapes d’utilisation de [produit] |
| Pourquoi cette erreur | Analyse et résolution de [message d’erreur] |
| Y a-t-il plus rapide | Raccourcis pour [fonction] |
Modèles : maintenables, à itérer. Domaine ouvert : réécriture LLM en temps réel, meilleur mais plus lent et coûteux.
III. Recherche hybride + reranking : le saut de précision
Si la requête est l’entrée, l’hybride est le cœur du retrieval. En 2026, Hybrid Search est standard en entreprise.
Pourquoi une seule méthode ne suffit pas
Vecteurs : sémantique, pas les mots exacts. BM25 : mots exacts, pas le sens. Complémentaires.
Image : vecteurs = lecteur qui « comprend » ; BM25 = lecteur « littéral » sur OAuth 2.0 vs 1.0.
Hybride : deux passages, fusion — sémantique et exact.
Architecture en trois temps : BM25 → vecteurs → rerank
Étape 1 — BM25 : rappel large par mots-clés, rapide.
Étape 2 — vecteurs : ce que BM25 a manqué (sémantique sans mot-clé commun).
Étape 3 — Cross-Encoder : score fin query + chaque candidat.
Dasroot (blog) : hybride + RRF + rerank → +30 % à +50 % de rappel vs vecteur seul.
Fusion RRF
RRF convertit les rangs en scores et les additionne :
RRF_score = 1/(k + rank_BM25) + 1/(k + rank_vector)
k souvent 60, pour éviter qu’un seul classement domine.
LangChain :
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS
# Initialiser les deux retrievers
bm25_retriever = BM25Retriever.from_documents(documents)
vector_retriever = FAISS.from_documents(documents, embeddings).as_retriever()
# Retriever hybride
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6] # BM25 40 %, vecteurs 60 %
)
Ajuster les poids : docs à mots-clés nets (normes, juridique) → plus de BM25 ; FAQ, discussions → plus de vecteurs.
Cross-Encoder : le compromis
~+2 % de précision (rapports Medium), ~+100 ms de latence par candidat.
300-500 ms acceptables → rerank utile. Temps réel strict → hybride seul.
Conseil : mesurer hybride + RRF d’abord, ajouter Cross-Encoder seulement si le rappel reste insuffisant — sinon impossible d’isoler l’effet de chaque brique.
IV. Chunking et filtrage par métadonnées
Côté documents : comment découper et étiqueter. Bon chunking = retrieval efficace ; mauvais = informations en miettes.
Chunk sémantique vs fixe
Fixe : tous les N tokens — simple, coupe parfois une idée en deux.
Sémantique : fins de paragraphe, changement de section, fin de bloc de code — unités de sens plus cohérentes.
LangChain :
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=800, # max 800 tokens par chunk
chunk_overlap=150, # chevauchement 150 tokens
separators=["\n\n", "\n", ". ", " ", ""]
# paragraphe, ligne, phrase, mot
)
CSDN : même doc, 62 % fixe vs 73 % sémantique — écart qui se voit à l’échelle sur la satisfaction utilisateur.
Zone de chevauchement
Assurance contre la coupure au milieu d’une procédure.
Sans overlap, « étapes pour réinitialiser le mot de passe » peut ne renvoyer que la fin de la liste.
150-200 tokens de chevauchement : ~+25 % de rappel (CSDN et mes tests). Trop d’overlap = stockage et bruit — à équilibrer.
Métadonnées : rétrécir l’espace de recherche
Source, date, catégorie, auteur par chunk. Filtrer avant le match vectoriel.
« Processus de remboursement 2024 » → year: 2024, puis similarité sur « remboursement ».
# Filtrage par métadonnées (si supporté par la base)
results = vectorstore.similarity_search(
query="procédure de remboursement",
filter={"year": 2024, "category": "finance"}
)
Gain difficile à chiffrer universellement, mais net si vos docs sont classés et datés sur de longues périodes.
V. Génération et boucle d’évaluation
Le retrieval ne suffit pas : la génération compte, et les deux s’ajustent souvent ensemble.
Comment nourrir le modèle
Ne pas tout coller dans le contexte — limites de tokens et bruit.
Fusion de contexte : regrouper les chunks plutôt que concaténer aveuglément.
- Clustering de paragraphes proches pour réduire les doublons
- NER pour garder les passages avec entités importantes
Contexte plus dense → réponses plus ciblées.
Fenêtre glissante et échantillonnage
Beaucoup de docs : fenêtre glissante (top N chunks + reliquat de la tour précédente).
Échantillonnage par importance (TF-IDF, BM25) en phase génération — proche du rerank mais côté prompt.
Gain modeste (~3-5 %), utile quand le retrieval est déjà au plafond.
Évaluation quantitative : Ragas
Sans métriques, on règle à l’aveugle. Ragas est le framework RAG le plus répandu.
| Métrique | Sens | Cible |
|---|---|---|
| Faithfulness | Réponse fidèle au contexte récupéré | ≥ 0,80 |
| Context Precision | Pertinence du contexte | ≥ 0,70 |
| Context Recall | Couverture de l’information nécessaire | ≥ 0,75 |
| Answer Relevance | Réponse à la question posée | ≥ 0,80 |
from ragas import evaluate
from ragas.metrics import faithfulness, context_precision, answer_relevance
# Jeu d'éval : question, answer, contexts, ground_truth
results = evaluate(
dataset=eval_dataset,
metrics=[faithfulness, context_precision, answer_relevance]
)
Faithfulness 0,65 → hallucinations en génération ; Context Precision 0,50 → trop de bruit au retrieval. Ajuster là où ça baisse.
Boucle d’évaluation continue
- Baseline : Ragas sur jeu de test avant mise en prod
- Itération : réévaluer après chaque changement
- Monitoring : échantillons utilisateurs, revue humaine ou auto
- Feedback : prochain levier guidé par les scores
Sans boucle, optimisations en ordre dispersé ; avec boucle, amélioration systématique.
Conclusion
Un cadre rapide selon votre contexte.
Type de base de connaissances
Dynamique (actus, produits) → RAG. Stable (loi, normes) → fine-tuning envisageable. Souvent les deux en entreprise.
Exigence de précision vs latence
Support temps réel → vitesse : hybride + RRF, sans Cross-Encoder. Conseil expert tolérant 300-500 ms → ajouter rerank, voire multi-pass retrieval.
Commencer par l’évaluation
Beaucoup « optimisent » sans savoir quoi. Lancez Ragas, identifiez le maillon faible, puis ciblez : Precision basse → retrieval ; Faithfulness basse → traitement du contexte en génération.
Pas de silver bullet ni de ligne d’arrivée fixe — mais avec métriques et méthode, chaque pas a une direction. J’espère que cet article vous fera gagner du temps.
FAQ
Quel est le problème de retrieval le plus courant en RAG ?
Pourquoi la recherche hybride surpasse-t-elle le retrieval vectoriel seul ?
Quel impact du chunking sur la qualité de retrieval ?
Vaut-il la peine d'utiliser un reranking Cross-Encoder ?
Comment lire les métriques Ragas ?
RAG ou fine-tuning ?
8 min de lecture · Publié le: 21 avr. 2026 · Mis à jour le: 27 juil. 2026
Guide d'ingénierie RAG
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Choix de base de données vectorielle pour RAG : Pinecone vs Weaviate vs Milvus
Guide de sélection de base de données vectorielle pour RAG : comparaison approfondie de l'architecture, des performances, de la tarification et des cas d'usage de Pinecone, Weaviate et Milvus. Avec code d'intégration LangChain et formules de coût réel pour choisir le bon moteur de retrieval.
Partie 2 sur 5
Suivant
Routage de requêtes RAG en pratique : collaboration multi-bases vectorielles et distribution intelligente
Guide pratique du routage de requêtes RAG : comparaison systématique du routage logique, du routage sémantique et d'EnsembleRetriever, avec implémentation LangChain complète, Semantic Caching et stratégies d'optimisation des coûts via Tiered Retrieval.
Partie 4 sur 5



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire