Tu as déjà utilisé ChatGPT. Tu sais qu'il peut répondre à des questions. Mais il y a un problème : il ne connaît rien de TES documents, de TES données, de TON entreprise. Il invente, il généralise, il date de sa date d'entraînement. Et si tu pouvais lui donner tes propres PDF, tes propres notes, tes propres bases de connaissances — et lui demander de répondre UNIQUEMENT à partir de ces documents ?
C'est exactement ce qu'on appelle le RAG (Retrieval-Augmented Generation), et c'est LA technique la plus importante de 2026 pour construire des applications IA utiles. Dans ce tutoriel, tu vas apprendre LangChain — le framework qui simplifie tout ça — en construisant un chatbot capable de lire tes documents et d'y répondre. De zéro. En Python. Code copier-coller garanti.
1. C'est quoi LangChain et le RAG ? (Le concept, sans migraine)
Le problème de ChatGPT
Demande à ChatGPT : « Quel est le chiffre d'affaires de mon entreprise en 2025 ? » Il va inventer une réponse. Pourquoi ? Parce qu'il n'a jamais vu tes documents. Il répond avec ce qu'il a appris pendant son entraînement, point.
La solution : le RAG
Le RAG résout ce problème en 3 étapes :
- Récupération (Retrieval) : Tu découpes tes documents en morceaux, tu les transformes en vecteurs numériques (des « embeddings »), et tu les ranges dans une base vectorielle.
- Recherche (Augmented) : Quand l'utilisateur pose une question, tu cherches les morceaux de documents les plus pertinents dans ta base.
- Génération (Generation) : Tu envoies la question + les morceaux trouvés à un LLM, avec un prompt du type « Réponds UNIQUEMENT en te basant sur les documents suivants ».
Résultat : le LLM répond avec les infos de TES documents. Plus d'invention, plus d'hallucinations (ou beaucoup moins).
Et LangChain dans tout ça ?
LangChain est le framework Python qui orchestre ces 3 étapes. Il gère : - Le découpage des documents (splitters) - La création d'embeddings (via OpenAI, Ollama, HuggingFace) - La base vectorielle (Chroma, FAISS, Pinecone) - La chaîne de question-réponse - La mémoire de conversation
Bref, LangChain transforme 300 lignes de code barbare en 30 lignes propres.
Idée d'illustration : Un schéma en 3 blocs avec des flèches : [Documents PDF] → [Découpage + Vectors] → [Base vectorielle] → [Question utilisateur] → [Recherche des morceaux pertinents] → [LLM + Prompt] → [Réponse sourcée]. Style néobrutaliste, couleurs #0a0e17 et #e8e4d8.
2. Prérequis : ce dont tu as besoin
- Python 3.10+ installé sur ta machine
- Une clé API OpenAI (compte gratuit avec 5 $ de crédit offerts — platform.openai.com) OU Ollama (voir tutoriel Ollama si tu veux du 100% local)
- Un PDF ou un fichier texte (ton CV, un rapport, un mode d'emploi — n'importe quoi)
- 5 minutes pour tout installer
Pour ce tutoriel, on utilise l'API OpenAI (simple et rapide). Tu peux remplacer par Ollama (gratuit, local) si tu as suivi le tutoriel Ollama — je te montre comment en section 7.
3. Installation : prépare ton environnement
Ouvre un terminal et crée un projet propre :
# Crée le dossier du projet
mkdir mon-chatbot-rag
cd mon-chatbot-rag
# Crée un environnement virtuel
python3 -m venv .venv
source .venv/bin/activate # Sur Windows : .venv\Scripts\activate
# Installe les dépendances
pip install langchain langchain-openai langchain-chroma chromadb pypdf2Voici ce que chaque paquet fait : - langchain : le framework principal - langchain-openai : connecteur pour OpenAI (embeddings + LLM) - langchain-chroma : intégration de la base vectorielle ChromaDB - chromadb : la base vectorielle elle-même (légère, locale, parfaite pour commencer) - pypdf2 : pour lire les fichiers PDF
Configure ta clé API OpenAI (crée-la sur platform.openai.com/api-keys) :
export OPENAI_API_KEY="sk-ta-clé-api-ici" Ce que tu dois voir : pip install télécharge les paquets sans erreur. Vérifie avec python3 -c "import langchain; print(langchain.__version__)" — tu dois voir un numéro de version.
4. Ton premier script LangChain : un chatbot basique
Avant de plonger dans le RAG, voyons comment LangChain simplifie déjà un simple appel à un LLM. Crée 01_chat_simple.py :
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
# 1. Initialise le modèle
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
# 2. Définis le comportement avec un message système
messages = [
SystemMessage(content="Tu es un assistant francophone, pédagogue et enthousiaste. Réponds toujours en français."),
HumanMessage(content="Explique-moi ce qu'est une base vectorielle en une phrase simple.")
]
# 3. Appelle le modèle
reponse = llm.invoke(messages)
print(" Assistant :")
print(reponse.content)Lance-le :
python3 01_chat_simple.pyCe que tu dois voir : Une réponse en français qui explique les bases vectorielles simplement — par exemple « Une base vectorielle, c'est une bibliothèque qui range les documents non pas par mots-clés mais par similarité de sens, comme quand ton cerveau associe "chat" à "félin" même si le mot est différent. »
Pas impressionnant ? Normal, c'est juste un appel à ChatGPT. Le vrai pouvoir arrive maintenant.
5. Le RAG complet : ton chatbot qui lit tes documents
Étape 1 : Prépare un document de test
Pour ce tutoriel, crée un document sur ton entreprise fictive. Crée mon_entreprise.txt :
cat > mon_entreprise.txt << 'EOF'
RAPPORT ANNUEL 2025 - TECHVERT SAS
TechVert est une entreprise française fondée en 2021 par Marie Durant et Lucas Bernard.
Spécialisée dans les solutions de recharge solaire pour véhicules électriques.
Chiffres clés 2025 :
- Chiffre d'affaires : 4,2 millions d'euros (+35% vs 2024)
- Effectif : 47 employés (siège à Grenoble)
- 3 brevets déposés en 2025
- Partenariat signé avec Renault en septembre 2025
Produits phares :
1. SolarCharge Pro : borne de recharge solaire 22 kW - prix public 4 900 €
2. SolarCharge Lite : borne domestique 7 kW - prix public 1 490 €
3. SunPack Mobile : batterie portable solaire pour camping-cars - prix public 299 €
Objectifs 2026 :
- Ouvrir un bureau à Berlin (T2 2026)
- Lancer la SolarCharge Ultra (50 kW, recharge rapide)
- Atteindre 8 millions d'euros de chiffre d'affaires
- Recruter 20 nouveaux collaborateurs
Contact : contact@techvert-solar.fr
Site web : www.techvert-solar.fr
EOFÉtape 2 : Le script RAG complet
Crée 02_chatbot_rag.py :
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
import os
# ====== 1. CHARGE ET DÉCOUPE LE DOCUMENT ======
print(" Chargement du document...")
loader = TextLoader("mon_entreprise.txt", encoding="utf-8")
documents = loader.load()
# Découpe le document en morceaux de 500 caractères avec 50 de chevauchement
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", ". ", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f" Document découpé en {len(chunks)} morceaux")
# ====== 2. CRÉE LES EMBEDDINGS ET LA BASE VECTORIELLE ======
print(" Création des embeddings (transformation en vecteurs)...")
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# ChromaDB stocke les morceaux + leurs vecteurs localement
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./ma_base_vectorielle"
)
print(f" Base vectorielle créée avec {len(chunks)} documents")
# ====== 3. INITIALISE LE CHATBOT RAG ======
print(" Initialisation du chatbot...")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.2)
# RetrievalQA : la chaîne qui combine recherche + génération
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # "stuff" = envoie tous les morceaux trouvés au LLM
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}), # Récupère les 3 plus pertinents
return_source_documents=True, # Pour voir D'OÙ vient la réponse
verbose=False
)
# ====== 4. POSE DES QUESTIONS ! ======
print("\n" + "="*60)
print(" CHATBOT RAG — Pose tes questions (tape 'quit' pour sortir)")
print("="*60 + "\n")
while True:
question = input(" Toi : ")
if question.lower() in ["quit", "exit", "q"]:
print(" À bientôt !")
break
resultat = qa_chain.invoke({"query": question})
print(f"\n Assistant : {resultat['result']}")
# Affiche les sources utilisées
print("\n Sources utilisées :")
sources_vues = set()
for doc in resultat["source_documents"]:
contenu = doc.page_content.strip()[:120]
if contenu not in sources_vues:
print(f" • {contenu}...")
sources_vues.add(contenu)
print()Étape 3 : Lance et teste
python3 02_chatbot_rag.py Ce que tu dois voir : Le script charge ton document, le découpe, crée la base vectorielle, puis te présente un prompt Toi :.
Pose ces questions et observe :
Toi : Qui a fondé TechVert ?
Assistant : TechVert a été fondée par Marie Durant et Lucas Bernard en 2021.
Sources utilisées :
• TechVert est une entreprise française fondée en 2021 par Marie Durant et Lucas Bernard...
Toi : Quel est le prix du SolarCharge Pro ?
Assistant : Le SolarCharge Pro est proposé au prix public de 4 900 €.
Sources utilisées :
• 1. SolarCharge Pro : borne de recharge solaire 22 kW - prix public 4 900 €...Félicitations ! Ton chatbot vient de répondre à des questions sur des informations qu'il n'avait JAMAIS vues avant. Il les a lues, comprises, et citées. C'est ça, le RAG.
6. Cas avancé : mémoire de conversation et plusieurs documents
Un vrai chatbot se souvient de ce que tu as dit avant. Améliorons notre création avec 03_chatbot_memoire.py :
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import ConversationalRetrievalChain
from langchain.document_loaders import DirectoryLoader
from langchain.memory import ConversationBufferMemory
import os
# ====== 1. CHARGE TOUS LES DOCUMENTS D'UN DOSSIER ======
print(" Chargement des documents depuis le dossier 'docs/'...")
# Crée le dossier s'il n'existe pas
os.makedirs("docs", exist_ok=True)
# Charge tous les fichiers .txt du dossier docs/
loader = DirectoryLoader("docs/", glob="*.txt", loader_cls=TextLoader)
documents = loader.load()
# Si le dossier est vide, charge le fichier par défaut
if not documents:
print(" Aucun .txt trouvé dans docs/, chargement du fichier par défaut...")
loader = TextLoader("mon_entreprise.txt", encoding="utf-8")
documents = loader.load()
# Découpage
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
print(f" {len(documents)} document(s) chargé(s), {len(chunks)} morceaux")
# ====== 2. EMBEDDINGS + BASE VECTORIELLE ======
print(" Création des embeddings...")
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./ma_base_vectorielle"
)
# ====== 3. MÉMOIRE DE CONVERSATION ======
print(" Initialisation de la mémoire...")
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer"
)
# ====== 4. CHAÎNE DE CONVERSATION RAG ======
print(" Démarrage du chatbot avec mémoire...")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
memory=memory,
return_source_documents=True,
verbose=False
)
# ====== 5. BOUCLE DE CHAT ======
print("\n" + "="*60)
print(" CHATBOT RAG AVEC MÉMOIRE (tape 'quit' pour sortir)")
print("="*60 + "\n")
while True:
question = input(" Toi : ")
if question.lower() in ["quit", "exit", "q"]:
print(" À bientôt !")
break
resultat = qa_chain.invoke({"question": question})
print(f"\n Assistant : {resultat['answer']}\n")Lance-le :
python3 03_chatbot_memoire.pyTeste la mémoire :
Toi : Quel est le chiffre d'affaires de TechVert en 2025 ?
Assistant : Le chiffre d'affaires de TechVert en 2025 est de 4,2 millions d'euros.
Toi : Et quel pourcentage de croissance ça représente ?
Assistant : Cela représente une croissance de 35% par rapport à 2024.Le chatbot se souvient que tu parlais de TechVert et de 2025. C'est la mémoire conversationnelle en action.
Pour ajouter tes propres documents : dépose tous tes .txt et .pdf dans le dossier docs/ et relance le script. Le chatbot les ingérera automatiquement.
Pour les PDF, ajoute
from langchain.document_loaders import PyPDFLoaderet adapte leDirectoryLoader. Le code complet est dans la section « Aller plus loin ».
7. Version gratuite avec Ollama (sans API OpenAI)
Si tu as suivi le tutoriel Ollama et que tu veux du 100% local, gratuit, et privé, voici la version modifiée. Crée 04_chatbot_rag_local.py :
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_chroma import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain.document_loaders import TextLoader
# ====== CONFIGURATION OLLAMA (100% LOCAL) ======
print(" Démarrage avec Ollama (local, gratuit, privé)...")
# Charge le document
loader = TextLoader("mon_entreprise.txt", encoding="utf-8")
documents = loader.load()
# Découpe
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
print(f" {len(chunks)} morceaux")
# Embeddings Ollama (gratuit, local)
embeddings = OllamaEmbeddings(model="nomic-embed-text")
# Base vectorielle locale
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./ma_base_ollama"
)
# Modèle Ollama local
llm = ChatOllama(model="llama3.2", temperature=0.2)
# Chaîne RAG
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever(),
return_source_documents=True
)
print(" Chatbot prêt ! (coût : 0 €, données : 100% locales)\n")
# Boucle de chat
while True:
question = input(" Toi : ")
if question.lower() in ["quit", "exit", "q"]:
break
resultat = qa_chain.invoke({"query": question})
print(f"\n Assistant : {resultat['result']}\n")# Installe le connecteur Ollama pour LangChain
pip install langchain-ollama
# Télécharge le modèle d'embeddings (une fois)
ollama pull nomic-embed-text
# Lance le chatbot local gratuit
python3 04_chatbot_rag_local.py8. Pièges classiques (et comment les éviter)
Piège n°1 : « Mon chatbot invente des réponses »
Cause : Les morceaux récupérés ne contiennent pas la réponse, donc le LLM « hallucine ».
Solutions : - Augmente chunk_size (essaie 800-1000) pour avoir des morceaux plus complets - Augmente k dans le retriever (search_kwargs={"k": 5}) pour récupérer plus de morceaux - Ajoute un prompt qui force le LLM à dire « Je ne sais pas » : chain_type_kwargs={"prompt": ton_prompt_personnalisé}
Piège n°2 : « ModuleNotFoundError: No module named 'chromadb' »
Solution : Réinstalle chromadb explicitement :
pip uninstall chromadb -y && pip install chromadbPiège n°3 : « J'ai une erreur 429 (rate limit) avec OpenAI »
Cause : Tu utilises un compte gratuit qui a des limites basses.
Solutions : - Passe à Ollama (section 7, gratuit et illimité) - Ajoute un délai entre les appels - Vérifie ton quota sur platform.openai.com/usage
Piège n°4 : « Les réponses sont nulles, le LLM répond à côté »
Cause : La température est trop élevée, ou les morceaux sont trop petits.
Solution : Baisse la température à 0.0 ou 0.1 pour des réponses factuelles, et teste différentes tailles de chunks.
Piège n°5 : « ChromaDB persiste mes anciens documents, même après suppression »
Solution : Supprime le dossier de persistance pour repartir de zéro :
rm -rf ./ma_base_vectorielle9. Pour aller plus loin
1. Ajouter le support des PDF
Remplace le TextLoader par PyPDFLoader :
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("mon_document.pdf")
documents = loader.load()
# Le reste est identique !Et pour un dossier complet de PDF :
from langchain.document_loaders import DirectoryLoader, PyPDFLoader
loader = DirectoryLoader("docs/", glob="*.pdf", loader_cls=PyPDFLoader)2. Transformer ton chatbot en application web avec Streamlit
En 20 lignes, tu as une interface web :
pip install streamlit# app_streamlit.py
import streamlit as st
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.chains import RetrievalQA
st.title(" Mon Chatbot RAG")
# Initialise le chatbot une seule fois
@st.cache_resource
def init_rag():
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
loader = TextLoader("mon_entreprise.txt", encoding="utf-8")
docs = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50).split_documents(loader.load())
vs = Chroma.from_documents(docs, OpenAIEmbeddings(model="text-embedding-3-small"))
return RetrievalQA.from_chain_type(llm=ChatOpenAI(model="gpt-4o-mini", temperature=0.2), retriever=vs.as_retriever())
qa = init_rag()
question = st.text_input("Pose ta question :")
if question:
reponse = qa.invoke({"query": question})
st.success(reponse["result"])
with st.expander(" Sources"):
for doc in reponse["source_documents"]:
st.info(doc.page_content[:200])streamlit run app_streamlit.py3. Chaîner plusieurs étapes avec LCEL (LangChain Expression Language)
Le vrai pouvoir de LangChain, c'est d'enchaîner les étapes :
from langchain.schema.runnable import RunnablePassthrough
from langchain.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("""
Tu es un assistant. Réponds UNIQUEMENT avec les informations ci-dessous.
Si l'information n'est pas présente, dis "Je ne trouve pas cette information dans les documents."
Documents de référence :
{context}
Question : {question}
""")
chain = (
{"context": vectorstore.as_retriever(), "question": RunnablePassthrough()}
| prompt
| llm
)
reponse = chain.invoke("Qui a fondé TechVert ?")
print(reponse.content)Conclusion
En 25 minutes, tu viens de :
Comprendre le concept de RAG et pourquoi c'est révolutionnaire Installer LangChain et son écosystème Construire un chatbot simple avec mémoire Créer un chatbot RAG qui lit TES documents et y répond Découvrir la version 100% locale avec Ollama Identifier les pièges classiques et leurs solutions
Tu as maintenant la compétence IA la plus recherchée en 2026. Le RAG est partout : support client, analyse juridique, recherche médicale, chatbots d'entreprise, assistants personnels...
La seule limite, c'est les documents que tu lui donnes. Alors nourris-le.
Idée d'illustration : Un split screen : à gauche, un personnage dépose des documents (PDF, TXT) dans une « boîte magique » (base vectorielle). À droite, un autre personnage pose une question, et la réponse sort de la boîte avec des surlignages montrant les passages utilisés. Style flat design, couleurs chaudes, l'air de rien comprendre mais en fait tout comprendre.

