Pourquoi votre pipeline RAG est sous-optimal
Les quatre pathologies structurelles qui affectent la majorité des systèmes RAG en production — et comment les corriger.
Pourquoi votre pipeline RAG est sous-optimal
La majorité des systèmes RAG déployés en production souffrent des mêmes pathologies structurelles. Non pas parce que les équipes manquent de compétences, mais parce que les tutoriels et les quickstarts ont normalisé des raccourcis qui deviennent des pièges à l'échelle. Sur les audits de pipelines RAG en production que nous avons menés, les mêmes quatre problèmes reviennent fréquemment — leur prévalence varie selon les équipes et les domaines.
Le chunking naïf : premier coupable
Le chunking à taille fixe est le péché originel du RAG industriel. Découper un document en blocs de 512 tokens sans considération sémantique produit des chunks qui brisent le raisonnement en plein milieu d'une phrase, d'un tableau ou d'un argument logique. Le retriever récupère alors des fragments incohérents, et le modèle génère en conséquence.
# Configuration naïve — à éviter
chunker = FixedSizeChunker(
chunk_size=512,
overlap=50
)
# Configuration sémantique — approche recommandée
chunker = SemanticChunker(
breakpoint_threshold_type="percentile",
breakpoint_threshold_amount=95,
min_chunk_size=200,
max_chunk_size=1000,
# Respect des frontières naturelles : paragraphes, sections
sentence_split_regex=r"(?<=[.!?])\s+",
)
# Chunking hiérarchique pour documents structurés
chunker = HierarchicalChunker(
parent_chunk_size=2048, # contexte large pour génération
child_chunk_size=256, # granularité fine pour retrieval
overlap_ratio=0.1
)Le chunking sémantique utilise des modèles de segmentation pour détecter les ruptures thématiques naturelles. Le chunking hiérarchique, popularisé par LlamaIndex, maintient deux niveaux de granularité : les petits chunks pour le retrieval précis, les grands chunks pour la génération contextuelle.
Les embeddings non spécialisés
Utiliser un embedding généraliste non évalué sur votre domaine sur un corpus médical, juridique ou technique est une erreur de conception. Ces modèles optimisent pour la similarité sémantique générale, pas pour la précision domaine-spécifique.
Le problème concret : dans un corpus de documentation API, "méthode POST" et "méthode agile" ont une similarité cosinus élevée avec un embedding généraliste. Un embedding spécialisé code-technique les distingue correctement.
Les alternatives selon le domaine :
- Code :
voyage-code-2,text-embedding-3-largeavec fine-tuning - Médical/juridique : modèles fine-tunés sur PubMed, corpus légaux
- Multilingue :
multilingual-e5-large,LaBSE - Long documents :
jina-embeddings-v2(8192 tokens de contexte)
L'absence de re-ranking
La récupération par similarité vectorielle est un premier filtre, pas une réponse finale. Les top-K résultats par similarité cosinus incluent invariablement du bruit. Le re-ranking est l'étape qui sépare les systèmes RAG amateurs des systèmes production.
Un cross-encoder comme cross-encoder/ms-marco-MiniLM-L-6-v2 re-score les candidats en considérant la requête et chaque document ensemble, ce qui est fondamentalement plus précis qu'une similarité vectorielle calculée séparément.
Le gain observé sur nos audits internes : +12 à +18 points de nDCG@10 après ajout d'un re-ranker, sur certains corpus testés. Ce chiffre dépend fortement du domaine, de la qualité des chunks et du modèle de base — il ne doit pas être lu comme universel.
Le retrieval hybride : dense + sparse
Le retrieval purement dense (vectoriel) échoue sur les requêtes lexicales précises : noms propres, identifiants, acronymes techniques. BM25 reste imbattable pour ce type de requête. La solution est le retrieval hybride avec fusion de scores.
# Reciprocal Rank Fusion — méthode robuste sans hyperparamètre critique
def reciprocal_rank_fusion(results_lists, k=60):
scores = {}
for results in results_lists:
for rank, doc_id in enumerate(results):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
return sorted(scores, key=scores.get, reverse=True)Recommandations actionnables
- Auditez vos chunks : calculez la distribution des tailles, visualisez des échantillons. Si vous voyez des phrases tronquées, migrez vers le chunking sémantique.
- Benchmarkez vos embeddings sur un jeu de test domaine-spécifique (50-100 paires requête/document gold) avant de choisir votre modèle.
- Ajoutez un re-ranker en priorité si votre pipeline n'en a pas — c'est le gain le plus rapide à obtenir.
- Activez le retrieval hybride : intégrez BM25 en parallèle du dense retrieval avec RRF. La plupart des frameworks (LangChain, LlamaIndex, Weaviate) le supportent nativement.
- Mesurez : mettez en place un benchmark RAGAS ou TruLens pour suivre faithfulness, answer relevancy et context precision à chaque itération.
Le RAG n'est pas un problème résolu. C'est un système d'ingénierie qui demande la même rigueur qu'un pipeline de données classique.