Chapitre 10 · RAG · 9 min

Lire tes documents

Comment un LLM accède à des milliers de pages sans les mémoriser. Embeddings, recherche sémantique, contexte injecté.

La limite que le contexte ne peut pas résoudre

Imagine que tu veuilles construire un assistant capable de répondre à des questions sur l'ensemble de la documentation interne de ton entreprise — 50 000 pages, mises à jour chaque semaine.

Même avec une fenêtre de 1 million de tokens, tu ne peux pas tout mettre dedans. Et si tu pouvais, le coût serait prohibitif et la qualité des réponses se dégraderait : les modèles ont du mal à extraire des informations précises dans des contextes très longs.

Il faut une autre approche. C'est le RAGRetrieval-Augmented Generation.

L'idée fondamentale

Plutôt que de donner tout le document au modèle, tu lui donnes uniquement les passages pertinents pour sa question. Pour faire ça, tu as besoin de deux choses :

  1. Un index : une représentation vectorielle de tous tes documents, stockée à l'avance.
  2. Un moteur de recherche sémantique : quand une question arrive, il trouve les passages les plus proches sémantiquement.

Les passages trouvés sont ensuite injectés dans le contexte du LLM avec la question. Le modèle répond en s'appuyant sur ces extraits.

C'est exactement ce que fait la recherche sémantique avec les embeddings que tu connais déjà depuis le chapitre 03 — mais appliquée à des documents réels.

Le pipeline en trois étapes

1. L'indexation (une seule fois)

On découpe le document en chunks — des extraits de quelques centaines de tokens (avec un léger chevauchement entre eux pour ne pas couper le sens à la frontière).

Chaque chunk est ensuite converti en vecteur par un modèle d'embedding. Ces vecteurs sont stockés dans une base de données vectorielle (Pinecone, Chroma, pgvector…).

Cette étape se fait une seule fois, ou à chaque mise à jour du document.

2. La recherche (à chaque question)

Quand une question arrive, on la convertit en vecteur avec le même modèle d'embedding.

On calcule la similarité cosinus entre ce vecteur-question et tous les vecteurs-chunks de la base. Les k chunks les plus proches sont récupérés — en général 3 à 5.

C'est la recherche sémantique : "proche" ne veut pas dire "qui contient les mêmes mots", mais "qui exprime un sens similaire".

3. La génération

Les chunks récupérés sont assemblés dans un prompt :

Extraits du document :
[Extrait 1 — ...]
[Extrait 2 — ...]
[Extrait 3 — ...]

Question : {question de l'utilisateur}

Ce prompt est envoyé au LLM, qui génère une réponse en s'appuyant sur les extraits. Le modèle n'a pas mémorisé le document — il le lit au moment où on lui pose la question.

Visualisation du pipeline

Voici le système en action sur un mini-corpus de planétologie. Choisis une question — observe quels chunks sont récupérés dans l'espace vectoriel et comment ils sont assemblés en contexte.

Choisis une question : elle est embedded, comparée aux chunks du corpus, et les plus pertinents sont injectés dans le prompt avant la génération. C'est ce détour qui permet à un LLM de répondre sur des documents qu'il n'a jamais vus pendant son entraînement.

La taille des chunks : un vrai choix d'ingénierie

Le découpage en chunks n'est pas anodin. C'est souvent la première source de problèmes dans un système RAG.

Chunks trop petits : chaque chunk est trop peu informatif. On récupère des fragments qui, sortis de contexte, ne permettent pas au modèle de répondre correctement.

Chunks trop grands : on dépasse la précision de l'embedding. Un vecteur qui représente 2 000 tokens est une moyenne floue — il sera récupéré pour certaines questions mais le contenu pertinent sera noyé dans le texte.

Une règle pratique : des chunks de 200 à 500 tokens, avec un overlap de 10-15 %. Le bon paramètre dépend de la structure de tes documents.

Quel modèle d'embedding utiliser ?

Toutes les questions ne mènent pas aux bons chunks avec le même embedding. Un modèle entraîné sur du français généraliste retrouvera mal du code Python ; un modèle entraîné sur du code retrouvera mal des échanges médicaux.

Les choix qui reviennent en pratique :

  • text-embedding-3-small / -large (OpenAI) — qualité solide, généraliste, multilingue. Le défaut quand on commence.
  • bge-large / bge-m3 (BAAI) — open-source, excellent en multilingue, top des benchmarks MTEB en 2024.
  • all-MiniLM-L6-v2 (Sentence-Transformers) — petit, rapide, déployable localement. Bon rapport qualité/coût pour des cas d'usage simples.
  • Modèles spécialisés par domaine (code, biomédical, juridique) — toujours meilleurs sur leur niche, plus faibles ailleurs.

Une règle pratique : tester deux ou trois modèles sur tes données et tes questions. Le classement MTEB ne dit pas grand-chose de ton cas d'usage particulier.

Le reranker : la deuxième passe

La recherche vectorielle a un défaut : elle est rapide mais grossière. Un embedding de quelques centaines de dimensions est une moyenne floue d'un texte. Beaucoup de chunks "à peu près pertinents" surnagent, et les vrais bons sont parfois noyés.

D'où une étape devenue standard dans les systèmes RAG sérieux : le reranker.

L'idée en deux temps :

  1. Première passe (recherche vectorielle) — récupère les 50 ou 100 chunks les plus proches. Rapide.
  2. Deuxième passe (reranking) — un petit modèle (souvent un cross-encoder) évalue chaque paire (question, chunk) ensemble, donne un score précis, et garde le top 5–10. Lent par chunk, mais on ne le fait que sur les 50 candidats de la première passe.

Le reranker voit la question et le chunk en même temps, ce que l'embedding ne fait pas. Il capte des subtilités sémantiques que la recherche vectorielle rate. Cohere, Jina AI, BAAI proposent des rerankers prêts à l'emploi.

Sans reranker, ton RAG plafonne. Avec, la qualité saute d'un cran sans changer le reste du pipeline.

Pourquoi pas du full-text search ?

Une question légitime : pourquoi ne pas simplement faire une recherche par mots-clés, comme un moteur de recherche classique ?

La recherche vectorielle est complémentaire, pas un remplacement. Elle trouve des passages sémantiquement proches, même si la formulation est différente. "Quelle planète tourne le plus lentement ?" peut retrouver un chunk qui parle de "période orbitale" sans que ces mots soient dans la question.

En pratique, les meilleurs systèmes combinent les deux : hybrid search — un score combinant similarité vectorielle et correspondance de mots-clés (BM25).

Les limites du RAG

Le RAG n'est pas magique. Voici les problèmes les plus fréquents :

Le chunk mal découpé. Si une réponse s'étale sur deux chunks et que la frontière de découpage tombe au mauvais endroit, aucun des deux chunks n'est suffisant seul.

Le "lost in the middle" à l'intérieur du chunk. Si le chunk est trop long, les informations importantes peuvent se retrouver au milieu et être ignorées par le modèle.

La question ambiguë. Si la question est vague, l'embedding-question sera loin de la plupart des chunks pertinents. Solution : reformuler la question, ou en générer plusieurs variantes.

Les hallucinations sur les extraits. Le LLM peut extrapoler au-delà de ce que disent les chunks. Le RAG réduit les hallucinations, il ne les élimine pas.

Ce que le RAG change en pratique

Le RAG est aujourd'hui la technique de référence pour connecter un LLM à des données privées ou récentes. Presque tous les chatbots d'entreprise, les assistants de documentation, les outils de veille s'appuient dessus.

Mais c'est encore une architecture "passive" : le modèle reçoit une question, cherche des chunks, répond. Pour des tâches plus complexes — rechercher, puis agir en fonction du résultat, puis chercher encore — il faut aller un cran plus loin.

Mis à jour le

RAG expliqué : faire lire tes documents à un LLM · Step by Token