Prérequis

14. Context engineering — RAG est un cas particulier de context engineering, où le contexte vient d’un index.

Notes liées

Le pattern de base

query → embed query → search vector store (+ keyword) → rerank → select top-k chunks → inject in context → LLM

Pattern devenu standard. Chaque étape porte cependant des dizaines de décisions, chacune pouvant dégrader la qualité.

Intuition — knowledge paramétrique vs non-paramétrique

RAG sépare deux sources de connaissance : la paramétrique (figée dans les poids du modèle au moment du pre-training) et la non-paramétrique (récupérée à la requête depuis un index externe). Le LLM devient une fonction de synthèse sur des chunks fournis à la volée, ce qui permet de mettre à jour la knowledge base sans réentraîner. Le coût se déplace : du training vers le retrieval, dont la qualité conditionne entièrement la sortie finale (garbage in, garbage out).

Chunking

Problème : les documents doivent être découpés en chunks de taille gérable (embedded, retrieved, injected). Trop petit → chunks sans contexte. Trop gros → retrieval imprécis et saturation du budget context.

Stratégies

1. Fixed-size

  • 512 ou 1024 tokens. Overlap 10-20% (pour ne pas couper au mauvais endroit).
  • Simple. Adapté à la plupart des cas.

2. Sentence-aware

  • Split sur sentence boundary, pack jusqu’à ~512 tokens.
  • Plus performant que fixed sur du prose.

3. Recursive

  • LangChain RecursiveCharacterTextSplitter : split sur paragraph, puis sentence, puis word.
  • Bon défaut.

4. Semantic chunking

  • Détection des changements de sujet (embedding distance entre phrases adjacentes).
  • Plus coûteux (embed à l’ingestion). Adapté aux transcriptions et conversations.

5. Structure-aware

  • Pour Markdown / HTML / code : respecter les headings, sections, fonctions.
  • Chunk = unité sémantique naturelle.

6. Late chunking (technique 2024)

  • Embed du doc complet puis chunking sur les embeddings.
  • Chaque chunk conserve le contexte du doc complet dans son embedding.
  • Plus coûteux, qualité de retrieval améliorée.

Pièges

  • Couper en milieu de phrase → retrieval miss.
  • Couper en milieu d’un tableau ou de code → contexte perdu.
  • Chunks sans header (provenance perdue).

Pattern : contextualized chunks

  • Préfixer chaque chunk de “Document: {title}. Section: {section}. Content: {chunk_content}”.
  • Le retrieval matche mieux, le LLM contextualizes mieux.

Embeddings

Modèles canoniques

  • OpenAI text-embedding-3-small / large.
  • Mistral mistral-embed.
  • Cohere embed-multilingual-v3.
  • Open source : BGE-large, e5-mistral-7b-instruct, nomic-embed-text.

Dimensions

Typique : 384, 768, 1024, 1536, 3072. Plus haut = plus précis mais plus coûteux (vector store) et plus lent (search).

Matryoshka embeddings : modèles entraînés de manière à autoriser la troncature des dimensions sans grosse perte (e5-mistral, certains OpenAI). Utile pour le trade-off cost/perf.

Normalisation : la plupart des embeddings sont L2-normalized → cosine similarity = dot product. Plus rapide à search.

Vector store

ANN algorithms

  • HNSW : Hierarchical Navigable Small World. Graphs multi-niveau. Très rapide, consomme beaucoup de mémoire.
  • IVF (Inverted File Index) : cluster les vecteurs, search dans clusters proches. Trade-off rappel/vitesse.
  • PQ (Product Quantization) : compress les vecteurs, search approximate. Combiné avec IVF (IVF-PQ).
  • Flat (brute force) : exact, O(N). Adapté à <1M vecteurs.

Vector stores

Pinecone, Weaviate, Qdrant, Milvus, pg_vector, Chroma, FAISS, LanceDB.

Trade-offs

  • Recall vs latency vs memory vs index build time.
  • Updates : certains index supportent les inserts incrémentaux, d’autres nécessitent un rebuild.

Motivation : les dense embeddings sont mauvais sur :

  • Mots exacts (noms de personnes, IDs, codes).
  • Termes rares non vus à l’entraînement.
  • Recherche par mot-clé pure.

Solution : combiner dense + sparse (BM25 ou SPLADE).

  • BM25 : TF-IDF classique. Rapide, no training.
  • SPLADE : sparse learned. Plus performant que BM25 sur certains domaines, plus coûteux.

Fusion : Reciprocal Rank Fusion (RRF) — combine les rankings sans normalisation des scores.

rrf_score = sum(1 / (k + rank_i)) for each list

k souvent 60.

Reranking

Après retrieval initial (top-100), rerank en top-10 avec un modèle plus puissant.

Architectures

  • Bi-encoder : embedding query + embedding chunk séparément → score. C’est l’embedding standard. Rapide.
  • Cross-encoder : query et chunk traités ensemble par un transformer. Beaucoup plus précis, beaucoup plus lent. Non scalable au million de chunks → réservé au top-100.

Modèles : Cohere Rerank v3, BGE Reranker v2.

Gain : 10-30% sur recall@10 typiquement. Critique pour la qualité finale.

Freshness

RAG sur des docs qui changent → invalidation cache de retrieval, re-embed, re-index.

  • Stratégies : full re-index quotidien, delta indexing, real-time CDC.
  • TTL sur les embeddings (utilité limitée, mais pertinent sur des metadata).
  • Versioning des chunks (savoir quel chunk a été utilisé pour quelle réponse — pour debug).

Failure modes

  • Bad chunk : chunk pertinent existant mais raté par le search (recall failure).
  • Distractor chunk : retrieval ramène des chunks “voisins” qui ressemblent mais sont hors-sujet → LLM confus.
  • Over-retrieval : injection de 30 chunks, LLM lost-in-the-middle. Voir 14-context-engineering.
  • Stale chunk : chunk pertinent mais obsolète.
  • Coverage gap : query parle d’un sujet absent du corpus → le modèle invente (hallucine sans signaler “je n’ai pas trouvé”).

Vocabulaire clé

chunking, fixed-size, recursive chunking, semantic chunking, late chunking, contextualized chunks, embeddings, dense retrieval, sparse retrieval, BM25, SPLADE, hybrid search, RRF (Reciprocal Rank Fusion), HNSW, IVF, PQ, bi-encoder, cross-encoder, reranking, recall@k, precision@k, freshness, matryoshka embeddings.

Synthèse

Le RAG moderne dépasse le simple vector search. Chunking : recursive ou semantic, avec contextualized chunks qui préfixent le titre du doc et la section pour que le retrieval matche mieux et que le LLM contextualizes. Embeddings : Mistral-embed, OpenAI, BGE selon le use case. Vector store : HNSW pour speed, IVF-PQ pour memory. Critique : hybrid search dense + BM25 fusionnés via RRF, parce que les dense embeddings sont mauvais sur les mots exacts comme les IDs ou noms propres. Reranking avec un cross-encoder sur top-100 → top-10, gain 10-30% recall. Freshness : invalidation et re-index sur les docs qui changent. Failure modes : bad chunk, distractor chunks, over-retrieval qui cause lost-in-the-middle, et coverage gaps où le modèle hallucine au lieu de signaler “pas trouvé”.