| Étape | Description | Analogie |
| Retrieval | Chercher les informations pertinentes | Chercher dans un livre avec l'index |
| Augmented | Enrichir le prompt avec ces informations | Donner des notes à un étudiant avant l'examen |
| Generation | Le LLM génère une réponse basée sur ces infos | L'étudiant répond en s'appuyant sur ses notes |
# ============================================================================
# IMPORTATION DES BIBLIOTHÈQUES NÉCESSAIRES
# ============================================================================
from langchain.vectorstores import FAISS # Base de données vectorielle
from langchain.chat_models import ChatOpenAI # Modèle de langage (LLM)
from langchain.chains import RetrievalQA # Chaîne pour faire du Question-Answering avec récupération
from langchain.prompts import PromptTemplate # Pour personnaliser les prompts (non utilisé ici)
from dotenv import load_dotenv # Pour charger les variables d'environnement
import os # Pour accéder aux variables d'environnement
# ============================================================================
# CONFIGURATION DU MODÈLE DE LANGAGE (LLM)
# ============================================================================
# Chargement des variables d'environnement depuis le fichier .env
load_dotenv()
# Récupération des informations de connexion depuis les variables d'environnement
# Cela permet de ne pas exposer les clés API directement dans le code
api_key = os.getenv("OPENAI_API_KEY") # Votre clé API
model_name = os.getenv("OPENAI_MODEL_NAME") # Nom du modèle (ex: "gpt-4", "gpt-3.5-turbo")
# Initialisation du modèle de langage
llm = ChatOpenAI(
model_name=model_name, # Modèle générique à utiliser
openai_api_key=api_key, # Clé d'authentification
temperature=0 # 0 = réponses déterministes, 1 = réponses créatives
)
# ============================================================================
# ÉTAPE 1 : CHARGEMENT DE LA BASE DE DONNÉES VECTORIELLE FAISS
# ============================================================================
# Chemin vers la base de données FAISS créée précédemment
faiss_index_path = "faiss_db"
print(f"Chargement de la base de données FAISS depuis : {faiss_index_path}")
# Chargement de la base de données vectorielle
# ⚠️ allow_dangerous_deserialization=True : nécessaire pour charger des fichiers pickle
# (à utiliser uniquement avec des sources de confiance)
db = FAISS.load_local(
faiss_index_path,
embeddings=embeddings, # Même modèle d'embeddings utilisé lors de la création
allow_dangerous_deserialization=True
)
print("✅ Base de données chargée avec succès")
# ============================================================================
# ÉTAPE 2 : CRÉATION DU RETRIEVER (RÉCUPÉRATEUR DE DOCUMENTS)
# ============================================================================
# Le retriever va chercher les morceaux de texte les plus pertinents
# en fonction de la question posée
retriever = db.as_retriever(
search_kwargs={"k": 3} # k=3 : récupère les 3 chunks les plus similaires à la question
)
print("✅ Retriever configuré pour récupérer 3 documents pertinents")
# ============================================================================
# ÉTAPE 3 : CRÉATION DE LA CHAÎNE RAG (Retrieval Augmented Generation)
# ============================================================================
# RAG = Récupération + Génération
# 1. On récupère les documents pertinents (Retrieval)
# 2. On les donne au LLM pour générer une réponse (Generation)
rag_chain = RetrievalQA.from_chain_type(
llm=llm, # Le modèle de langage qui va générer la réponse
chain_type="stuff", # "stuff" = concatène tous les documents récupérés dans le prompt
# Autres options : "map_reduce", "refine", "map_rerank"
retriever=retriever, # Le retriever qui va chercher les documents pertinents
return_source_documents=True # Retourne aussi les documents sources utilisés
)
print("✅ Chaîne RAG créée et prête à répondre aux questions")
# ============================================================================
# ÉTAPE 4 : INTERROGATION DU SYSTÈME RAG
# ============================================================================
# Question à poser au système
question = "Quelles idées Paul Graham donne-t-il pour les startups ?"
print(f"\n📝 Question posée : {question}\n")
# Exécution de la chaîne RAG
# Le système va :
# 1. Chercher les 3 chunks les plus pertinents dans la base FAISS
# 2. Les donner au LLM avec la question
# 3. Générer une réponse basée sur ces documents
result = rag_chain({"query": question})
# ============================================================================
# ÉTAPE 5 : AFFICHAGE DES RÉSULTATS
# ============================================================================
print("=" * 80)
print("🤖 RÉPONSE DU SYSTÈME RAG")
print("=" * 80)
# Affichage de la réponse générée
print("\n📌 Réponse :")
print(result['result'])
# Affichage des documents sources utilisés
print("\n📚 Documents sources utilisés :")
for i, doc in enumerate(result['source_documents'], 1):
print(f"\n--- Document {i} ---")
print(doc.page_content[:200] + "...") # Affiche les 200 premiers caractères
print(f"Source : {doc.metadata}") # Métadonnées (fichier source, page, etc.)
print("\n" + "=" * 80)
# ============================================================================
# RÉSUMÉ DU PROCESSUS RAG
# ============================================================================
#
# 1. 📥 CHARGEMENT : On charge la base de données vectorielle FAISS
# 2. 🔍 RETRIEVAL : On cherche les documents pertinents pour la question
# 3. 🤖 GENERATION : Le LLM génère une réponse basée sur ces documents
# 4. ✅ RÉSULTAT : On obtient une réponse précise et sourcée
#
# AVANTAGES DU RAG :
# - Réponses basées sur vos propres documents
# - Pas d'hallucinations (le LLM s'appuie sur des sources réelles)
# - Traçabilité (on peut voir quels documents ont été utilisés)
# - Mise à jour facile (il suffit de mettre à jour la base FAISS)
#
# ============================================================================
# ============================================================================
# IMPORTATION DES BIBLIOTHÈQUES NÉCESSAIRES
# ============================================================================
from langchain.vectorstores import FAISS # Base de données vectorielle
from langchain.chat_models import ChatOpenAI # Modèle de langage (LLM)
from langchain.chains import RetrievalQA # Chaîne pour faire du Question-Answering avec récupération
from langchain.prompts import PromptTemplate # Pour personnaliser les prompts (non utilisé ici)
from dotenv import load_dotenv # Pour charger les variables d'environnement
import os # Pour accéder aux variables d'environnement
# ============================================================================
# ⚠️ IMPORTANT : CRÉATION DU FICHIER .env
# ============================================================================
#
# Avant d'exécuter ce code, vous DEVEZ créer un fichier nommé ".env"
# à la racine de votre projet (au même niveau que ce script Python)
#
# Contenu du fichier .env :
# -------------------------
# OPENAI_API_KEY=sk-votre-clé-api-ici
# OPENAI_MODEL_NAME=gpt-3.5-turbo
#
# ⚠️ SÉCURITÉ :
# - Ne JAMAIS partager ce fichier .env
# - Ne JAMAIS le commiter sur Git
# - Ajouter ".env" dans votre fichier .gitignore
#
# Structure du projet :
# ---------------------
# mon_projet/
# ├── .env ← Fichier à créer (contient les clés secrètes)
# ├── .gitignore ← Ajouter ".env" dedans
# ├── script_rag.py ← Ce fichier
# ├── faiss_db/ ← Base de données vectorielle
# └── requirements.txt ← Dépendances Python
#
# ============================================================================
# ============================================================================
# CONFIGURATION DU MODÈLE DE LANGAGE (LLM)
# ============================================================================
# Chargement des variables d'environnement depuis le fichier .env
# Cette fonction lit le fichier .env et charge les variables dans l'environnement
load_dotenv()
# Récupération des informations de connexion depuis les variables d'environnement
# Cela permet de ne pas exposer les clés API directement dans le code
api_key = os.getenv("OPENAI_API_KEY") # Votre clé API OpenAI
model_name = os.getenv("OPENAI_MODEL_NAME") # Nom du modèle (ex: "gpt-4", "gpt-3.5-turbo")
# ⚠️ Vérification que les variables ont bien été chargées
if not api_key:
raise ValueError(
"❌ ERREUR : La clé API n'a pas été trouvée !\n"
"Assurez-vous d'avoir créé un fichier .env avec :\n"
"OPENAI_API_KEY=votre-clé-ici"
)
if not model_name:
raise ValueError(
"❌ ERREUR : Le nom du modèle n'a pas été trouvé !\n"
"Assurez-vous d'avoir créé un fichier .env avec :\n"
"OPENAI_MODEL_NAME=gpt-3.5-turbo"
)
print("✅ Variables d'environnement chargées avec succès")
print(f" Modèle utilisé : {model_name}")
# Initialisation du modèle de langage
llm = ChatOpenAI(
model_name=model_name, # Modèle générique à utiliser
openai_api_key=api_key, # Clé d'authentification
temperature=0 # 0 = réponses déterministes, 1 = réponses créatives
)
# ============================================================================
# ÉTAPE 1 : CHARGEMENT DE LA BASE DE DONNÉES VECTORIELLE FAISS
# ============================================================================
# Chemin vers la base de données FAISS créée précédemment
faiss_index_path = "faiss_db"
print(f"Chargement de la base de données FAISS depuis : {faiss_index_path}")
# Chargement de la base de données vectorielle
# ⚠️ allow_dangerous_deserialization=True : nécessaire pour charger des fichiers pickle
# (à utiliser uniquement avec des sources de confiance)
db = FAISS.load_local(
faiss_index_path,
embeddings=embeddings, # Même modèle d'embeddings utilisé lors de la création
allow_dangerous_deserialization=True
)
print("✅ Base de données chargée avec succès")
# ============================================================================
# ÉTAPE 2 : CRÉATION DU RETRIEVER (RÉCUPÉRATEUR DE DOCUMENTS)
# ============================================================================
# Le retriever va chercher les morceaux de texte les plus pertinents
# en fonction de la question posée
retriever = db.as_retriever(
search_kwargs={"k": 3} # k=3 : récupère les 3 chunks les plus similaires à la question
)
print("✅ Retriever configuré pour récupérer 3 documents pertinents")
# ============================================================================
# ÉTAPE 3 : CRÉATION DE LA CHAÎNE RAG (Retrieval Augmented Generation)
# ============================================================================
# RAG = Récupération + Génération
# 1. On récupère les documents pertinents (Retrieval)
# 2. On les donne au LLM pour générer une réponse (Generation)
rag_chain = RetrievalQA.from_chain_type(
llm=llm, # Le modèle de langage qui va générer la réponse
chain_type="stuff", # "stuff" = concatène tous les documents récupérés dans le prompt
# Autres options : "map_reduce", "refine", "map_rerank"
retriever=retriever, # Le retriever qui va chercher les documents pertinents
return_source_documents=True # Retourne aussi les documents sources utilisés
)
print("✅ Chaîne RAG créée et prête à répondre aux questions")
# ============================================================================
# ÉTAPE 4 : INTERROGATION DU SYSTÈME RAG
# ============================================================================
# Question à poser au système
question = "Quelles idées Paul Graham donne-t-il pour les startups ?"
print(f"\n📝 Question posée : {question}\n")
# Exécution de la chaîne RAG
# Le système va :
# 1. Chercher les 3 chunks les plus pertinents dans la base FAISS
# 2. Les donner au LLM avec la question
# 3. Générer une réponse basée sur ces documents
result = rag_chain({"query": question})
# ============================================================================
# ÉTAPE 5 : AFFICHAGE DES RÉSULTATS
# ============================================================================
print("=" * 80)
print("🤖 RÉPONSE DU SYSTÈME RAG")
print("=" * 80)
# Affichage de la réponse générée
print("\n📌 Réponse :")
print(result['result'])
# Affichage des documents sources utilisés
print("\n📚 Documents sources utilisés :")
for i, doc in enumerate(result['source_documents'], 1):
print(f"\n--- Document {i} ---")
print(doc.page_content[:200] + "...") # Affiche les 200 premiers caractères
print(f"Source : {doc.metadata}") # Métadonnées (fichier source, page, etc.)
print("\n" + "=" * 80)
# ============================================================================
# RÉSUMÉ DU PROCESSUS RAG
# ============================================================================
#
# 1. 📥 CHARGEMENT : On charge la base de données vectorielle FAISS
# 2. 🔍 RETRIEVAL : On cherche les documents pertinents pour la question
# 3. 🤖 GENERATION : Le LLM génère une réponse basée sur ces documents
# 4. ✅ RÉSULTAT : On obtient une réponse précise et sourcée
#
# AVANTAGES DU RAG :
# - Réponses basées sur vos propres documents
# - Pas d'hallucinations (le LLM s'appuie sur des sources réelles)
# - Traçabilité (on peut voir quels documents ont été utilisés)
# - Mise à jour facile (il suffit de mettre à jour la base FAISS)
#
# ============================================================================