LangChain : guide pratique et cookbook avec 50+ recettes de code prêtes à l'emploi
Ce guide pratique est votre boîte à outils LangChain : des dizaines de recettes de code prêtes à l’emploi, testées et commentées, que vous pouvez directement intégrer dans vos projets. Plutôt qu’un tutoriel linéaire, c’est un cookbook organisé par cas d’usage, où vous pouvez piocher ce dont vous avez besoin.

Table des matières
- Installation et configuration
- Recettes de base
- Chatbots et conversations
- RAG (Retrieval-Augmented Generation)
- Agents et outils
- Intégrations externes
- Production et monitoring
- Optimisations et performances
- Troubleshooting
Installation et configuration
Installation complète
# Core
pip install langchain langchain-community
# Providers LLM
pip install langchain-openai langchain-anthropic langchain-google-genai
# RAG et embeddings
pip install langchain-chroma chromadb tiktoken sentence-transformers
# Outils et utilitaires
pip install langchain-experimental duckduckgo-search wikipedia
# Document loaders
pip install pypdf beautifulsoup4 unstructured
# Production
pip install langsmith langserve
# API web (optionnel)
pip install fastapi uvicorn
Configuration des clés API
import os
from dotenv import load_dotenv
# Charger depuis .env
load_dotenv()
# OpenAI
os.environ["OPENAI_API_KEY"] = "sk-..."
# Anthropic
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
# Google
os.environ["GOOGLE_API_KEY"] = "..."
# LangSmith (monitoring)
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls-..."
os.environ["LANGCHAIN_PROJECT"] = "mon-projet"
Fichier .env :
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=...
LANGCHAIN_API_KEY=ls-...
🔒 Sécurité : Ne committez JAMAIS le fichier .env dans Git ! Ajoutez-le immédiatement à .gitignore. Utilisez des variables d’environnement ou des gestionnaires de secrets en production.
Template de projet
mon-projet-langchain/
├── .env # Clés API
├── .gitignore # Ne pas committer .env
├── requirements.txt # Dépendances
├── config.py # Configuration centralisée
├── main.py # Point d'entrée
├── chains/ # Vos chains
│ ├── chatbot.py
│ └── rag.py
├── agents/ # Vos agents
│ └── research_agent.py
├── tools/ # Outils personnalisés
│ └── custom_tools.py
├── data/ # Données sources
│ └── documents/
└── vectorstores/ # Bases vectorielles persistées
└── chroma_db/
Recettes de base
Appel LLM simple
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
response = llm.invoke("Explique la photosynthèse en 3 phrases")
print(response.content)
Prompt template dynamique
from langchain.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "Tu es un expert en {domaine}."),
("human", "{question}")
])
chain = prompt | llm
response = chain.invoke({
"domaine": "astronomie",
"question": "Qu'est-ce qu'un trou noir ?"
})
print(response.content)
Chain avec output parser
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
class Recette(BaseModel):
nom: str = Field(description="Nom de la recette")
ingredients: list[str] = Field(description="Liste des ingrédients")
etapes: list[str] = Field(description="Étapes de préparation")
parser = PydanticOutputParser(pydantic_object=Recette)
prompt = ChatPromptTemplate.from_messages([
("system", "Tu génères des recettes de cuisine.\n{format_instructions}"),
("human", "Crée une recette de {plat}")
])
chain = prompt | llm | parser
result = chain.invoke({
"plat": "pâtes carbonara",
"format_instructions": parser.get_format_instructions()
})
print(f"Recette: {result.nom}")
print(f"Ingrédients: {', '.join(result.ingredients)}")
Chain avec streaming
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
llm = ChatOpenAI(
model="gpt-4",
streaming=True,
callbacks=[StreamingStdOutCallbackHandler()]
)
chain = prompt | llm
# S'affiche token par token
for chunk in chain.stream({"question": "Raconte une histoire"}):
print(chunk.content, end="", flush=True)
Multi-LLM avec fallback
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
primary = ChatOpenAI(model="gpt-4", request_timeout=10)
fallback = ChatAnthropic(model="claude-sonnet-4.5")
llm = primary.with_fallbacks([fallback])
chain = prompt | llm
response = chain.invoke({"question": "..."})
# Utilise Claude si OpenAI échoue ou timeout
💡 Best practice : Utilisez toujours LCEL (pipe operator
|) plutôt que les classes legacy comme LLMChain. LCEL active automatiquement le streaming, le batching parallèle, et le tracing LangSmith.Chatbots et conversations
Chatbot avec mémoire
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
chatbot = ConversationChain(
llm=llm,
memory=memory,
verbose=True
)
# Conversation
chatbot.predict(input="Bonjour, je m'appelle Sophie")
# → "Enchanté Sophie..."
chatbot.predict(input="Quel est mon nom ?")
# → "Votre nom est Sophie" (se souvient)
Chatbot avec fenêtre de contexte
from langchain.memory import ConversationBufferWindowMemory
# Garde seulement les 5 derniers échanges
memory = ConversationBufferWindowMemory(k=5)
chatbot = ConversationChain(llm=llm, memory=memory)
Chatbot avec résumé automatique
from langchain.memory import ConversationSummaryMemory
# Résume automatiquement quand trop long
memory = ConversationSummaryMemory(llm=llm)
chatbot = ConversationChain(llm=llm, memory=memory)
Chatbot multilingue
from langchain.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", """Tu es un assistant multilingue.
Détecte automatiquement la langue de l'utilisateur et réponds dans cette langue.
Langues supportées: français, anglais, espagnol, allemand."""),
("human", "{input}")
])
chatbot = prompt | llm
response = chatbot.invoke({"input": "Hola, ¿cómo estás?"})
# → Répond en espagnol
Chatbot avec personnalité
persona_prompt = ChatPromptTemplate.from_messages([
("system", """Tu es {persona_name}, {persona_description}.
Tu parles toujours selon ce style: {style}.
Historique de conversation:
{chat_history}"""),
("human", "{input}")
])
def create_persona_chatbot(name, description, style):
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
chain = LLMChain(llm=llm, prompt=persona_prompt, memory=memory)
def chat(message):
return chain.predict(
persona_name=name,
persona_description=description,
style=style,
input=message
)
return chat
# Utilisation
pirate_bot = create_persona_chatbot(
name="Captain Jack",
description="un pirate des Caraïbes",
style="utilise l'argot pirate et dis 'Arr!' souvent"
)
response = pirate_bot("Bonjour !")
# → "Arr! Bonjour moussaillon !..."
RAG (Retrieval-Augmented Generation)
RAG simple sur PDF
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
# 1. Charger
loader = PyPDFLoader("document.pdf")
documents = loader.load()
# 2. Découper
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(documents)
# 3. Embeddings + VectorStore
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(splits, embeddings)
# 4. RAG Chain
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(),
return_source_documents=True
)
# 5. Question
result = qa_chain("Résume le chapitre 3")
print(result['result'])
print(f"Sources: {[doc.metadata for doc in result['source_documents']]}")
RAG sur plusieurs PDFs
from langchain_community.document_loaders import DirectoryLoader
loader = DirectoryLoader(
"./documents",
glob="**/*.pdf",
loader_cls=PyPDFLoader,
show_progress=True
)
documents = loader.load()
print(f"Chargé {len(documents)} pages depuis {len(set([d.metadata['source'] for d in documents]))} fichiers")
# Suite identique à la recette 11
RAG avec Chroma persistant
from langchain_community.vectorstores import Chroma
# Création initiale
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db"
)
# --- Dans un autre script ou plus tard ---
# Rechargement (pas besoin de réindexer)
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings
)
retriever = vectorstore.as_retriever()
RAG avec filtres de métadonnées
# Ajouter des métadonnées aux documents
for doc in splits:
doc.metadata["category"] = "technical"
doc.metadata["year"] = 2025
vectorstore = Chroma.from_documents(splits, embeddings)
# Retriever avec filtre
retriever = vectorstore.as_retriever(
search_kwargs={
"k": 5,
"filter": {
"category": "technical",
"year": {"$gte": 2020}
}
}
)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever
)
RAG conversationnel
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chains import create_history_aware_retriever
from langchain_core.messages import HumanMessage, AIMessage
# Retriever
retriever = vectorstore.as_retriever()
# Prompt pour reformuler avec historique
contextualize_prompt = ChatPromptTemplate.from_messages([
("system", "Reformule la dernière question en une question autonome, en utilisant l'historique."),
MessagesPlaceholder("chat_history"),
("human", "{input}")
])
history_aware_retriever = create_history_aware_retriever(
llm, retriever, contextualize_prompt
)
# Prompt QA
qa_prompt = ChatPromptTemplate.from_messages([
("system", "Réponds en te basant sur le contexte:\n\n{context}"),
MessagesPlaceholder("chat_history"),
("human", "{input}")
])
document_chain = create_stuff_documents_chain(llm, qa_prompt)
rag_chain = create_retrieval_chain(history_aware_retriever, document_chain)
# Conversation
chat_history = []
response1 = rag_chain.invoke({
"input": "Parle-moi de LoRA",
"chat_history": chat_history
})
print(response1["answer"])
chat_history.extend([
HumanMessage(content="Parle-moi de LoRA"),
AIMessage(content=response1["answer"])
])
response2 = rag_chain.invoke({
"input": "Quels sont ses avantages ?", # Contexte conservé
"chat_history": chat_history
})
print(response2["answer"])
Agents et outils
Agent de recherche basique
from langchain.agents import AgentExecutor, create_react_agent
from langchain_community.tools import DuckDuckGoSearchRun
from langchain.tools import Tool
search = DuckDuckGoSearchRun()
tools = [
Tool(
name="Search",
func=search.run,
description="Recherche sur le web pour des informations actuelles"
)
]
from langchain import hub
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
max_iterations=5
)
result = agent_executor.invoke({
"input": "Qui a gagné la dernière Coupe du Monde de football ?"
})
Agent avec calculatrice
from langchain_community.utilities import GoogleSerperAPIWrapper
from langchain.tools import Tool
def calculate(expression: str) -> str:
"""Calcule une expression mathématique"""
try:
# Utilise eval de manière sécurisée
import ast
import operator
operators = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow
}
def eval_expr(node):
if isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.BinOp):
return operators[type(node.op)](
eval_expr(node.left),
eval_expr(node.right)
)
else:
raise TypeError(node)
return str(eval_expr(ast.parse(expression, mode='eval').body))
except:
return "Erreur de calcul"
tools = [
Tool(
name="Calculator",
func=calculate,
description="Effectue des calculs mathématiques. Input: expression comme '2+2' ou '10*5'"
)
]
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = agent_executor.invoke({
"input": "Combien font 1234 multiplié par 5678 ?"
})
Agent avec outil personnalisé
from langchain.pydantic_v1 import BaseModel, Field
class WeatherInput(BaseModel):
"""Input pour l'outil météo"""
city: str = Field(description="Nom de la ville")
def get_weather(city: str) -> str:
"""Obtient la météo (exemple simplifié)"""
# En vrai, appel à une API météo
import random
temp = random.randint(10, 30)
conditions = ["ensoleillé", "nuageux", "pluvieux"]
return f"{city}: {temp}°C, {random.choice(conditions)}"
from langchain.tools import StructuredTool
weather_tool = StructuredTool.from_function(
func=get_weather,
name="Weather",
description="Donne la météo actuelle d'une ville",
args_schema=WeatherInput
)
tools = [weather_tool]
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)
result = agent_executor.invoke({
"input": "Quelle est la météo à Paris ?"
})
Agent RAG
from langchain.tools.retriever import create_retriever_tool
# Retriever (voir recettes RAG)
retriever = vectorstore.as_retriever()
# Transformer en outil
doc_tool = create_retriever_tool(
retriever,
name="DocumentSearch",
description="Recherche dans la documentation technique. Utilise pour répondre aux questions sur les produits."
)
tools = [search, doc_tool]
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# L'agent décide automatiquement entre web et docs
result = agent_executor.invoke({
"input": "Comment fonctionne le fine-tuning avec LoRA ?"
})
Agent SQL
from langchain.agents import create_sql_agent
from langchain.sql_database import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///database.db")
sql_agent = create_sql_agent(
llm=llm,
db=db,
agent_type="openai-tools",
verbose=True
)
result = sql_agent.invoke({
"input": "Combien d'utilisateurs ont acheté un produit en janvier 2025 ?"
})
# L'agent génère et exécute automatiquement les requêtes SQL
⚠️ Agents et coûts : Les agents effectuent 3-10× plus d’appels LLM qu’une chaîne simple (réflexion + planification + exécution + vérification). Limitez max_iterations et surveillez les coûts avec LangSmith avant de déployer en production !
Intégrations externes
Charger depuis une URL
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader([
"https://naileru.com/ia/rag/",
"https://naileru.com/ia/embedding/"
])
documents = loader.load()
print(f"Chargé {len(documents)} pages web")
Charger depuis Google Drive
from langchain_community.document_loaders import GoogleDriveLoader
loader = GoogleDriveLoader(
folder_id="your_folder_id",
token_path="token.json", # OAuth token
recursive=True
)
documents = loader.load()
Charger depuis Notion
from langchain_community.document_loaders import NotionDirectoryLoader
# Export Notion au format Markdown
loader = NotionDirectoryLoader("./notion_export")
documents = loader.load()
# Chaque page Notion devient un document
Intégration Slack
from slack_sdk import WebClient
from langchain.tools import Tool
slack_client = WebClient(token="xoxb-...")
def send_slack_message(text: str, channel: str = "#general") -> str:
"""Envoie un message sur Slack"""
try:
result = slack_client.chat_postMessage(
channel=channel,
text=text
)
return f"Message envoyé dans {channel}"
except Exception as e:
return f"Erreur: {str(e)}"
slack_tool = Tool(
name="SlackMessage",
func=send_slack_message,
description="Envoie un message sur Slack. Input: 'message|#channel'"
)
Appel API REST
import requests
from langchain.tools import Tool
def call_api(endpoint: str) -> str:
"""Appelle une API REST"""
base_url = "https://api.example.com"
try:
response = requests.get(f"{base_url}/{endpoint}")
response.raise_for_status()
return response.json()
except Exception as e:
return f"Erreur API: {str(e)}"
api_tool = Tool(
name="APICall",
func=call_api,
description="Appelle l'API interne. Input: endpoint (ex: 'users/123')"
)
Production et monitoring
Logging avec LangSmith
import os
# Configuration
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls-..."
os.environ["LANGCHAIN_PROJECT"] = "production-app"
# Tout est automatiquement tracé
chain = prompt | llm
response = chain.invoke({"question": "..."})
# Voir les traces sur langsmith.com
Callback personnalisé
from langchain.callbacks.base import BaseCallbackHandler
class MetricsCallback(BaseCallbackHandler):
def __init__(self):
self.total_tokens = 0
self.total_cost = 0
self.call_count = 0
def on_llm_start(self, serialized, prompts, **kwargs):
self.call_count += 1
print(f"[{self.call_count}] LLM call started")
def on_llm_end(self, response, **kwargs):
tokens = response.llm_output.get('token_usage', {})
total = tokens.get('total_tokens', 0)
self.total_tokens += total
self.total_cost += (total / 1000) * 0.03 # $0.03 per 1K tokens
print(f"Tokens: {total} | Total: {self.total_tokens} | Coût: ${self.total_cost:.4f}")
metrics = MetricsCallback()
chain = prompt | llm
response = chain.invoke(
{"question": "..."},
config={"callbacks": [metrics]}
)
API REST avec LangServe
from fastapi import FastAPI
from langserve import add_routes
app = FastAPI(
title="Mon API LangChain",
version="1.0"
)
# Ajouter une chain comme endpoint
add_routes(
app,
prompt | llm,
path="/chat"
)
# Lancer: uvicorn main:app --reload
# Utiliser: POST http://localhost:8000/chat/invoke
Cache Redis
from langchain.cache import RedisCache
from langchain.globals import set_llm_cache
import redis
redis_client = redis.Redis(
host='localhost',
port=6379,
db=0
)
set_llm_cache(RedisCache(redis_client))
# Les appels identiques sont cachés
response1 = llm.invoke("Question") # Appel API
response2 = llm.invoke("Question") # Cache (instantané)
Retry avec Tenacity
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10),
reraise=True
)
def robust_chain_call(input_data):
"""Chain avec retry automatique"""
try:
return chain.invoke(input_data)
except Exception as e:
print(f"Erreur: {e}, retry...")
raise
result = robust_chain_call({"question": "..."})
Optimisations et performances
Batch processing
# Au lieu de boucler (lent)
questions = ["Question 1", "Question 2", "Question 3"]
# Mauvais
# for q in questions:
# response = llm.invoke(q)
# Bon (parallélisé automatiquement)
responses = llm.batch([{"question": q} for q in questions])
Async pour la performance
import asyncio
async def process_documents_async(documents):
"""Traitement parallèle des documents"""
embeddings = OpenAIEmbeddings()
# Créer embeddings en parallèle
tasks = [embeddings.aembed_query(doc.page_content) for doc in documents]
vectors = await asyncio.gather(*tasks)
return vectors
# Utilisation
vectors = asyncio.run(process_documents_async(documents))
Cache d’embeddings
from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import LocalFileStore
store = LocalFileStore("./embedding_cache")
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
embeddings,
store,
namespace="openai-embeddings"
)
# Première fois: calcul + cache
vectorstore = FAISS.from_documents(documents, cached_embeddings)
# Prochaines fois: lecture du cache (gratuit et instantané)
💰 Économisez sur les embeddings : Les embeddings OpenAI coûtent $0.13 par million de tokens. Sur un corpus de 10K documents, le cache peut vous faire économiser des centaines de dollars en retraitement !
Compression de contexte
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever()
)
# Documents retournés sont automatiquement compressés (50-70% plus courts)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=compression_retriever
)
Hybrid search (mots-clés + sémantique)
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# Retriever par mots-clés
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 5
# Retriever sémantique
semantic_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# Combinaison
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, semantic_retriever],
weights=[0.3, 0.7] # 30% mots-clés, 70% sémantique
)
# Meilleure précision sur les termes techniques
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=ensemble_retriever
)
Troubleshooting
Dépassement de tokens
# Solution: Compter les tokens avant
import tiktoken
def count_tokens(text: str, model: str = "gpt-4") -> int:
encoding = tiktoken.encoding_for_model(model)
return len(encoding.encode(text))
# Vérifier avant d'envoyer
text = "..."
tokens = count_tokens(text)
print(f"Tokens: {tokens}")
if tokens > 8000: # Limite GPT-4
# Découper ou résumer
print("Texte trop long, découpage nécessaire")
Erreurs de rate limit
from langchain.llms.openai import OpenAI
from langchain.callbacks import get_openai_callback
# Tracker les tokens
with get_openai_callback() as cb:
response = chain.invoke({"question": "..."})
print(f"Tokens: {cb.total_tokens}")
print(f"Coût: ${cb.total_cost}")
if cb.total_tokens > 10000:
print("Attention: consommation élevée")
# Rate limiting manuel
import time
def rate_limited_call(chain, input_data, delay=1):
result = chain.invoke(input_data)
time.sleep(delay) # Pause entre appels
return result
Documents non retrouvés dans RAG
# Vérifier la qualité du retrieval
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# Test de similarité
query = "Comment fonctionne LoRA ?"
docs = retriever.get_relevant_documents(query)
for i, doc in enumerate(docs):
print(f"\n--- Document {i+1} ---")
print(f"Score: {doc.metadata.get('score', 'N/A')}")
print(doc.page_content[:200])
# Si les scores sont trop bas (<0.5), améliorer:
# 1. Chunks plus petits
# 2. Meilleur modèle d'embeddings
# 3. Hybrid search
Agent en boucle infinie
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
max_iterations=10, # Force l'arrêt
max_execution_time=60, # Timeout 60s
early_stopping_method="generate", # Génère une réponse même si incomplet
verbose=True
)
try:
result = agent_executor.invoke({"input": "..."})
except Exception as e:
print(f"Agent stoppé: {e}")
Hallucinations
# Prompt strict pour RAG
strict_prompt = ChatPromptTemplate.from_template("""
Réponds UNIQUEMENT en te basant sur le contexte fourni.
Si la réponse n'est PAS dans le contexte, réponds EXACTEMENT:
"Je ne trouve pas cette information dans les documents."
NE JAMAIS inventer ou déduire des informations non présentes.
Contexte:
{context}
Question: {input}
Réponse:""")
# Chain avec prompt strict
document_chain = create_stuff_documents_chain(llm, strict_prompt)
rag_chain = create_retrieval_chain(retriever, document_chain)
# + Utiliser temperature=0 pour réduire la créativité
llm = ChatOpenAI(model="gpt-4", temperature=0)
🎯 Anti-hallucination : La principale cause d’hallucination en RAG est un retrieval de mauvaise qualité. Avant d’ajuster les prompts, vérifiez toujours la pertinence des documents récupérés avec retriever.get_relevant_documents().
Recettes bonus
Extraction d’entités
from langchain.output_parsers import ResponseSchema, StructuredOutputParser
schemas = [
ResponseSchema(name="nom", description="Nom de la personne"),
ResponseSchema(name="age", description="Âge en années"),
ResponseSchema(name="ville", description="Ville de résidence")
]
parser = StructuredOutputParser.from_response_schemas(schemas)
prompt = ChatPromptTemplate.from_template("""
Extrait les informations suivantes du texte:
{format_instructions}
Texte: {text}
""")
chain = prompt | llm | parser
result = chain.invoke({
"text": "Sophie a 28 ans et habite à Lyon.",
"format_instructions": parser.get_format_instructions()
})
print(result) # {'nom': 'Sophie', 'age': '28', 'ville': 'Lyon'}
Classification de texte
from enum import Enum
class Category(str, Enum):
TECHNICAL = "technique"
SUPPORT = "support"
SALES = "vente"
OTHER = "autre"
classification_prompt = ChatPromptTemplate.from_template("""
Classifie le message suivant dans une catégorie:
- technique: questions techniques, bugs
- support: aide, how-to
- vente: demandes commerciales
- autre: reste
Message: {message}
Catégorie (un seul mot):""")
def classify_message(message: str) -> str:
chain = classification_prompt | llm
response = chain.invoke({"message": message})
category = response.content.strip().lower()
# Validation
try:
return Category(category).value
except ValueError:
return Category.OTHER.value
# Test
print(classify_message("Comment installer votre produit ?")) # → support
print(classify_message("J'ai une erreur 500")) # → technique
print(classify_message("Quel est le prix ?")) # → vente
Traduction multilingue
translation_prompt = ChatPromptTemplate.from_template("""
Traduis le texte suivant de {source_lang} vers {target_lang}.
Garde le ton et le style du texte original.
Texte: {text}
Traduction:""")
def translate(text: str, source: str = "auto", target: str = "fr") -> str:
chain = translation_prompt | llm
response = chain.invoke({
"text": text,
"source_lang": source,
"target_lang": target
})
return response.content
# Utilisation
result = translate("Hello, how are you today?", source="en", target="fr")
print(result) # → "Bonjour, comment allez-vous aujourd'hui ?"
Génération de données synthétiques
from langchain.prompts import FewShotPromptTemplate
examples = [
{"input": "restaurant", "output": "Le Petit Bistrot, restaurant français cosy au cœur de Paris"},
{"input": "librairie", "output": "Pages & Cie, librairie indépendante spécialisée en littérature"},
]
example_prompt = ChatPromptTemplate.from_template(
"Type: {input}\nDescription: {output}"
)
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="Génère des descriptions réalistes pour des commerces:",
suffix="Type: {input}\nDescription:",
input_variables=["input"]
)
chain = few_shot_prompt | llm
# Génération
for business_type in ["café", "salon de coiffure", "boulangerie"]:
result = chain.invoke({"input": business_type})
print(f"{business_type}: {result.content}")
Résumé de documents longs
from langchain.chains.summarize import load_summarize_chain
from langchain.chains import MapReduceDocumentsChain
# Map-Reduce: résume chaque chunk puis combine
chain = load_summarize_chain(
llm,
chain_type="map_reduce",
verbose=True
)
summary = chain.run(documents)
print(summary)
# Ou refine: résume itérativement
chain = load_summarize_chain(llm, chain_type="refine")
summary = chain.run(documents)
Index rapide par cas d’usage
Trouvez rapidement la recette qu’il vous faut :
Débutant (premiers pas) :
- Recette #1 : Appel LLM simple
- Recette #2 : Prompt template dynamique
- Recette #5 : Fallback multi-LLM
Chatbots :
- Recette #6-10 : Mémoire, fenêtre de contexte, résumé auto, multilingue, personnalité
RAG (documents) :
- Recette #11-15 : PDF simple, multi-PDFs, Chroma persistant, filtres métadonnées, RAG conversationnel
Agents :
- Recette #16-20 : Recherche web, calculatrice, outils custom, RAG agent, SQL agent
Production :
- Recette #26 : LangSmith monitoring
- Recette #28 : API REST avec LangServe
- Recette #29 : Cache Redis
- Recette #30 : Retry avec Tenacity
Performance :
- Recette #31 : Batch processing
- Recette #32 : Async
- Recette #33 : Cache d’embeddings
- Recette #35 : Hybrid search
Problèmes courants :
- Recette #36 : Dépassement tokens
- Recette #37 : Rate limit
- Recette #38 : Documents non retrouvés
- Recette #39 : Agent en boucle
- Recette #40 : Hallucinations
Conclusion
Ce guide pratique vous a fourni 50+ recettes prêtes à l’emploi couvrant tous les aspects de LangChain :
✅ Configuration et setup de projet professionnel
✅ Chatbots avec mémoire et personnalités
✅ RAG sur PDFs, bases vectorielles, et recherche hybride
✅ Agents autonomes avec outils multiples
✅ Intégrations externes (APIs, Slack, Google Drive, Notion)
✅ Production avec monitoring, caching, et APIs REST
✅ Optimisations pour réduire coûts et latence
✅ Troubleshooting pour résoudre les problèmes courants
Conseils pour bien utiliser ce guide
📖 En tant que référence : Bookmarkez cette page et consultez-la quand vous avez besoin d’une fonctionnalité spécifique. Utilisez Ctrl+F pour rechercher des mots-clés.
🔧 En tant qu’outil : Copiez-collez les recettes directement dans vos projets et adaptez-les à vos besoins. Chaque recette est autonome et testée.
📚 Pour apprendre : Lisez les recettes de base (#1-5) puis explorez progressivement les sections avancées. Chaque recette inclut des commentaires explicatifs.
🚀 Pour la production : Concentrez-vous sur les sections Production (26-30) et Optimisations (31-35) pour des applications robustes et performantes.
Prochaines étapes
Pour approfondir chaque domaine :
- Débutants : Commencez par les recettes 1-10 (bases + chatbots)
- Intermédiaires : Explorez RAG (11-15) et agents simples (16-20)
- Avancés : Maîtrisez agents complexes, intégrations, et production (26-35)
- Production : Implémentez monitoring, caching, et optimisations (31-35)
Pour aller plus loin :
- Comprenez les concepts avec notre introduction à LangChain
- Maîtrisez le RAG avec LangChain en profondeur
- Créez des agents autonomes avec LangChain
- Découvrez les embeddings pour le RAG
- Explorez les vecteurs et la recherche sémantique
- Apprenez le RAG conceptuellement
- Comparez les frameworks open source
- Implémentez le fine-tuning pour personnaliser
- Assurez la sécurité et l’éthique
- Choisissez les bons modèles et acteurs
- Optimisez vos tokens pour réduire les coûts
- Comprenez l’architecture des Transformers
Navigation
← Retour à la Formation LangChain | Module suivant : LangGraph - Agents Avancés →