Un LLM seul est une boîte noire qui hallucine et dont les connaissances sont datées. Le RAG (Retrieval-Augmented Generation) est la solution pragmatique pour l’ancrer dans vos propres données. Le principe est simple : avant de poser une question au LLM, on cherche les documents les plus pertinents dans une base de connaissances, et on les injecte dans le prompt. Bien fait, le RAG réduit les hallucinations et garde les réponses à jour. Mal fait, il coûte cher et répond à côté. La clé du succès réside dans un bon index et des prompts sobres.
le pipeline rag en deux temps
Le RAG se décompose en deux processus distincts : l’indexation, qui se fait en amont, et la récupération, qui se fait en temps réel à chaque question.
prérequis
- Un corpus de documents propre et dédoublonné.
- Un pipeline d’extraction de texte stable pour convertir vos sources (PDF, HTML) en texte brut.
- Une base de données vectorielle adaptée à votre volume (ex: Pinecone, Weaviate, ou pgvector pour PostgreSQL).
- Des métriques de qualité et de coût pour piloter le système.
découper et indexer intelligemment
La qualité de votre RAG dépend à 80% de la qualité de votre index.
- Découpage logique (Chunking): Ne découpez pas vos documents à une taille fixe et aveugle. Cela coupe les phrases et détruit le contexte. Découpez par idées : paragraphes, sections, titres.
- Métadonnées riches: Chaque “chunk” doit être accompagné de métadonnées : la source du document, sa date de publication, son propriétaire. Ces métadonnées sont cruciales pour filtrer et citer.
- Embeddings cohérents: Utilisez le même modèle d’embedding pour indexer vos documents et pour vectoriser les questions des utilisateurs.
# Pseudo-code pour un découpage par sections markdown
def split_by_sections(document_text):
chunks = []
current_chunk = []
for line in document_text.splitlines():
# Si on trouve un nouveau titre de section, on sauvegarde le chunk précédent
if line.startswith("## "):
if current_chunk:
chunks.append("\n".join(current_chunk))
current_chunk = []
current_chunk.append(line)
# Ne pas oublier le dernier chunk
if current_chunk:
chunks.append("\n".join(current_chunk))
return chunks
récupérer et composer le prompt
- Top K: Ne noyez pas le LLM avec trop de contexte. Récupérer les 3 à 5 chunks les plus pertinents est souvent un bon compromis.
- Diversité: Pour éviter d’avoir 3 chunks qui disent la même chose, vous pouvez re-classer les résultats pour favoriser la diversité des sources ou des dates.
- Prompt sobre avec citations: Le prompt doit être direct et imposer au LLM de citer ses sources en utilisant les métadonnées que vous lui avez fournies.
# Extrait d'un prompt pour un RAG
Tu es un assistant factuel. En te basant **uniquement** sur le contexte suivant, réponds à la question de l'utilisateur.
[Contexte]
- [source_id: doc-123] Le RAG est une technique pour ancrer les LLM.
- [source_id: doc-456] Le découpage par paragraphes est recommandé.
- ...
[Question]
Comment fonctionne le RAG ?
[Contrainte]
Cite tes sources en utilisant le format [source_id]. Si le contexte ne te permet pas de répondre, dis "Je ne sais pas".
cache, coût et fraîcheur
- Cache des embeddings: La vectorisation d’un même document ou d’une même question est coûteuse. Mettez en place un cache pour éviter de recalculer les embeddings.
- Ré-indexation incrémentale: Ne ré-indexez pas tout votre corpus tous les jours. Mettez en place un pipeline qui ne traite que les documents nouveaux ou modifiés.
- Budget par route: Suivez les coûts par cas d’usage et par utilisateur pour identifier les dérives.
évaluation
- Exactitude factuelle: Construisez un “golden set” de questions/réponses réelles et mesurez le taux de bonnes réponses.
- Taux de “je ne sais pas”: Un bon système RAG sait quand il ne sait pas. Un taux de réponse “je ne sais pas” élevé sur des questions hors-sujet est un signe de bonne santé.
- Jugement humain: Pour la qualité perçue, rien ne remplace une évaluation humaine sur un échantillon de réponses.
pièges et parades
-
Symptôme: Les réponses manquent de contexte.
- Cause: Chunks trop courts ou découpés au milieu d’une idée.
- Correctif: Découper par structure logique (paragraphes, sections) et non par taille fixe.
-
Symptôme: Les utilisateurs ne font pas confiance aux réponses.
- Cause: Opacité, absence de citations.
- Correctif: Rendre la citation des sources obligatoire dans le prompt et l’afficher clairement dans l’interface.
-
Symptôme: La recherche remonte des documents non pertinents.
- Cause: Index sans métadonnées.
- Correctif: Enrichir l’index avec des métadonnées et les utiliser pour filtrer les résultats avant la recherche vectorielle (ex: “cherche uniquement dans les documents modifiés après le 1er janvier”).
-
Symptôme: Impossible d’améliorer le système car on ne sait pas ce qui ne marche pas.
- Cause: Absence de logs.
- Correctif: Tracer chaque étape : le prompt, le contexte récupéré, et la réponse finale. C’est la base pour débugger et itérer.