Le RAG hybride excelle à retrouver des passages pertinents. Mais posez-lui une question relationnelle — « quels clients touchés par l’incident X ont une commande sous garantie ? » — et il échoue : la réponse n’est dans aucun passage unique. Elle se construit en suivant des relations à travers plusieurs documents. C’est l’angle mort de la récupération par similarité.
Le GraphRAG y répond en récupérant non par ressemblance mais par traversée d’un graphe de connaissances. Sur AWS, ce graphe vit dans Amazon Neptune.
Un graphe de connaissances, c’est quoi
Un graphe de connaissances modélise le domaine en entités (nœuds : Client,
Commande, Produit, Incident…) reliées par des relations typées (A_COMMANDÉ,
CONCERNE, COUVERT_PAR). Là où un index vectoriel ne connaît que des points proches
dans un espace, le graphe connaît des chemins — et c’est en les parcourant qu’on
répond aux questions relationnelles.
Étape 1 — Construire le graphe (extraction)
On extrait entités et relations des documents avec un LLM, en sortie structurée — un travail d’ingestion, à faire une fois (et à maintenir).
from pydantic import BaseModel, Field
from langchain_aws import ChatBedrockConverse
class Triplet(BaseModel):
sujet: str = Field(description="Entité source")
relation: str = Field(description="Type de relation, en MAJUSCULES")
objet: str = Field(description="Entité cible")
class Extraction(BaseModel):
triplets: list[Triplet]
modele = ChatBedrockConverse(model="eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
region_name="eu-west-1")
def extraire(document: str) -> list[Triplet]:
"""Extrait les (entité, relation, entité) d'un document."""
res = modele.with_structured_output(Extraction).invoke(
f"Extrais les entités et leurs relations de ce texte sous forme de triplets "
f"(sujet, RELATION, objet) :\n{document}"
)
return res.triplets
Étape 2 — Charger dans Neptune
Amazon Neptune est la base de graphes managée d’AWS. Deux saveurs : Neptune Database (transactionnel, requêtes openCypher/Gremlin/SPARQL) et Neptune Analytics (analyse de graphes en mémoire, algorithmes, et index vectoriel intégré — utile pour l’hybride graphe + vecteur). On insère les triplets via openCypher.
def charger(graphe, triplets: list[Triplet]):
for t in triplets:
graphe.query(
"MERGE (s:Entite {nom: $sujet}) "
"MERGE (o:Entite {nom: $objet}) "
"MERGE (s)-[r:REL {type: $relation}]->(o)",
params={"sujet": t.sujet, "objet": t.objet, "relation": t.relation},
)
Étape 3 — Récupérer par traversal
Deux stratégies de récupération GraphRAG, complémentaires :
- Locale — on identifie l’entité de départ dans la question, puis on traverse ses voisins sur quelques sauts pour bâtir le contexte. Idéal pour les questions pointues sur une entité.
- Globale — on pré-calcule des résumés de communautés (clusters d’entités très liées) ; une question globale interroge ces résumés. Idéal pour les questions de synthèse sur tout le corpus.
Pour la récupération locale, on génère la requête de graphe à partir de la question. LangChain fournit des chaînes question→openCypher pour Neptune ; on peut aussi l’exposer plus simplement.
def recuperer_graphe(graphe, entite: str, sauts: int = 2) -> str:
"""Traverse le voisinage d'une entité et renvoie les relations trouvées."""
chemins = graphe.query(
f"MATCH p = (s:Entite {{nom: $entite}})-[*1..{sauts}]-(v) "
"RETURN p LIMIT 50", params={"entite": entite},
)
return formater_chemins(chemins) # « Client -A_COMMANDÉ-> Cmd -CONCERNE-> Produit »
Étape 4 — Brancher à un agent LangGraph
On expose la récupération par graphe comme un outil, aux côtés (souvent) du RAG hybride : l’agent choisit la bonne arme selon la question.
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
@tool
def interroger_graphe(question: str) -> str:
"""Récupère par TRAVERSÉE du graphe de connaissances. À utiliser pour les
questions relationnelles ou multi-sauts (qui, lié à quoi, via quoi)."""
entite = identifier_entite(question) # extraction de l'entité de départ
return recuperer_graphe(graphe, entite)
@tool
def base_vectorielle(requete: str) -> str:
"""Recherche hybride (sémantique + mots-clés). Pour les questions factuelles."""
...
agent = create_react_agent(modele, [interroger_graphe, base_vectorielle])
Le coût de la richesse
Le GraphRAG est puissant mais exigeant : il faut construire et maintenir le graphe (l’extraction se rejoue quand les données changent), opérer Neptune, et la récupération est plus complexe à régler. Ne l’introduisez que si vos questions le justifient — et mesurez le gain, comme toujours, sur un dataset d’évaluation.
Bonnes pratiques & pièges
- Réservez le GraphRAG aux questions multi-sauts, relationnelles ou globales.
- Définissez une ontologie légère (entités/relations attendues) avant d'extraire.
- Donnez à l'agent les DEUX outils — graphe et vectoriel — et laissez-le choisir.
- Neptune Analytics pour combiner traversée et index vectoriel (hybride graphe+vecteur).
- Pré-calculez des résumés de communautés pour les questions globales.
- Mesurez le gain du GraphRAG sur un dataset : il a un coût, il doit le justifier.
- Dégainer le GraphRAG pour des questions factuelles locales : le hybride suffit, en plus simple.
- Extraire sans schéma : un graphe incohérent est intraversable.
- Oublier la maintenance : un graphe figé diverge des données qui évoluent.
- Sous-estimer l'exploitation de Neptune et le réglage de la traversée.
- Opposer graphe et vectoriel au lieu de les combiner.
Ce qu’il faut retenir
- Le GraphRAG récupère par traversée de relations, pas par similarité — il répond aux questions multi-sauts et relationnelles.
- On extrait un graphe de connaissances (entités + relations) qu’on héberge sur Amazon Neptune (Database ou Analytics).
- Récupération locale (voisinage d’une entité) et globale (résumés de communautés) sont complémentaires.
- On l’expose comme outil d’un agent LangGraph, aux côtés du RAG hybride — l’agent choisit.
- Puissant mais coûteux à construire et maintenir : à justifier par les questions et à mesurer.
Vous avez maintenant tout l’arsenal de récupération AWS — hybride, managé, par graphe. Assemblons-le dans un système complet : le cas pratique 100 % AWS.