Chapitre 5 — Architecturer la chaîne de recherche
Cinquième billet de la tournée chapitre par chapitre de LLM Primer III : Améliorer l'IA d'entreprise avec RAG. Une seule recherche vectorielle est là où la plupart des prototypes s'arrêtent, et là où la plupart des échecs de production commencent. Le chapitre parcourt le chemin complet, d'une requête mal formulée aux candidats finaux qui atteignent le générateur — et pourquoi chaque étape existe.
Pourquoi ce chapitre existe
Les Chapitres 2 à 4 ont produit un magasin de vecteurs : documents analysés, découpés avec soin, embarqués, indexés. L'étape suivante naïve est d'embarquer la requête de l'utilisateur, de lancer une recherche du plus proche voisin, et de fournir le top-k au générateur. Pour des corpus triviaux, cela marche. Pour la production, presque jamais. Les requêtes arrivent sous-spécifiées et truffées de noms propres que l'embedder n'a jamais vus ; les corpus contiennent des quasi-doublons qui se pressent en tête de tout classement unique ; identifiants et codes portent un sens que l'embedder lisse.
Le Chapitre 5 porte sur l'architecture sur laquelle les systèmes mûrs convergent. Ce n'est pas un artefact de recherche. C'est la forme que les équipes font effectivement tourner quand rappel, précision et latence doivent tenir simultanément.
5.1 Pourquoi une seule recherche vectorielle ne suffit pas
La recherche dense réécrit l'économie de la recherche, mais la tolérance même à la paraphrase qui rend les embeddings utiles les rend aussi fragiles. Les tokens numériques, citations de statuts, codes de transactions, numéros de pièces — tout ce dont la forme de surface est le sens — atterrissent dans des recoins arbitraires de l'espace vectoriel. BM25, qui se contente de compter ce qui est là, n'a pas ce problème.
Les deux méthodes échouent sur des entrées disjointes. Cette seule observation est l'argumentaire complet pour la recherche hybride, et c'est le premier principe sur lequel le chapitre repose. Le reste suit : si aucun retrieveur seul ne suffit, la chaîne doit en combiner plusieurs, fusionner leurs classements honnêtement, dépenser du vrai calcul sur une passe finale précise, et préparer la requête avant qu'aucune de ces étapes ne commence.
5.2 Recherche hybride : vecteurs denses et BM25 en parallèle
Deux index sur les mêmes morceaux : un index dense HNSW ou IVF issu de l'embedder, et un index inversé creux issu de BM25 ou SPLADE. Les deux sont interrogés, les deux renvoient des listes classées, et le pipeline d'ingestion écrit dans les deux en cadence. BM25 n'est pas une relique ; c'est la fonction de classement par mots-clés la plus fiable jamais conçue, peu paramétrée mais pas sans paramètres, et sur la suite de benchmarks BEIR, la recherche hybride surpasse la recherche purement dense sur la majorité des tâches hors-domaine. L'écart se creuse à mesure que le domaine s'éloigne de la distribution d'entraînement de l'embedder.
Un mode d'échec spécifique mérite d'être nommé : BM25 doit être tokenisé correctement pour chaque langue concernée. Livrer un corpus japonais avec l'analyseur anglais par défaut transforme silencieusement la branche BM25 en pur bruit, et le système semble fonctionner seulement parce que la branche dense fait tout le travail. La recherche creuse a aussi évolué — les modèles creux appris de style SPLADE héritent de la simplicité opérationnelle de BM25 avec le comportement de rappel d'un retrieveur dense.
5.3 Fusion de rangs réciproques et reranking par cross-encoder
La manière naïve de combiner deux listes classées est d'additionner leurs scores. Cela ne marche pas — les magnitudes BM25 sont non bornées et dépendantes du corpus ; les similarités cosinus se situent à peu près dans [-1, 1]. Elles ne sont pas commensurables, et toute pondération fixe est un problème de réglage perpétuel. La fusion de rangs réciproques contourne le problème en jetant les scores. Pour chaque candidat, le score fusionné est la somme de 1/(k + rang) à travers les retrieveurs, avec k = 60. La forme est raide en tête et plate en queue, les résultats sont insensibles à k, et l'algorithme se compose naturellement avec l'expansion multi-requêtes — six listes issues de trois paraphrases contre deux retrieveurs fusionnent en une seule ligne de code.
La RRF ne peut pas rattraper un document qu'aucun des deux retrieveurs n'a fait remonter ; ce travail revient à la réécriture de requête. Ce qu'elle fait, à bas coût et sans hyperparamètres, c'est réconcilier des retrieveurs qui sont mis à jour et remplacés indépendamment — une chaîne dont la fusion n'a pas besoin d'être re-réglée quand une branche change est radicalement moins chère à maintenir.
Les bi-encoders qui ont produit ces classements n'ont jamais vu la requête et le morceau ensemble. Un reranker cross-encoder, lui, oui — il concatène la paire et la passe conjointement dans un transformeur affiné pour produire un score de pertinence. Chaque tête d'attention voit les deux côtés à la fois, et le modèle peut s'attacher à la phrase spécifique de la requête qui doit matcher une phrase spécifique du morceau. Il ne peut pas être précalculé, donc il est trop lent comme retrieveur primaire, mais il est parfait sur les 50 à 200 candidats que la recherche hybride fait remonter. Le gain sur NDCG@10 est typiquement de 5 à 15 points — plus grand que de changer de modèle d'embedding au sein de la famille des bi-encoders.
5.4 Compréhension de requête : réécriture, expansion, HyDE
Tout ce qui précède supposait que la requête était bien formée. Elle ne l'est presque jamais. Un utilisateur de support tape « vacances » ; la politique dit « droit aux congés payés annuels ». Un développeur tape « auth échoue 500 » ; le runbook décrit « le service d'authentification renvoie HTTP 500 avec échec de validation de token ». Le travail doit se faire côté requête. Trois patrons se composent : la réécriture de la requête pour qu'elle soit autonome (résoudre les pronoms, étendre les acronymes, changer de langue pour correspondre au corpus) ; l'expansion en une poignée de paraphrases qui se diffusent chacune dans les deux retrieveurs ; et HyDE, qui demande à un petit modèle d'écrire une réponse hypothétique et embarque celle-là au lieu de la question. Le corpus est plein de réponses, et les réponses ressemblent davantage à d'autres réponses qu'à des questions.
Le patron défensif est de garder la requête originale aux côtés de la réécrite et de dispatcher les deux. La sortie du réécriveur est une hypothèse, pas un remplacement. La plupart des « régressions de recherche » dans les systèmes agentiques sont en fait des régressions de réécriture, et elles sont invisibles sans télémétrie par étape.
Ce que prépare le Chapitre 5
La chaîne telle que dessinée est aussi la surface entière qu'un attaquant a besoin de subvertir. Chaque étape prend une entrée, produit une sortie, et fait confiance aux données qu'elle manipule. Le corpus peut être empoisonné à l'ingestion ; l'embedder peut être manipulé par des morceaux adversariaux ; le reranker peut être biaisé ; le générateur peut être trompé par des instructions cachées dans le contenu récupéré. À partir d'ici, le livre ouvre la Partie IV, et le cadrage passe du comment bien retrouver au que se passe-t-il quand la recherche est attaquée.
Prochaine étape — Chapitre 6 : Modèles de menaces et vulnérabilités RAG. L'ouverture même qui rend RAG utile est aussi la surface que les adversaires exploitent — empoisonnement de corpus, recherche adversariale, injection de prompt indirecte, inversion d'embedding, et le deputy confus.