Le RAG « naïf » — récupérer le top-k, coller le contexte, générer — plafonne dès que la question demande du **raisonnement** : comparer deux sources, agréger des faits dispersés, ou « faire sens » d'un corpus entier. Cet article part du principe que vous connaissez déjà les embeddings et la recherche vectorielle (voir l'article dédié) et se place **au-dessus** : comment un agent transforme la récupération en boucle de raisonnement (Agentic RAG), et comment GraphRAG structure le corpus en graphe de connaissances pour répondre aux questions globales que le RAG vectoriel rate.

## Pourquoi le RAG naïf plafonne

Le pipeline classique fait **une seule passe** : une requête, une récupération, une génération. Il n'itère pas, ne se corrige pas, et ne vérifie pas si les documents récupérés répondent réellement à la question. Trois angles morts reviennent constamment :

- **Récupération en un coup.** Si le top-k est mauvais (requête ambiguë, mismatch de vocabulaire, chunk mal découpé), la réponse est mauvaise — sans recours.
- **Pas de raisonnement multi-étapes.** Une question « multi-hop » (« Quel est le PDG de l'entreprise qui a racheté X en 2021 ? ») exige deux récupérations enchaînées ; le one-shot n'en fait qu'une.
- **Pas d'auto-évaluation.** Le LLM reçoit le contexte et génère, qu'il soit pertinent ou non. Aucun garde-fou ne détecte une récupération hors-sujet avant qu'elle ne pollue la réponse.
- **Questions globales.** « Quels sont les grands thèmes de ce corpus ? » n'a pas de réponse dans un sous-ensemble de k passages : l'information est **répartie** sur tout le corpus, pas concentrée dans quelques chunks.

Le symptôme typique est l'**hallucination par contexte pauvre** : le modèle, faute de preuve pertinente, comble les trous. Le RAG naïf reste excellent pour les **questions factuelles simples** où un seul passage suffit — c'est précisément là qu'il faut le garder. Le problème n'est pas le RAG, c'est l'absence de boucle quand la question l'exige.

![Comparaison entre un pipeline RAG naïf linéaire en une passe et une boucle agentique avec évaluation, repli web et auto-réflexion.](/articles/agentic-rag-et-graphrag/naive-vs-agentic-rag.svg)
*Figure : RAG naïf (one-shot) vs RAG agentique (boucle récupérer–raisonner). Diagramme original.*

## L'idée de l'Agentic RAG

L'Agentic RAG remplace le pipeline figé par un **agent** qui décide, à chaque étape, quoi faire : reformuler la requête, choisir une source, récupérer à nouveau, évaluer ce qu'il a obtenu, et seulement ensuite générer. La récupération devient un **outil** appelé dans une boucle de raisonnement, pas une étape unique en amont. On le formalise souvent comme une **machine à états** (un graphe de nœuds reliés par des arêtes conditionnelles) : récupérer → noter les documents → réécrire → générer → vérifier — avec des boucles de retour quand une étape échoue.

### Réécriture et décomposition de requête

La requête de l'utilisateur est rarement la meilleure requête de recherche. Deux transformations clés :

- **Réécriture (query rewriting)** : reformuler pour coller au vocabulaire du corpus, lever les pronoms, expanser les acronymes.
- **Décomposition (multi-hop)** : casser une question complexe en sous-questions récupérées **indépendamment**, puis recomposer. Le coût croît linéairement avec le « fan-out », mais c'est ce qui débloque les comparaisons et les agrégations.
- **Expansion (HyDE)** : générer une réponse *hypothétique* à la question, puis l'utiliser comme requête de recherche — souvent plus proche des documents cibles que la question brute.

Ces transformations sont peu coûteuses (un appel LLM court) et corrigent la cause la plus fréquente d'échec : une requête qui ne « parle pas la langue » du corpus indexé.

### Routage

Avant de récupérer, un **routeur** dirige la requête vers la bonne source : base vectorielle pour le non-structuré, SQL pour le structuré, web pour l'actualité, un outil métier précis. L'**Adaptive RAG** pousse l'idée plus loin : un classifieur léger prédit la **difficulté** de la requête (pas de récupération / une étape / multi-étapes) et choisit la profondeur du pipeline — ce qui coupe 30–50 % du coût moyen sur un trafic mixte en évitant l'agent pour les questions faciles.

Bien routé, un système peut répondre à un simple « bonjour » sans aucune récupération, et engager toute la machinerie agentique uniquement sur les questions qui la méritent.

### Boucles récupérer–raisonner (ReAct)

Le patron **ReAct** alterne *raisonner* et *agir* : à chaque tour l'agent réfléchit, appelle un outil (récupération, SQL, web, serveur MCP), observe le résultat, et recommence jusqu'à pouvoir répondre. C'est indispensable dès qu'on mélange sources non structurées, données structurées et actualité. **Garde-fou impératif** : un plafond d'itérations (5–6) pour éviter les boucles infinies, et une borne de profondeur d'outils.

Concrètement, on modélise la boucle comme un **graphe d'états** explicite, ce que des outils comme LangGraph rendent naturel :

- des **nœuds** = étapes (récupérer, noter, réécrire, générer, vérifier) ;
- des **arêtes conditionnelles** = décisions (« documents pertinents ? » → générer / réécrire / web) ;
- un **état partagé** = la requête courante, les documents retenus, le compteur d'itérations.

Ce « flow engineering » rend la logique **auditable** : chaque décision est un point nommé du graphe, traçable et testable — bien plus maintenable qu'un prompt monolithique qui « décide tout seul ».

Voici l'ossature d'une telle boucle, où la **récupération est un nœud** rappelé tant que les contrôles ne passent pas :

```python
# Graphe d'états Agentic RAG (pseudo-LangGraph)
def agent_loop(question, max_iters=5):
    state = {"question": question, "iters": 0, "docs": []}
    while state["iters"] < max_iters:
        state["iters"] += 1
        state["docs"] = retrieve(state["question"])         # nœud : récupérer
        verdict = grade_documents(state)                    # nœud : noter
        if verdict["route"] == "web_search":
            state["docs"] = web_search(state["question"])    # repli externe (CRAG)
        elif verdict["route"] == "rewrite":
            state["question"] = rewrite_query(state)         # arête conditionnelle
            continue
        answer = generate(state)                             # nœud : générer
        if is_grounded(answer, state["docs"]) and answers(answer, question):
            return answer                                    # contrôles Self-RAG OK
        state["question"] = rewrite_query(state)             # sinon : on reboucle
    return escalate_to_human(question)                       # garde-fou : plafond atteint
```

La sortie n'est jamais « la première génération venue » : elle doit franchir deux contrôles (ancrage + réponse à la question) hérités de Self-RAG, sinon la boucle réécrit la requête et recommence — jusqu'au plafond, où l'on **escalade vers un humain** plutôt que de tourner à l'infini.

## Self-RAG : la réflexion par jetons

**Self-RAG** entraîne le modèle à émettre des **jetons de réflexion** qui le font s'auto-évaluer à chaque étape :

- `Retrieve` — faut-il récupérer (oui / non / continuer) ?
- `ISREL` — les passages récupérés sont-ils **pertinents** ?
- `ISSUP` — la génération est-elle **étayée** par les passages (anti-hallucination) ?
- `ISUSE` — la réponse est-elle **utile** à la question (note 1–5) ?

Le papier original entraîne en réalité **deux modèles** : un *critic* qui apprend à prédire ces jetons, et un *generator* qui les émet au fil de la décodage. À l'inférence, une **recherche en faisceau au niveau du segment** (segment-level beam search) sélectionne la continuation qui maximise une combinaison linéaire de la vraisemblance du texte et des probabilités de jetons « désirables » (`ISREL` = pertinent, `ISSUP` = étayé, `ISUSE` élevé). Le poids de chaque jeton est un **curseur réglable** à l'inférence : on durcit `ISSUP` pour une tâche médicale sensible, on l'assouplit pour une rédaction créative — sans réentraîner.

En pratique (par exemple avec LangGraph), des nœuds de *grading* implémentent cette logique sans modèle spécialement entraîné : on note la pertinence des documents ; si tous échouent, on **réécrit** la requête et on récupère à nouveau. Après génération, deux contrôles : la réponse est-elle ancrée dans les documents (anti-hallucination) et répond-elle vraiment à la question ? Si l'un échoue, la boucle repart avec une requête améliorée.

## Corrective RAG (CRAG) : noter puis corriger

**CRAG** insère un **évaluateur de récupération** qui attribue une note de confiance aux documents et route vers trois actions :

1. **Correct** (au moins un document au-dessus du seuil haut) → utiliser les documents, mais les **raffiner** d'abord.
2. **Incorrect** (tous les documents sous le seuil bas) → les jeter et déclencher une **recherche web** (repli externe, p. ex. via une API de recherche).
3. **Ambiguous** (entre les deux) → action mixte, on **combine** documents internes et complément web.

Le raffinement passe par une stratégie **décompose-puis-recompose** : chaque document est découpé en **bandes de connaissance** (knowledge strips), chaque bande est re-notée par l'évaluateur, les bandes hors-sujet sont filtrées et seules les pertinentes sont recollées. On évite ainsi de polluer le contexte avec les passages voisins, même corrects, qui ne servent pas la question. C'est ce qui rend CRAG **plug-and-play** : il s'insère devant n'importe quel pipeline RAG existant.

Self-RAG et CRAG sont **complémentaires** : CRAG améliore la **qualité de la preuve** (l'entrée), Self-RAG améliore la **façon de raisonner** sur cette preuve (la sortie). On peut chaîner les deux : CRAG nettoie/corrige les entrées, puis Self-RAG réfléchit sur la réponse finale.

### Récapitulatif des patrons

Les systèmes de production combinent rarement un seul patron. Voici comment ils se positionnent :

- **Self-RAG** — le modèle émet des jetons de réflexion et s'auto-note. Brille quand les signaux de récupération sont **bruités** ; gaspille des tokens sur un corpus fiable.
- **CRAG** — un évaluateur externe trie en trois voies (garder / web / hybride). Idéal pour les bases **hétérogènes** mêlant docs produit et fils de forum.
- **Adaptive RAG** — un classifieur prédit la difficulté en amont et choisit la profondeur. Coupe 30–50 % du coût moyen sur du trafic varié.
- **ReAct** — boucle raisonner/agir avec outils hétérogènes (vecteurs, SQL, web, MCP). Indispensable en environnement multi-sources.
- **Décomposition multi-hop** — sous-questions parallèles puis recomposition. Coût linéaire avec le fan-out ; parfait pour comparaisons et agrégations.

La règle pratique : commencer simple (hybride + rerank), ajouter l'**Adaptive routing** pour préserver la vitesse, puis n'activer Self-RAG/CRAG/multi-hop que sur les chemins qui en ont besoin.

```python
# Esquisse d'un nœud d'évaluation CRAG (pseudo-LangGraph)
def grade_documents(state):
    question, docs = state["question"], state["documents"]
    kept = [d for d in docs if grader(question, d).score == "relevant"]
    if len(kept) == 0:
        return {"route": "web_search", "documents": []}   # repli externe
    if len(kept) < len(docs):
        return {"route": "rewrite", "documents": kept}      # confiance moyenne
    return {"route": "generate", "documents": kept}         # confiance élevée
```

## Rappel express : hybride + reranking

Avant de raisonner, il faut **bien récupérer**. Sans ré-expliquer les embeddings, retenez le pipeline à deux étages devenu standard :

1. **Recherche hybride** — fusionner le **lexical** (BM25, robuste sur les termes rares, codes, noms propres) et le **dense** (sémantique) ; renvoyer un large top-50.
2. **Reranking** — un **cross-encoder** (Cohere, Voyage…) re-note finement la paire (requête, passage) et ne garde que le top-5. Le gain est net : le Recall@5 passe typiquement de ~0,70 (hybride seul) à ~0,82 avec reranking.

Le dense seul rate les correspondances lexicales exactes ; BM25 seul rate les synonymes. L'hybride couvre les deux, le reranker met de l'ordre. C'est le socle sur lequel les boucles agentiques opèrent.

Quelques rappels pratiques sur le découpage, sans ré-ouvrir le débat des embeddings :

- **Chunking sémantique** (512–1024 tokens, 50–100 de chevauchement) bat le découpage à taille fixe : on respecte les frontières de sens.
- **Métadonnées** sur chaque chunk (source, date, section) pour le **filtrage** avant la recherche vectorielle.
- **Fusion des scores** (Reciprocal Rank Fusion) pour combiner les classements BM25 et dense de manière robuste, sans calibrer des échelles incompatibles.

Un reranker coûte un appel modèle de plus par requête, mais sur un top-50 réduit à top-5 il améliore directement la **fidélité** en aval : moins de bruit dans le contexte, moins d'hallucinations à corriger ensuite.

## GraphRAG : structurer le corpus en graphe

Le RAG vectoriel échoue sur les questions **globales** parce qu'il récupère « un sous-ensemble de passages individuellement pertinents » — or une question de synthèse n'a pas de passage unique qui la contient. **GraphRAG** (Microsoft, *From Local to Global*) répond en pré-construisant un **graphe de connaissances** puis en le résumant hiérarchiquement. Le pipeline d'indexation a six étapes :

1. **Découpage + extraction.** Le LLM lit chaque chunk et en extrait des **triplets** (entité, relation, entité) et des affirmations — p. ex. *Steve Jobs — a fondé — Apple*. Des prompts spécialisés et de l'**auto-réflexion** (le LLM relit pour les entités manquées) permettent de plus gros chunks sans perte de rappel.
2. **Construction du graphe.** Les instances d'entités sont **dédupliquées** et agrégées : les nœuds sont des entités, les arêtes des relations, pondérées par leur fréquence dans le corpus.
3. **Détection de communautés (Leiden).** L'algorithme de **Leiden** (amélioration de Louvain) partitionne récursivement le graphe en **communautés imbriquées** : niveau feuille (entités très liées), niveaux intermédiaires, niveau racine — un véritable **arbre** de communautés.
4. **Résumés de communautés.** Chaque communauté reçoit un **résumé** type rapport, généré de bas en haut ; les niveaux supérieurs réutilisent les résumés des niveaux inférieurs sous contrainte de place.
5. **Requête (map-reduce).** Pour une question globale, on **map** sur les résumés de communautés en parallèle (réponses partielles + score d'utilité), puis on **reduce** (tri par score → synthèse finale).
6. **Requête locale.** Pour une question factuelle précise, la recherche locale part des entités correspondant à la requête, **étend aux voisins** et aux relations, récupère les chunks associés et répond sur ce contexte combiné.

La **qualité d'extraction** est l'étape critique : un graphe issu d'entités mal extraites ou mal dédupliquées propage ses erreurs partout. Trois leviers :

- **Prompts spécialisés** au domaine, avec exemples *few-shot*, pour cadrer les types d'entités attendus.
- **Auto-réflexion d'extraction** : le LLM relit le chunk pour repérer les entités manquées, ce qui autorise de plus gros chunks sans perte de rappel.
- **Résolution d'entités** (déduplication) : fusionner « Apple », « Apple Inc. » et « la firme de Cupertino » en un seul nœud, sous peine de fragmenter le graphe.

Notez le parallèle : l'auto-réflexion sert ici **à l'indexation**, alors que dans l'Agentic RAG elle sert **à la requête**. La même idée — le modèle se relit — opère à deux moments différents du pipeline.

![Graphe d'entités partitionné en communautés Leiden, et l'arbre de résumés hiérarchiques (racine, intermédiaire, feuille) utilisé pour les requêtes globales par map-reduce.](/articles/agentic-rag-et-graphrag/graphrag-communities.svg)
*Figure : graphe d'entités, communautés Leiden et résumés hiérarchiques. Diagramme original.*

### Global vs local : quand utiliser quoi

- **Requête locale** — questions factuelles ciblées (« Qui dirige X ? »). Combine sous-graphe d'entités + chunks de texte. C'est proche du RAG vectoriel, en mieux ancré sur les relations.
- **Requête globale** — questions de **synthèse** (« Quels sont les thèmes dominants ? », « Quelles tensions traversent ce corpus ? »). Utilise les résumés de communautés via map-reduce.

Le **niveau** de communauté interrogé est un curseur : la racine (C0) donne une vue très condensée et bon marché ; les feuilles donnent du détail au prix de beaucoup plus de tokens. Dans l'étude Microsoft, le **niveau intermédiaire** offre le meilleur équilibre exhaustivité/coût — un bon défaut de départ.

### Quand GraphRAG bat le RAG vectoriel

Sur les questions de **sensemaking** global, GraphRAG domine nettement le RAG vectoriel : dans l'étude Microsoft, des taux de victoire de **72–83 % en exhaustivité** (comprehensiveness) et **62–82 % en diversité** des points de vue, sur des corpus d'environ un million de tokens. Mieux : interroger les **résumés racine** (C0) consomme **9× à 43× moins de tokens de contexte** que l'approche « tout le texte source », tout en conservant un avantage d'exhaustivité de ~72 % sur le RAG vectoriel. Les résumés de niveau **intermédiaire** offrent le meilleur compromis.

La contrepartie est le **coût d'indexation** : construire le graphe est lourd (extraction LLM sur chaque chunk, résumés à chaque niveau) — l'étude rapporte ~281 minutes d'indexation pour un corpus « podcast » avec GPT-4-turbo. GraphRAG n'est donc pas un remplaçant universel du RAG vectoriel : c'est l'outil des questions **globales** et des corpus où la **structure relationnelle** porte le sens.

### Combiner GraphRAG et Agentic RAG

Les deux approches ne s'opposent pas : un **routeur agentique** peut choisir la stratégie selon la question. Schéma fréquent en 2026 :

1. Le routeur classe la requête : factuelle ciblée, multi-hop relationnelle, ou globale de synthèse.
2. **Factuelle** → RAG vectoriel hybride + rerank (rapide, bon marché).
3. **Relationnelle / multi-hop** → requête **locale** GraphRAG (suivre les arêtes du graphe sur plusieurs sauts).
4. **Globale** → requête **globale** GraphRAG (map-reduce sur les résumés de communautés).
5. Une boucle Self-RAG/CRAG enveloppe le tout pour vérifier et, au besoin, corriger ou replier sur le web.

Le graphe devient ainsi un **outil** parmi d'autres dans la boucle ReAct, mobilisé seulement quand la structure relationnelle compte.

## Évaluer : RAGAS et au-delà

On ne pilote pas un système agentique sans mesure. **RAGAS** fournit des métriques par requête, calculées par un LLM-juge :

- **Faithfulness** (fidélité, viser ≥ 0,9) — les affirmations de la réponse sont-elles **étayées** par le contexte récupéré ? C'est la métrique anti-hallucination.
- **Answer relevancy** (pertinence de la réponse, ≥ 0,85) — la réponse colle-t-elle à la question ?
- **Context precision / relevancy** (≥ 0,8) — les **bons** chunks ont-ils été récupérés ?
- **Context recall** — le contexte couvre-t-il **toute** l'information nécessaire à la réponse de référence ?

Ces métriques se calculent **par requête** sur un jeu de test, ce qui permet de comparer objectivement deux configurations (avec/sans rerank, avec/sans CRAG) avant de toucher à la production.

Trois précautions opérationnelles : (1) le **paradoxe de l'évaluateur** — demander au même LLM faillible de se noter crée une circularité ; on l'atténue en **ensemblant** plusieurs juges, en figeant un *golden set*, et en faisant relire ~5 % des traces par des humains ; (2) le **traçage de trajectoire** (Phoenix, Langfuse, OpenTelemetry) pour déboguer chaque itération de l'agent ; (3) la **surveillance de dérive** (knowledge-base, embeddings, évaluation) chaque semaine contre un jeu de référence figé.

## Coûts et arbitrages opérationnels

L'Agentic RAG est puissant mais **cher** : comptez **3× à 10×** plus de tokens que le RAG simple, et **2× à 5×** de latence (de ~1–2 s à ~8–12 s par requête). À 10 000 requêtes/jour, un coût de ~500 $/jour peut grimper à 1 500–5 000 $/jour sans optimisation. Les leviers : **routage adaptatif** (ne lancer la boucle que sur les questions ambiguës), **cache sémantique**, **plafonds d'itérations**, et budgets de tokens par requête.

Quand **ne pas** être agentique : FAQ, recherche d'un fait unique, contraintes UX sub-3 s. Le bon réflexe est l'**Adaptive RAG** — préserver la vitesse sur les questions faciles, ne raisonner en boucle que sur celles qui l'exigent vraiment.

Les pièges récurrents en production, à anticiper dès le jour un :

- **Boucles infinies** — plafonner à 5–6 itérations puis escalader vers un humain.
- **Dérive de la base** — suivre le Recall@5 chaque semaine contre un jeu figé.
- **Queue de coût** — surveiller le p99, bien pire que la moyenne, pas seulement le coût médian.
- **Cascade d'appels d'outils** — borner la profondeur du graphe d'outils (≤ 3).
- **Paradoxe de l'évaluateur** — ensembler les juges, geler le golden set, relire ~5 % à la main.

### Checklist d'implémentation

Un ordre de marche pragmatique pour passer du prototype à la production :

1. **Socle** : hybride BM25 + dense, chunking sémantique, reranking cross-encoder.
2. **Mesure** : brancher RAGAS (fidélité, pertinence, précision du contexte) + traçage (OpenTelemetry) dès le départ.
3. **Routage adaptatif** : un classifieur de difficulté pour ne payer le raisonnement que quand il rapporte.
4. **Boucles** : ajouter Self-RAG (réflexion) et CRAG (correction + repli web) sur les chemins difficiles.
5. **Graphe** : introduire GraphRAG pour les questions globales / relationnelles, en outil de la boucle.
6. **Garde-fous** : plafonds d'itérations, budgets de tokens, cache sémantique, alertes de dérive.

## En résumé

Trois couches se superposent. **Récupération** : hybride (BM25 + dense) + reranking, le socle. **Agentic RAG** : réécriture/décomposition, routage, boucles ReAct, Self-RAG (réflexion) et CRAG (correction + repli web) pour transformer la récupération en raisonnement vérifié. **GraphRAG** : un graphe de connaissances + communautés Leiden + résumés hiérarchiques pour les questions globales que le vectoriel ne sait pas couvrir.

Aucune de ces couches n'est gratuite : chaque boucle, chaque graphe, chaque juge ajoute des tokens et de la latence. La maturité consiste donc à **mesurer avant d'ajouter** — instrumenter avec RAGAS et le traçage, router selon la difficulté, et n'investir le raisonnement que là où le gain de qualité justifie le surcoût. Le RAG naïf n'est pas obsolète : il reste le bon choix pour la majorité des requêtes factuelles. L'art, en 2026, est de **dépenser le raisonnement là où il rapporte**, et de rester en one-shot partout ailleurs.