Tous les articles Patterns RAG

Architecture RAG de production : du chunking au reranking, le guide complet

L'équipe RagNight · 15 min de lecture · 02 décembre 2025

Le guide complet pour passer d'un POC RAG à un système de production : chunking, embeddings, recherche hybride + RRF, reranking, pgvector/HNSW et évaluation RAGAS. Choix techniques 2026, code et checklist de mise en prod.

Il existe un gouffre entre un POC RAG et un RAG de production. Le POC se monte en une après-midi : quelques documents découpés, un modèle d'embedding, une base vectorielle, et la démo impressionne. Puis on le met entre les mains d'utilisateurs réels, sur un vrai corpus, avec de vraies questions — et la pertinence s'effondre. Réponses à côté, sources manquantes, hallucinations confiantes, latence erratique. Le POC répondait « souvent » ; la production doit répondre « juste, de façon fiable et mesurable ».

Ce guide parcourt l'architecture complète d'un RAG de production, maillon par maillon, avec les choix techniques à jour de 2026 et les pièges qui font échouer les projets. L'objectif n'est pas l'exhaustivité académique mais la décision : à chaque étape, quoi choisir, quels ordres de grandeur viser, et quels arbitrages assumer.

L'anatomie d'un pipeline RAG sérieux

Un RAG de production n'est pas « une base vectorielle et un LLM ». C'est une chaîne dont chaque maillon conditionne la qualité finale :

INGESTION
  parsing ─► nettoyage ─► chunking ─► embedding ─► indexation
RÉCUPÉRATION
  requête ─► recherche hybride ─► fusion ─► reranking ─► top-k
GÉNÉRATION
  contexte + question ─► LLM ─► réponse + citations
ÉVALUATION (boucle continue)
  golden set ─► métriques ─► amélioration
OBSERVABILITÉ (transverse)
  logs ─► coûts ─► latences ─► dérive de qualité

La règle d'or : la qualité se joue très en amont de la génération. Un mauvais chunking ou un mauvais embedding ne se rattrape pas par un meilleur prompt. On optimise dans l'ordre du pipeline, et on mesure à chaque étape. Les équipes qui inversent cette logique — peaufiner le prompt système avant d'avoir vérifié que les bons passages remontent — passent des semaines à traiter les symptômes plutôt que la cause.

Le chunking : la fondation sous-estimée

Le découpage des documents détermine ce que le système pourra retrouver. C'est l'étape la plus sabotée, parce qu'elle paraît triviale : « on coupe tous les 500 tokens ». Or un chunk est l'unité atomique de récupération. S'il mélange deux idées, l'embedding sera flou et la recherche imprécise. S'il tronque une idée, le passage récupéré sera incomplet et le LLM comblera les trous — par une hallucination.

Stratégies, de la plus naïve à la plus avancée :

  • Découpage fixe (par tokens/caractères + overlap) — simple, mais coupe au milieu des idées. À réserver aux cas où la structure est inexploitable.
  • Découpage récursif respectant la structure (paragraphes, titres, séparateurs) — bien meilleur, à privilégier par défaut. On coupe d'abord sur les frontières naturelles, et on ne tombe sur un découpage brut qu'en dernier recours.
  • Découpage sémantique — on coupe là où la similarité entre phrases consécutives chute, signalant un changement de sujet. Plus coûteux (il faut embedder chaque phrase), gain réel sur les textes longs et continus (rapports, articles de fond).
  • Structure-aware (Markdown, HTML, code) — ne jamais couper un bloc de code, un tableau ou une cellule en deux. Pour le code, découper par fonction ou par classe, pas par nombre de lignes.

Deux techniques 2026 qui changent la donne :

  • Late chunking (Jina) — au lieu d'embedder chaque chunk isolément, on passe le document entier (ou un large segment) dans le modèle, puis on agrège les embeddings au niveau token après coup pour produire un vecteur par chunk. Chaque chunk hérite ainsi du contexte global. Concrètement, le chunk « Le chiffre d'affaires a progressé de 12 % » garde le lien avec « Renault » mentionné trois paragraphes plus haut, alors qu'embeddé isolément il aurait perdu le sujet. Préserve les références à longue distance et les anaphores (« cette filiale », « ledit contrat »).
  • Contextual retrieval (Anthropic) — préfixer chaque chunk d'un court contexte généré par LLM avant l'embedding. Exemple concret :
Chunk brut :
  "La marge brute s'établit à 38,2 %, en recul de 1,4 point."

Chunk contextualisé (préfixe généré par LLM) :
  "[Extrait du rapport annuel 2025 de la société Acme, section
   « Performance financière », exercice clos au 31/12/2025.]
   La marge brute s'établit à 38,2 %, en recul de 1,4 point."

Anthropic rapporte une réduction notable du taux d'échec de récupération quand contextual retrieval est combiné à la recherche hybride. Le coût : un appel LLM par chunk à l'ingestion. On l'amortit avec le prompt caching (le document complet est mis en cache, seul le chunk varie) et on le réserve aux corpus où la qualité de récupération est critique.

Recommandations pratiques : viser 256-512 tokens par chunk selon le modèle d'embedding, un overlap de 10-20 %, et toujours conserver en métadonnées la source, la section, la date et la version. Un chunk trop grand dilue le signal sémantique ; un chunk trop petit perd le contexte. Testez deux ou trois tailles sur votre golden set plutôt que de copier une valeur par défaut.

Les embeddings : choisir son modèle

L'embedding transforme le texte en vecteurs. Le choix du modèle pèse sur la pertinence, le coût et la souveraineté.

Modèle Profil Atouts
text-embedding-3-large (OpenAI) API, jusqu'à 3072 dim Très performant, dimensions réglables
voyage-3 (Voyage AI) API Excellent rapport qualité/prix
embed v3 (Cohere) API Solide, multilingue
bge-m3 (BAAI) Open, multilingue Auto-hébergeable, souverain, dense+sparse
embeddings v3 (Jina) API/Open Late chunking natif
embed (Mistral) API EU Ancrage européen

Critères de décision : multilingue (crucial en contexte européen — bge-m3, Mistral, Qwen 3 brillent sur les corpus mêlant français, allemand et anglais), dimensions, coût, et open vs API selon vos exigences de souveraineté.

Dimensions, coût et stockage. Plus de dimensions = plus de finesse, mais aussi plus de stockage et de calcul de similarité. Un vecteur 3072 dimensions en float32 pèse environ 12 Ko ; sur 10 millions de chunks, cela représente près de 120 Go rien que pour les embeddings, avant l'index. D'où l'intérêt des deux leviers suivants.

Matryoshka / MRL (Matryoshka Representation Learning). Les modèles entraînés en Matryoshka (dont text-embedding-3-large) rangent l'information par ordre d'importance dans le vecteur : on peut tronquer un vecteur de 3072 à 1024 ou 512 dimensions en ne gardant que les premières composantes, avec une perte de qualité faible et progressive. En pratique, on stocke par exemple 1024 dimensions au lieu de 3072 et l'on divise par trois le coût de stockage et de recherche, pour quelques points de rappel perdus. C'est le réglage qualité/coût le plus rentable du pipeline.

Pour un corpus multilingue à exigence de souveraineté, bge-m3 auto-hébergé est souvent le meilleur compromis (dense + sparse en un seul modèle, données qui ne quittent pas votre infrastructure). Pour démarrer vite sans contrainte de données, text-embedding-3-large ou voyage-3. Règle absolue : ne jamais comparer des embeddings produits par deux modèles différents — un changement de modèle impose un ré-embedding complet du corpus.

La recherche hybride : dense + lexical

La similarité vectorielle comprend le sens mais rate le littéral : codes produits, acronymes, noms propres, numéros de version, identifiants. D'où la recherche hybride, qui combine :

  • Dense (vectoriel) — similarité sémantique. Capte « les contrats de résiliation anticipée » même si le document dit « rupture avant terme ».
  • Lexical (BM25) — correspondances de termes exacts. Capte la référence XR-4420-B ou l'acronyme RGPD que le vectoriel noie dans le bruit.

On fusionne les deux classements via le RRF (Reciprocal Rank Fusion), qui combine les rangs plutôt que des scores incomparables. La formule est simple : pour chaque document, on somme 1 / (k + rang) sur chaque moteur, avec k une constante (typiquement 60).

RRF(d) = Σ  1 / (k + rang_i(d))      avec k = 60

Exemple : un document classé 1er en dense et 3e en lexical
  score = 1/(60+1) + 1/(60+3) = 0,01639 + 0,01587 = 0,03226

Un document classé 2e en dense seulement
  score = 1/(60+2) = 0,01613
Requête
   ├──► recherche dense (pgvector / HNSW) ──► top-k_dense
   └──► recherche lexicale (BM25)         ──► top-k_lexical
                       │
                  fusion RRF
                       │
              candidats unifiés (top-N large, ex. 50)

L'élégance du RRF : il ne dépend pas de l'échelle des scores (une distance cosinus et un score BM25 ne sont pas comparables), seulement des rangs. Un document trouvé par les deux moteurs remonte fortement. C'est ce qui permet de capter à la fois le sens et le littéral dans un seul classement unifié.

Le reranking : récupérer large, trancher fin

Les 50 candidats fusionnés sont trop nombreux pour le LLM et mal ordonnés. Il faut comprendre pourquoi : l'embedding d'une requête et celui d'un document sont calculés indépendamment (bi-encoder), puis comparés par produit scalaire. C'est rapide et indexable, mais grossier. Un reranker (cross-encoder) lit la requête et chaque candidat ensemble, dans la même passe d'attention, et attribue un score de pertinence bien plus fin.

Bi-encoder (embedding) Cross-encoder (reranker)
Calcul Requête et doc séparément Requête + doc ensemble
Indexable Oui (pré-calculé) Non (à la volée)
Précision Correcte Élevée
Latence Très faible Élevée (proportionnelle au nombre de candidats)

Le pattern gagnant — entonnoir :

candidats (top-50) ──► reranker cross-encoder ──► top-8 ──► LLM
        (rappel)              (précision)
  1. Récupérer large (hybride, top-50) → privilégier le rappel.
  2. Reranker → privilégier la précision.
  3. Garder le top-5 à top-8 pour le contexte du LLM.

Latence. Un cross-encoder coûte cher : reranker 50 candidats ajoute typiquement quelques dizaines à quelques centaines de millisecondes selon le modèle et le matériel. C'est précisément pourquoi on ne reranke jamais tout le corpus — la recherche hybride réduit d'abord le champ à quelques dizaines de candidats. Le nombre de candidats rerankés (top-N) est un curseur direct latence/qualité : 50 est un bon point de départ, 100 si le rappel est insuffisant, 25 si la latence serre.

Rerankers matures en 2026 : Cohere Rerank 3, bge-reranker-v2-m3 (open, multilingue, souverain — auto-hébergeable sur GPU), Voyage rerank, le reranker de Jina.

pgvector en production

PostgreSQL avec l'extension pgvector est un choix de production sérieux : un seul système pour les données métier et les vecteurs, sous votre contrôle (donc souverain), avec les transactions, les jointures et le filtrage SQL que vous connaissez déjà.

L'index HNSW (Hierarchical Navigable Small World) est la clé de la performance en recherche approximative. C'est un graphe en couches qu'on navigue de proche en proche :

-- Index HNSW pour la similarité cosinus
CREATE INDEX ON document_chunks
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

-- Au moment de la requête, on règle le compromis rappel/latence
SET hnsw.ef_search = 100;
  • m — nombre de connexions par nœud. Valeur indicative 16 (jusqu'à 32-64 pour des corpus très grands exigeant un rappel maximal). Plus élevé = meilleur rappel, plus de mémoire et d'index plus lourd.
  • ef_construction — taille de la liste de candidats à la construction. Valeur indicative 64 (128-256 pour plus de qualité). Plus élevé = meilleur index, mais build plus lent.
  • ef_search — effort à la requête. Valeur indicative 40-100, réglable dynamiquement par session. C'est votre curseur rappel/latence en production : montez-le si le rappel manque, baissez-le si la latence serre.

Une requête de récupération enrichie, avec filtrage multi-tenant et métadonnées :

SET hnsw.ef_search = 100;

SELECT dc.id, dc.content, dc.section, dc.source_url,
       dc.embedding <=> $1 AS distance
FROM document_chunks dc
JOIN documents d ON d.id = dc.document_id
WHERE d.organization_id = $2            -- isolation du tenant
  AND d.status = 'completed'
  AND d.version = d.current_version      -- pas de contenu périmé
ORDER BY dc.embedding <=> $1             -- <=> = distance cosinus
LIMIT 50;

Note importante sur le filtrage : pgvector applique le filtre WHERE puis parcourt l'index HNSW. Sur des filtres très sélectifs, le rappel peut chuter (l'index ne « voit » pas assez de candidats valides) ; pensez à monter ef_search ou à utiliser un partitionnement par tenant.

Optimisations 2026 :

  • halfvec (16 bits, demi-précision) — divise par deux le stockage des vecteurs avec un impact minime sur la qualité. On indexe directement en halfvec : CREATE INDEX ON document_chunks USING hnsw ((embedding::halfvec(1024)) halfvec_cosine_ops). Précieux à grande échelle.
  • Quantization binaire — pousse la compression à l'extrême (1 bit par dimension) pour des corpus massifs où le stockage et la mémoire deviennent le facteur limitant ; on combine avec un re-scoring exact (re-ranking par distance complète) sur les meilleurs candidats pour récupérer la précision.
  • IVFFlat reste une alternative à HNSW : build plus rapide et moins gourmand en mémoire, mais rappel et latence généralement moins bons, et il faut choisir le nombre de listes (lists) en fonction de la taille du corpus. HNSW est le défaut recommandé pour la plupart des cas.

Pensez à conserver les métadonnées (source, section, version, permissions, date) dans des colonnes indexées : elles permettent le filtrage (par tenant, par version), la traçabilité et le tri. C'est aussi ce qui rend possible l'expiration du contenu périmé — un piège classique en production.

L'évaluation : la boucle qu'on saute toujours

Un RAG qu'on n'évalue pas est un RAG qu'on ne maîtrise pas. L'évaluation transforme l'optimisation « au feeling » en démarche pilotée. Sans elle, chaque changement de chunking ou d'embedding est un pari : on ne sait pas s'il améliore ou dégrade.

Constituer un golden set. Un jeu de 50 à 200 questions représentatives avec leurs réponses et sources attendues (les chunks ou documents qui devraient être récupérés). On le construit à partir des vraies questions des utilisateurs, en couvrant les cas faciles, les cas ambigus et les cas hors-périmètre (la bonne réponse étant alors « je ne sais pas »). C'est votre banc d'essai à chaque changement de chunking, d'embedding ou de reranking.

Les métriques RAGAS en détail :

  • Context recall — parmi les passages qui auraient dû être récupérés, combien l'ont été ? Mesure la qualité de la récupération (chunking + embedding + recherche). Une faible valeur signifie que l'information n'est même pas remontée : aucun prompt ne sauvera la réponse.
  • Context precision — les passages pertinents sont-ils bien classés en tête ? Mesure la qualité du classement (fusion + reranking). Une faible valeur signifie que le bon passage est noyé loin dans la liste.
  • Faithfulness — la réponse générée est-elle entièrement étayée par les sources récupérées (pas d'hallucination) ? Mesure la qualité de la génération.
  • Answer relevancy — la réponse répond-elle vraiment à la question posée, sans digression ?

LLM-as-judge : utiliser un LLM puissant pour noter automatiquement faithfulness et pertinence à l'échelle. Le piège est la fiabilité du juge : calibrez-le sur 20-50 notations humaines, vérifiez l'accord (le juge note-t-il comme un humain ?), et préférez des grilles binaires ou à 3 niveaux plutôt qu'une note continue de 1 à 10, plus bruitée.

La séquence d'optimisation efficace : mesurer le context recall d'abord (l'info remonte-t-elle ?), puis le context precision (est-elle bien classée ?), puis la faithfulness (le LLM s'en tient-il aux sources ?), puis l'answer relevancy. On corrige dans l'ordre du pipeline, en mesurant à chaque étape. Inutile de toucher au prompt tant que le recall est mauvais.

Observabilité et coût en production

Une fois en ligne, un RAG doit être instrumenté comme tout système critique. Trois axes à suivre en continu :

  • Qualité dans le temps. Rejouez le golden set à chaque déploiement et suivez les métriques RAGAS comme des tests de non-régression. Surveillez aussi la dérive du corpus : de nouveaux documents peuvent dégrader la précision (bruit) ou révéler des questions sans réponse. Branchez la détection des lacunes (requêtes à faible score de récupération) sur l'enrichissement du corpus.
  • Latence, décomposée par étape. Tracez chaque maillon : embedding de la requête, recherche dense, recherche lexicale, fusion, reranking, génération. La latence perçue est leur somme ; on n'optimise que ce qu'on mesure. Le reranking et la génération sont les postes les plus lourds.
  • Coût, décomposé par poste. L'embedding à l'ingestion (one-shot, mais lourd sur un gros corpus, surtout avec contextual retrieval), l'embedding des requêtes (récurrent), le reranking (par appel), et la génération (les tokens de contexte dominent — d'où l'intérêt de l'entonnoir qui limite à 5-8 chunks). Le prompt caching côté génération réduit fortement le coût quand le prompt système est stable.

Loggez systématiquement : la requête, les chunks récupérés (avec leurs scores), les sources citées, les versions de modèles (embedding, reranker, LLM) et la latence par étape. Sans cette traçabilité, un incident de pertinence est impossible à diagnostiquer — et la conformité (qui a vu quoi, sur quelle source) devient incertaine.

Checklist de mise en production

  • [ ] Chunking structure-aware, métadonnées conservées (source, section, version, date)
  • [ ] Modèle d'embedding choisi selon multilingue / coût / souveraineté ; dimensions ajustées (Matryoshka) si pertinent
  • [ ] Recherche hybride (dense + BM25) avec fusion RRF (k = 60)
  • [ ] Reranking en entonnoir (large → fin), top-N calibré sur la latence cible
  • [ ] Index HNSW réglé (m, ef_construction, ef_search), halfvec si l'échelle l'exige
  • [ ] Filtrage par permissions à la récupération (multi-tenant), ef_search ajusté pour les filtres sélectifs
  • [ ] Réponses sourcées + garde-fou anti-hallucination (« je ne sais pas »)
  • [ ] Golden set (50-200 questions) et métriques RAGAS en place, suivies dans le temps
  • [ ] Observabilité : journalisation requêtes/sources/versions, latence et coût par étape
  • [ ] Détection des lacunes branchée sur l'enrichissement du corpus

Les erreurs fréquentes

  • Optimiser le prompt avant la récupération — si les bons passages ne remontent pas (faible recall), aucun prompt ne sauvera la réponse.
  • Le tout-vectoriel — sans lexical, on rate les correspondances exactes (codes, acronymes, identifiants).
  • Pas de reranking — on noie le LLM dans des passages moyennement pertinents, et la faithfulness chute.
  • Aucune évaluation — impossible de savoir si un changement améliore ou dégrade ; on optimise à l'aveugle.
  • Corpus périmé — la meilleure architecture sert des réponses fausses si les sources sont obsolètes. Versionnez et expirez.
  • Changer de modèle d'embedding sans ré-embedder — mélanger des vecteurs de deux modèles produit des classements absurdes.

Conclusion

Un RAG de production n'est pas plus « intelligent » qu'un POC : il est plus rigoureux. Chaque maillon — chunking, embedding, recherche hybride, reranking, stockage, évaluation, observabilité — apporte sa contribution, et c'est leur somme qui sépare un système qui répond juste d'un système qui répond « à peu près ». Construisez dans l'ordre du pipeline, mesurez à chaque étape avec un golden set, instrumentez la qualité, la latence et le coût, et traitez la pertinence comme un indicateur à piloter, pas comme une magie à espérer. C'est ainsi qu'on franchit le gouffre entre la démo et la production.

Pour aller plus loin

  • Le chunking, l'étape la plus sous-estimée du RAG : stratégies 2026
  • Recherche hybride et reranking : pourquoi la similarité vectorielle seule échoue
  • Détecter les lacunes de votre base avec les requêtes utilisateurs

Prêt à brancher vos agents sur vos données ?

Démarrez gratuitement. Premier audit Knowledge Pulse en 60 secondes.

Démarrer gratuitement