Section 11.4.17 : Construire un agent RAG complet
🎯 Objectif pédagogique
Combiner agents IA et RAG pour construire un assistant qui raisonne ET consulte une base de connaissances. Vous serez capable de construire un agent RAG end-to-end : indexation, retrieval, raisonnement, et action.
Agent + RAG — Le combo ultime
Marc a un agent (qui raisonne et agit) et un système RAG (qui consulte des documents). En les combinant, on obtient un agent RAG : un assistant qui réfléchit, cherche dans votre base de connaissances, et génère des réponses sourcées. C'est l'architecture des chatbots d'entreprise les plus avancés.
Architecture Agent RAG
import json
import chromadb
from openai import OpenAI
from pathlib import Path
client = OpenAI()
chroma = chromadb.PersistentClient(path="./agent_rag_db")
# ═══ KNOWLEDGE BASE ═══
def setup_knowledge_base():
"""Initialiser la base de connaissances."""
collection = chroma.get_or_create_collection("career_knowledge")
knowledge = [
# FAQ Reconversion
"Pour se reconvertir en Data Analyst depuis la finance, les compétences transférables sont : analyse quantitative, modélisation financière, Excel avancé, présentation de données aux décideurs.",
"Les formations recommandées pour devenir Data Analyst : bootcamps (3-6 mois), certifications Google Data Analytics, cours en ligne (Coursera, DataCamp), Master en Data Science.",
"Le salaire moyen d'un Data Analyst junior en France est de 38-48k€. Avec 2-3 ans d'expérience : 48-60k€. Senior : 60-80k€. À Paris, ajouter 10-15%.",
# Compétences techniques
"Les compétences techniques essentielles pour un Data Analyst : Python (pandas, matplotlib), SQL (jointures, CTE, window functions), Tableau ou Power BI, Excel avancé, Git basics.",
"Pour les entretiens Data Analyst, préparer : un test SQL (30-45 min), un cas pratique Python (nettoyage + analyse), une présentation de dashboard, et des questions comportementales.",
# Marché de l'emploi
"En 2025, le marché Data Analyst en France : +15% de croissance, 8000 postes ouverts, forte demande en finance, santé et e-commerce. Le remote est proposé dans 40% des offres.",
"Les entreprises qui recrutent le plus de Data Analysts : grandes banques (BNP, SG), GAFAM, startups FinTech, cabinets de conseil (McKinsey, BCG), e-commerce (Amazon, Cdiscount).",
]
collection.upsert(
ids=[f"doc_\{i\}" for i in range(len(knowledge))],
documents=knowledge
)
return collection
# ═══ AGENT RAG ═══
class CareerAgentRAG:
"""Agent RAG pour la recherche d'emploi."""
def __init__(self):
self.collection = setup_knowledge_base()
self.conversation_history = []
self.tools = [
\{
"type": "function",
"function": \{
"name": "search_knowledge_base",
"description": "Recherche dans la base de connaissances carrière (reconversion, salaires, compétences, formations, marché de l'emploi).",
"parameters": \{
"type": "object",
"properties": \{
"query": \{"type": "string", "description": "La question à rechercher"\}
\},
"required": ["query"]
\}
\}
\},
\{
"type": "function",
"function": \{
"name": "analyze_profile_fit",
"description": "Analyse la compatibilité d'un profil avec un poste cible.",
"parameters": \{
"type": "object",
"properties": \{
"profile": \{"type": "string", "description": "Description du profil"\},
"target_role": \{"type": "string", "description": "Poste visé"\}
\},
"required": ["profile", "target_role"]
\}
\}
\},
\{
"type": "function",
"function": \{
"name": "create_action_plan",
"description": "Crée un plan d'action personnalisé avec des étapes concrètes.",
"parameters": \{
"type": "object",
"properties": \{
"goal": \{"type": "string", "description": "Objectif à atteindre"\},
"timeline": \{"type": "string", "description": "Durée souhaitée (ex: '3 mois')"\},
"current_skills": \{"type": "string", "description": "Compétences actuelles"\}
\},
"required": ["goal", "timeline"]
\}
\}
\}
]
def _search_knowledge_base(self, query):
"""Tool: Recherche dans ChromaDB."""
results = self.collection.query(query_texts=[query], n_results=3)
context = "\n".join([f"- \{doc\}" for doc in results["documents"][0]])
return f"Informations trouvées :\n\{context\}"
def _analyze_profile_fit(self, profile, target_role):
"""Tool: Analyse de compatibilité profil/poste."""
# Enrichir avec RAG
context = self._search_knowledge_base(f"compétences \{target_role\}")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[\{
"role": "user",
"content": f"""Analyse la compatibilité :
Profil : \{profile\}
Poste visé : \{target_role\}
Contexte marché : \{context\}
Donne : Score (1-10), Forces, Gaps, Recommandations."""
\}],
max_tokens=500
)
return response.choices[0].message.content
def _create_action_plan(self, goal, timeline, current_skills=""):
"""Tool: Création de plan d'action."""
context = self._search_knowledge_base(f"formation \{goal\}")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[\{
"role": "user",
"content": f"""Crée un plan d'action :
Objectif : \{goal\}
Durée : \{timeline\}
Compétences actuelles : \{current_skills or 'Non spécifiées'\}
Contexte : \{context\}
Format : semaine par semaine, avec des livrables concrets."""
\}],
max_tokens=800
)
return response.choices[0].message.content
def chat(self, user_message):
"""Point d'entrée principal de l'agent."""
self.conversation_history.append(\{"role": "user", "content": user_message\})
messages = [
\{"role": "system", "content": """Tu es CareerBot, un agent expert en reconversion tech.
Tu as accès à une base de connaissances et des outils d'analyse.
Utilise tes outils pour donner des réponses précises et sourcées.
Ton : professionnel, chaleureux, tu tutoies."""\}
] + self.conversation_history
# Boucle agent
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=self.tools,
tool_choice="auto"
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
self.conversation_history.append(\{"role": "assistant", "content": msg.content\})
return msg.content
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
if tc.function.name == "search_knowledge_base":
result = self._search_knowledge_base(**args)
elif tc.function.name == "analyze_profile_fit":
result = self._analyze_profile_fit(**args)
elif tc.function.name == "create_action_plan":
result = self._create_action_plan(**args)
else:
result = "Outil non disponible"
messages.append(\{
"role": "tool",
"tool_call_id": tc.id,
"content": result
\})
# ═══ UTILISATION ═══
agent = CareerAgentRAG()
# Conversation multi-tours
print(agent.chat("Salut ! Je viens de la finance (8 ans) et je veux devenir Data Analyst."))
print("---")
print(agent.chat("Quel salaire puis-je espérer en tant que junior ?"))
print("---")
print(agent.chat("Crée-moi un plan d'action sur 3 mois pour être prêt."))
Enrichir votre base de connaissances
L'agent RAG est aussi bon que sa base de connaissances. Alimentez-la avec : FAQ métier, guides de formation, données salariales, témoignages de reconversion, guides d'entretien. Plus la base est riche, plus les réponses sont pertinentes et précises.
🏋️ Exercice pratique (30 minutes)
- →Implémentez le
CareerAgentRAGcomplet - →Enrichissez la base de connaissances avec 10 documents
- →Testez une conversation de 5 messages — l'agent utilise-t-il les bons outils ?
- →Vérifiez que les réponses sont basées sur la base de connaissances (pas d'hallucination)
Pourquoi combiner Agent + RAG plutôt que d'utiliser l'un ou l'autre seul ?
Quel est l'avantage de donner un outil search_knowledge_base à l'agent plutôt que de toujours envoyer le contexte RAG ?