Aller au contenu
RAG

Recherche, reranking et citations

Recherche vectorielle, BM25 et fusion RRF ; pré-filtrage par permissions et ses effets sur HNSW ; rerankers ; construction du contexte ; restitution des citations page par page ; garde-fous contre les hallucinations.

Hypothèse#rag#reranking#permissions#vector-dbPublié le 16 sept. 2026Mis à jour le 16 sept. 2026Vérifié le 16 sept. 2026À revérifier le 15 déc. 2026

L'essentiel

  • La recherche combine deux signaux : la similarité vectorielle (sens) et BM25 (mots exacts : numéros de pièce, noms propres, références d'articles). En droit, le second est indispensable.
  • La fusion se fait par RRF (k = 60, Cormack et al. 2009) : robuste, sans réglage, disponible nativement dans Qdrant, OpenSearch, Weaviate, LanceDB, à coder en SQL avec pgvector.
  • Le filtre de permissions s'applique dans la requête (pré-filtrage). Avec HNSW, un post-filtrage renvoie trop peu de résultats ; pgvector documente le problème et son remède (iterative_scan, 0.8.0) ; Qdrant intègre le filtre au graphe.
  • Un reranker (bge-reranker-v2-m3 ou Qwen3-Reranker-0.6B, Apache 2.0) reclasse 20 à 50 candidats et en garde 5 à 10 pour le LLM.
  • Chaque réponse cite dossier, document, page, extrait et lien. Une citation n'est pas une preuve de fidélité (« up to 57% of citations being post-rationalized ») : d'où des garde-fous et une évaluation.

Recherche vectorielle

La question est vectorisée avec le même modèle que les chunks (embeddings), puis la base renvoie les k vecteurs les plus proches (cosinus ou produit scalaire). L'index HNSW rend la recherche approximative mais rapide ; ses paramètres (m, ef_construction, ef_search) arbitrent rappel contre latence et mémoire. Sur quelques centaines de milliers de chunks, une recherche exacte (scan complet) reste envisageable en secours pour vérifier le rappel de l'index (estimation).

Ce que la recherche vectorielle rate : un numéro de pièce, une référence « L. 1235-3 », un nom de partie mal orthographié, une date précise. Ce sont pourtant les requêtes les plus fréquentes d'un avocat.

BM25 et recherche hybride

BM25 indexe les termes et pondère par fréquence et rareté. Il retrouve les identifiants exacts et les termes rares. La recherche hybride lance les deux recherches, sur le même filtre de permissions, puis fusionne.

MoteurHybride natifFusionSource
Qdrantvecteurs sparse + dense dans une même requêteRRF natif4
pgvector + PostgreSQLtsvector (ou ParadeDB, non vérifié) + pgvectorRRF à écrire en SQL (CTE)2
Weaviateoui, paramètre alpha (0 = BM25, 1 = vecteur)Relative Score Fusion par défaut depuis 1.24 ; filtres where appliqués post-fusion5
LanceDBouiRRFReranker() par défaut ; préfiltrage par défaut6
OpenSearchouinormalisation arithmétique, harmonique, géométrique ou RRF7
Open WebUI (intégré)ENABLE_RAG_HYBRID_SEARCH (défaut False), RAG_HYBRID_BM25_WEIGHT 0,5pondération linéaire12

Le français exige un analyseur adapté pour BM25 : lemmatisation ou au minimum stemming (french dans PostgreSQL), suppression des mots vides, gestion des apostrophes et des accents. Sans cela, « contrats » et « contrat » sont deux termes différents.

Reciprocal Rank Fusion

Score d'un document = somme, sur chaque liste de résultats, de 1 / (k + rang). Introduit par Cormack, Clarke et Büttcher (SIGIR 2009) ; k = 60 est la valeur empirique de l'article et k entre 40 et 80 donne des résultats équivalents ; la méthode ignore les scores bruts, donc s'accommode d'un score BM25 non borné et d'un cosinus entre 0 et 1 1. C'est le défaut d'OpenSearch, Elasticsearch, Azure AI Search, Weaviate (avant 1.24) et LanceDB. Pour la Box : RRF avec k = 60, 50 candidats par liste, sans pondération au départ ; la pondération éventuelle sera décidée par l'évaluation.

Pré-filtrage et post-filtrage

Le pré-filtrage a un coût que chaque moteur gère différemment :

  • pgvector : « With approximate indexes, filtering is applied after the index is scanned. If a condition matches 10% of rows, with HNSW and the default hnsw.ef_search of 40, only 4 rows will match on average » 2. Autrement dit, sans précaution, un avocat qui n'a accès qu'à 10 % des dossiers obtient 4 résultats au lieu de 40, parfois zéro. Remèdes documentés : augmenter ef_search, créer des index partiels par dossier, et depuis la 0.8.0 activer hnsw.iterative_scan = relaxed_order (ou strict_order) qui « will automatically scan more of the index until enough results are found », borné par hnsw.max_scan_tuples (défaut 20 000) et hnsw.scan_mem_multiplier. Ce n'est pas une fuite mais une perte de rappel silencieuse, exactement ce qu'il faut mesurer.
  • Qdrant : le filtrage sur le payload est intégré à la traversée HNSW ; un index payload marqué is_tenant: true regroupe physiquement les vecteurs d'un même dossier et rend la recherche filtrée efficace 3.
  • Weaviate : en hybride, la doc indique d'appliquer les clauses where « post-fusion », ce qui demande vérification avant tout usage ACL 5.
  • LanceDB : préfiltrage par défaut 6.

Azure justifie aussi le pré-filtrage par la performance : « Filtering inside the search pipeline is faster than loading larger result sets into your application and trimming there » 14.

Reranking

Le bi-encodeur (embeddings) compare la question et le chunk séparément ; le cross-encodeur (reranker) lit les deux ensemble et produit un score bien plus fin, au prix d'un passage par paire. On l'applique donc à une liste courte.

ModèleLicenceTailleLanguesRemarquesSource
BAAI/bge-reranker-v2-m3Apache 2.0environ 0,6 Mdmultilinguebase bge-m3 ; référence courante ; fiche bge-reranker-v2-m38
Qwen3-Reranker 0.6B / 4B / 8BApache 2.00,6 à 8 Mdplus de 100contexte 32k, instruction-aware ; MTEB-R 65,80 pour le 0.6B (chiffres éditeur) ; fiche qwen3-reranker-8b9
Jina-ColBERT-v2 (late interaction)non trouvée (CC BY-NC pour les versions précédentes)89un vecteur par token, stockage lourd ; à vérifier avant tout usage10
CrossEncoder Open WebUIselon modèleRAG_RERANKING_MODEL, vide par défaut ; RAG_TOP_K_RERANKER 312

Hypothèse de départ : bge-reranker-v2-m3 sur GPU (ou CPU si la mémoire GPU est réservée au LLM), 40 candidats en entrée, 8 en sortie, seuil de score minimal pour rejeter les passages hors sujet plutôt que de les donner au modèle. À comparer avec Qwen3-Reranker-0.6B sur le corpus fictif.

Top-k et fenêtre de contexte

Le nombre de passages transmis au LLM est un compromis : trop peu, la réponse rate une pièce ; trop, le modèle se disperse et la fenêtre de contexte se remplit, ce qui allonge le TTFT et consomme du KV cache partagé entre utilisateurs (multi-utilisateurs).

Ordre de grandeur (hypothèse) : 8 passages de 600 tokens = environ 5 000 tokens de contexte documentaire, plus la question, l'historique et les consignes : 6 000 à 8 000 tokens par requête. Avec un modèle à 128k de contexte, la limite n'est pas la fenêtre mais le temps de prompt processing sur la machine candidate, à mesurer dans les benchmarks. Open WebUI ne transmet que 3 passages par défaut (RAG_TOP_K 3) 12, ce qui est faible pour du juridique.

Le prompt de génération contient : la consigne de répondre uniquement à partir des passages, de citer leurs numéros, et de dire quand l'information n'y est pas ; puis les passages numérotés avec leur en-tête (dossier, pièce, page) ; puis la question. Rappel : ces consignes servent la qualité, pas la sécurité.

Citations : restituer page, passage et lien

Chaque passage envoyé au modèle porte un numéro et ses métadonnées. Le modèle référence les numéros ; l'interface les remplace par des cartes :

Élément affichéMétadonnée sourceOrigine
Dossierdossier_id, nomtable des dossiers
Documentnom_fichier, typeingestion
Page ou sectionpage_debut, sectionDocling
Extraittexte du chunk, surlignébase
Lienchemin transformé en URL (visionneuse interne, lien SMB file://, lien SharePoint) ouvrant à la page, avec la zone bbox surlignée quand la visionneuse le permetingestion + interface

RAGFlow annonce des « grounded citations » ancrées dans le document 13 ; c'est le niveau visé : cliquer sur une citation ouvre la pièce à la bonne page, passage surligné. Cela suppose que le lien respecte lui aussi les permissions : la visionneuse vérifie la portée avant de servir le fichier (une seconde fois, indépendamment de la recherche).

Deux compléments utiles : afficher les passages récupérés non utilisés dans la réponse (l'avocat voit ce que le système a lu) et un bouton « signaler une citation fausse » qui alimente le jeu d'évaluation.

Hallucinations et garde-fous

Une réponse est fondée « when it correctly answers a question using only the information in the documents, and the response can be inferred from the inline citations » ; or une étude mesure « up to 57% of citations being post-rationalized » : le modèle cite après avoir répondu, pas parce qu'il a lu 11. Les hallucinations en RAG prennent trois formes : réponse hors des passages, citation qui ne soutient pas la phrase, mélange de deux dossiers.

Garde-fous, du plus simple au plus coûteux :

  1. Seuil de pertinence au reranking : sous le seuil, la Box répond « rien dans les documents accessibles » au lieu d'inventer.
  2. Consigne de refus et exemples dans le prompt ; température basse.
  3. Vérification des citations : après génération, vérifier que chaque numéro cité existe dans la liste fournie et que la phrase citée a un recouvrement lexical minimal avec le passage (règle simple, peu coûteuse).
  4. Second passage de vérification par le LLM (« cette phrase est-elle soutenue par ce passage ? ») sur les réponses longues : coûteux, à réserver aux usages sensibles.
  5. Évaluation hors ligne de la fidélité (Ragas, DeepEval) sur le jeu de test (évaluation).
  6. Isolation par dossier dans le prompt : quand la portée couvre plusieurs dossiers, grouper les passages par dossier et le dire au modèle, pour limiter les mélanges.

Questions ouvertes

Ce qu'il reste à tester

Sources

  1. 1Reciprocal Rank Fusion — explications (ParadeDB, BigData Boutique)Article techniqueFiabilité moyenneParadeDB / BigData Boutique · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  2. 2pgvector — README (filtrage, HNSW, iterative scan 0.8.0)GitHubFiabilité hautepgvector · publié v0.8.6 (README) ; 0.8.0 annoncé sur postgresql.org · consulté le 16 sept. 2026 · fiche source
  3. 3Qdrant — Multitenancy (payload partitioning, is_tenant)Documentation officielleFiabilité hauteQdrant · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  4. 4Qdrant — README et releases (Apache 2.0, v1.19.1)GitHubFiabilité hauteQdrant · publié v1.19.1, 04/09/2026 · consulté le 16 sept. 2026 · fiche source
  5. 5Weaviate — multi-tenancy native et recherche hybrideDocumentation officielleFiabilité hauteWeaviate · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  6. 8BAAI/bge-reranker-v2-m3 — model cardDocumentation officielleFiabilité hauteBAAI · publié 02/2024 · consulté le 16 sept. 2026 · fiche source
  7. 9Qwen/Qwen3-Reranker — model card (0.6B / 4B / 8B)Documentation officielleFiabilité hauteAlibaba Qwen · publié 05/06/2025 · consulté le 16 sept. 2026 · fiche source
  8. 10Jina-ColBERT-v2 — late interaction multilingueArticle techniqueFiabilité moyenneJina AI · publié 2024 (arXiv 2408.16672) · consulté le 16 sept. 2026 · fiche source
  9. 11Citations et fidélité en RAG (arXiv 2412.18004, 2409.11242)ÉtudeFiabilité moyennearXiv · publié 2024 · consulté le 16 sept. 2026 · fiche source
  10. 12Open WebUI — variables d'environnement (docs + config.py)Documentation officielleFiabilité hauteOpen WebUI · publié lu le 16/09/2026 (main) · consulté le 16 sept. 2026 · fiche source
  11. 13RAGFlow — README (Apache 2.0, DeepDoc, prérequis)GitHubFiabilité hauteInfiniFlow · publié v0.27.2, lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  12. 14Azure AI Search — Document-Level Access ControlDocumentation officielleFiabilité hauteMicrosoft · publié 08/08/2026 (mise à jour 31/08/2026) · consulté le 16 sept. 2026 · fiche source
content/docs/rag/recherche-reranking.md1736 mots