01
📖 Introduction
Connecter un LLM (Large Language Model) à un graphe de connaissances permet de créer des systèmes d'IA plus fiables, plus précises et plus explicables. Le LLM apporte la compréhension et la génération de texte, le graphe apporte les faits vérifiés et les relations sémantiques.
💡 Ce que vous allez apprendre :
- ✅ Choisir le bon LLM pour votre cas d'usage
- ✅ Configurer LangChain avec Neo4j ou RDF
- ✅ Implémenter GraphRAG (RAG sur graphe)
- ✅ Créer un agent IA qui navigue dans le graphe
- ✅ Optimiser les performances et la qualité
📊 Architecture GraphRAG :
[Question] → [LLM analyse] → [Requête SPARQL/Cypher] → [Graphe] → [Résultats] → [LLM synthèse] → [Réponse]
02
🤖 Étape 1 : Choisir son LLM
| Modèle | Avantages | Inconvénients | Usage recommandé |
| GPT-4
| Très bonne compréhension, multilingue
| Payant, API seulement
| Production, haute qualité
|
| Mistral / Mixtral
| Open source, bon français, gratuit possible
| Moins puissant que GPT-4
| On-premise, budget limité
|
| Llama 3
| Open source, performant
| Anglais principalement
| Usage local, anglais
|
| Claude 3
| Très bon français, contexte long
| Payant, API seulement
| Grands contextes, analyse documentaire
|
💡 Notre recommandation : Pour un projet en français, commencez avec Mistral (open source, bon rapport qualité/prix) ou GPT-4 (meilleure qualité).
03
🔧 Étape 2 : Configuration LangChain
Installation
pip install langchain langchain-community langchain-openai
pip install neo4j rdflib SPARQLWrapper
Avec Neo4j (Cypher)
from langchain_community.graphs import Neo4jGraph
from langchain.chains import GraphCypherQAChain
from langchain_openai import ChatOpenAI
# Connexion à Neo4j
graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password="password"
)
# LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)
# Chaîne Cypher QA
chain = GraphCypherQAChain.from_llm(
graph=graph,
llm=llm,
verbose=True,
return_intermediate_steps=True
)
Avec RDF / SPARQL
from langchain_community.graphs import RdfGraph
from langchain.chains import GraphSparqlQAChain
# Connexion au triple store
graph = RdfGraph(
query_endpoint="http://localhost:3030/ds/sparql",
update_endpoint="http://localhost:3030/ds/update"
)
# Chaîne SPARQL QA
chain = GraphSparqlQAChain.from_llm(
graph=graph,
llm=llm,
verbose=True
)
05
🧠 Étape 4 : Créer un agent intelligent
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool
# Définir les outils
graph_tool = Tool(
name="query_graph",
func=lambda q: chain.run(q),
description="Interroge le graphe de connaissances avec SPARQL/Cypher"
)
vector_tool = Tool(
name="semantic_search",
func=lambda q: vectorstore.similarity_search(q, k=3),
description="Recherche sémantique dans les documents"
)
# Agent
agent = create_react_agent(
llm=llm,
tools=[graph_tool, vector_tool],
prompt=prompt
)
agent_executor = AgentExecutor(
agent=agent,
tools=[graph_tool, vector_tool],
verbose=True,
max_iterations=3
)
# Exemple d'utilisation
response = agent_executor.invoke({
"input": "Quels discours de Charles de Gaulle parlent de la résistance ?"
})
📝 Exemple de raisonnement agent :
Input : "Compare les discours de De Gaulle et Macron sur l'Europe"
1. Thought : Je dois trouver les discours des deux orateurs sur l'Europe.
2. Action : query_graph("SELECT ?titre WHERE { ... }")
3. Observation : [Discours de De Gaulle: "Discours de Bayeux", ...]
4. Action : query_graph("SELECT ?titre WHERE { ... }")
5. Observation : [Discours de Macron: "Discours de la Sorbonne", ...]
6. Final Answer : Synthèse des deux...
06
⚡ Étape 5 : Optimisation
1. Cache des requêtes
import hashlib
import pickle
class QueryCache:
def __init__(self, cache_file="sparql_cache.pkl"):
self.cache = self._load(cache_file)
def get(self, question):
key = hashlib.md5(question.encode()).hexdigest()
return self.cache.get(key)
def set(self, question, answer):
key = hashlib.md5(question.encode()).hexdigest()
self.cache[key] = answer
2. Prompt engineering
SYSTEM_PROMPT = """Tu es un expert en histoire des discours.
Utilise le graphe de connaissances pour répondre.
Si la réponse n'est pas dans le graphe, dis-le honnêtement.
Cite toujours tes sources (les URI des entités trouvées).
Sois précis et concis."""
3. Gestion des erreurs
def safe_query(question):
try:
response = chain.invoke(question)
if not response.get('result'):
return "Je n'ai pas trouvé d'information dans le graphe."
return response['result']
except Exception as e:
return f"Erreur: {str(e)}"
07
🎯 Exemple complet : Assistant discours historiques
class HistoricalSpeechAssistant:
def __init__(self):
# Connexion au graphe Neo4j
self.graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password="password"
)
# LLM local (Mistral via Ollama)
self.llm = Ollama(model="mistral", temperature=0)
# Chaîne QA
self.chain = GraphCypherQAChain.from_llm(
graph=self.graph,
llm=self.llm,
verbose=False
)
# Historique des conversations
self.history = []
def ask(self, question):
# Ajouter à l'historique
self.history.append({"role": "user", "content": question})
# Interroger le graphe
result = self.chain.invoke({"query": question})
# Stocker la réponse
self.history.append({"role": "assistant", "content": result['result']})
return result['result']
def get_conversation(self):
return self.history
# Utilisation
assistant = HistoricalSpeechAssistant()
print(assistant.ask("Quels sont les discours de Victor Hugo ?"))
print(assistant.ask("Et sur quel thème parle-t-il ?"))