NOUVEAU - Intelligence Artificielle

Chatbot Entreprise avec RAG et LangChain

Construisez un chatbot d'entreprise intelligent avec Retrieval-Augmented Generation et LangChain : de l'ingestion documentaire au déploiement en production

Ayi NEDJIMI 13 février 2026 26 min de lecture Niveau Intermédiaire

Table des Matières

1 Introduction : Le Chatbot d'Entreprise Nouvelle Génération

Les chatbots d'entreprise ont longtemps été synonymes de frustration : réponses génériques, incapacité à comprendre le contexte métier, et hallucinations fréquentes lorsqu'ils reposent uniquement sur des LLM (Large Language Models) pré-entraînés. En 2026, l'architecture RAG (Retrieval-Augmented Generation) combinée au framework LangChain transforme radicalement cette réalité en permettant de construire des assistants conversationnels qui s'appuient sur vos propres données d'entreprise.

Les limites des chatbots classiques

Les chatbots traditionnels souffrent de limitations structurelles qui les rendent inadaptés aux besoins complexes de l'entreprise :

La promesse du RAG

Le RAG (Retrieval-Augmented Generation) résout ces problèmes en séparant la connaissance du raisonnement. Au lieu de stocker toute l'information dans les poids du modèle, le RAG va chercher les informations pertinentes dans votre base documentaire au moment de la requête, puis les injecte comme contexte pour le LLM. C'est exactement ce que fait un expert humain : il consulte la documentation avant de répondre.

Cas d'usage concrets en entreprise :

  • Chatbot RH — Répond aux questions sur la convention collective, les congés, la mutuelle, les procédures internes. Source : documents RH, intranet, accords d'entreprise.
  • Assistant documentation technique — Interroge la base de connaissances technique, les manuels produit, les wikis Confluence. Idéal pour l'onboarding développeurs.
  • Support client niveau 1 — Exploite la FAQ, les tickets résolus, la documentation produit pour fournir des réponses précises et sourcées.

Dans ce guide, nous allons construire pas à pas un chatbot d'entreprise complet avec LangChain 0.3+, depuis l'ingestion de vos documents jusqu'au déploiement en production. Chaque étape sera accompagnée de code Python fonctionnel et de recommandations basées sur des retours d'expérience en production.

2 Architecture RAG pour Chatbot

L'architecture RAG pour un chatbot d'entreprise se décompose en deux pipelines fondamentaux : le pipeline d'ingestion (hors ligne) et le pipeline de requête (en temps réel). Comprendre cette séparation est essentiel pour concevoir un système performant et maintenable.

Pipeline d'ingestion (Indexing)

Le pipeline d'ingestion transforme vos documents bruts en représentations vectorielles interrogeables. Il s'exécute en amont, de manière asynchrone, et se compose des étapes suivantes :

Pipeline de requête (Retrieval + Generation)

Lorsqu'un utilisateur pose une question, le pipeline de requête s'active en temps réel :

Point clé : Le même modèle d'embeddings doit être utilisé à l'ingestion et à la requête. Un décalage (mismatch) entre les modèles dégrade drastiquement la qualité du retrieval. Documentez toujours le modèle utilisé dans vos métadonnées de collection.

3 Ingestion et Préparation des Documents

La qualité de votre chatbot RAG dépend directement de la qualité de l'ingestion documentaire. Cette étape, souvent sous-estimée, représente 80% de l'effort de développement d'un chatbot d'entreprise robuste. LangChain 0.3+ fournit un écosystème complet de loaders et de text splitters pour couvrir la plupart des scénarios.

Document Loaders

LangChain propose plus de 160 loaders pour charger des documents depuis pratiquement n'importe quelle source. Voici les plus utilisés en contexte entreprise :

Voici l'implémentation d'un pipeline d'ingestion multi-sources avec LangChain :

from langchain_community.document_loaders import (
    PyMuPDFLoader,
    Docx2txtLoader,
    ConfluenceLoader,
    NotionDBLoader,
    DirectoryLoader
)
from langchain.schema import Document
from pathlib import Path
import logging

logger = logging.getLogger(__name__)

class EnterpriseDocumentLoader:
    """Pipeline d'ingestion multi-sources pour chatbot entreprise."""

    def __init__(self, config: dict):
        self.config = config
        self.documents: list[Document] = []

    def load_pdfs(self, directory: str) -> list[Document]:
        """Charge tous les PDF d'un répertoire."""
        loader = DirectoryLoader(
            directory,
            glob="**/*.pdf",
            loader_cls=PyMuPDFLoader,
            show_progress=True,
            use_multithreading=True
        )
        docs = loader.load()
        logger.info(f"Chargé {len(docs)} pages PDF depuis {directory}")
        return self._enrich_metadata(docs, source_type="pdf")

    def load_confluence(self, space_key: str) -> list[Document]:
        """Charge les pages Confluence d'un espace."""
        loader = ConfluenceLoader(
            url=self.config["confluence_url"],
            username=self.config["confluence_user"],
            api_key=self.config["confluence_token"],
            space_key=space_key,
            include_attachments=True,
            limit=100
        )
        docs = loader.load()
        logger.info(f"Chargé {len(docs)} pages Confluence ({space_key})")
        return self._enrich_metadata(docs, source_type="confluence")

    def _enrich_metadata(self, docs, source_type: str):
        """Enrichit les métadonnées pour le filtrage et la traçabilité."""
        for doc in docs:
            doc.metadata["source_type"] = source_type
            doc.metadata["ingested_at"] = datetime.now().isoformat()
            doc.metadata["company"] = self.config.get("company_name", "default")
        return docs

Stratégies de Chunking

Le chunking est l'art de découper vos documents en fragments optimaux pour le retrieval. Un chunk trop petit perd le contexte, un chunk trop grand noie l'information pertinente dans du bruit. LangChain propose plusieurs stratégies :

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings

# Stratégie 1 : RecursiveCharacter (recommandé pour commencer)
recursive_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,          # Taille cible en caractères
    chunk_overlap=200,        # Chevauchement pour le contexte
    length_function=len,
    separators=["\n\n", "\n", ". ", " ", ""],
    is_separator_regex=False
)
chunks = recursive_splitter.split_documents(documents)

# Stratégie 2 : SemanticChunker (pour du contenu varié)
semantic_splitter = SemanticChunker(
    embeddings=OpenAIEmbeddings(model="text-embedding-3-small"),
    breakpoint_threshold_type="percentile",
    breakpoint_threshold_amount=95  # Seuil de similarité pour couper
)
semantic_chunks = semantic_splitter.split_documents(documents)

print(f"Recursive: {len(chunks)} chunks | Semantic: {len(semantic_chunks)} chunks")

Règle empirique pour le chunk_size : Commencez avec 1000 caractères et 200 d'overlap. Pour des documents très structurés (manuels techniques), montez à 1500. Pour du Q&A court (FAQ), descendez à 500. Toujours mesurer la qualité avec un jeu de test avant de changer.

4 Embeddings et Vector Stores

Les embeddings transforment le texte en vecteurs numériques denses dans un espace mathématique où la proximité reflète la similarité sémantique. Le choix du modèle d'embeddings et de la base vectorielle a un impact direct sur la pertinence des réponses de votre chatbot.

Modèles d'Embeddings

En 2026, plusieurs modèles d'embeddings se distinguent pour les applications d'entreprise :

Bases Vectorielles

Le choix de la base vectorielle dépend de vos contraintes de volume, performance, et infrastructure :

Voici l'intégration complète embeddings + vector store avec LangChain :

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma, Qdrant, Milvus
from langchain.schema import Document

# Initialisation du modèle d'embeddings
embeddings = OpenAIEmbeddings(
    model="text-embedding-3-large",
    dimensions=1024  # Dimension shortening pour économiser
)

# Option 1 : ChromaDB (développement / prototypage)
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db",
    collection_name="chatbot_rh"
)

# Option 2 : Qdrant (production)
from qdrant_client import QdrantClient
vectorstore = Qdrant.from_documents(
    documents=chunks,
    embedding=embeddings,
    url="http://localhost:6333",
    collection_name="chatbot_rh",
    force_recreate=False
)

# Retriever avec paramètres optimisés
retriever = vectorstore.as_retriever(
    search_type="similarity",      # ou "mmr" pour diversifier
    search_kwargs={
        "k": 5,                       # Nombre de chunks à récupérer
        "score_threshold": 0.7       # Seuil de pertinence minimum
    }
)

5 Construction avec LangChain

LangChain 0.3+ introduit le LCEL (LangChain Expression Language) qui remplace l'ancienne API des Chains. Le LCEL offre une syntaxe déclarative avec le pipe operator (|) pour composer des pipelines RAG de manière élégante et maintenable.

Prompt Template RAG

Le prompt template est le coeur de votre chatbot RAG. Il doit instruire le LLM à répondre uniquement à partir du contexte fourni, en citant ses sources, et en avouant son ignorance quand l'information n'est pas disponible :

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

RAG_PROMPT = ChatPromptTemplate.from_messages([
    ("system", """Tu es un assistant d'entreprise spécialisé et précis.
Tu réponds UNIQUEMENT à partir du contexte fourni ci-dessous.
Si l'information n'est pas dans le contexte, dis-le clairement.
Cite toujours la source de tes informations entre crochets [source].
Réponds en français de manière professionnelle et concise.

Contexte:
{context}

Règles:
- Ne fabrique JAMAIS d'information
- Si plusieurs sources se contredisent, mentionne-le
- Propose de contacter le service concerné si la question dépasse le contexte"""),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{question}")
])

Chaîne RAG Complète avec LCEL

Voici l'implémentation complète d'un chatbot RAG conversationnel avec mémoire, utilisant le LCEL de LangChain 0.3+ :

from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

# Initialisation du LLM
llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0.1,        # Bas pour des réponses factuelles
    max_tokens=1500,
    streaming=True          # Pour la réponse en streaming
)

# Fonction de formatage du contexte
def format_docs(docs):
    formatted = []
    for i, doc in enumerate(docs, 1):
        source = doc.metadata.get('source', 'Inconnu')
        page = doc.metadata.get('page', '')
        ref = f"{source}" + (f" p.{page}" if page else "")
        formatted.append(f"[Source {i}: {ref}]\n{doc.page_content}")
    return "\n\n---\n\n".join(formatted)

# Chaîne RAG avec LCEL
rag_chain = (
    RunnableParallel(
        context=retriever | format_docs,
        question=RunnablePassthrough(),
        chat_history=lambda x: x.get("chat_history", [])
    )
    | RAG_PROMPT
    | llm
    | StrOutputParser()
)

# Ajout de la mémoire conversationnelle
message_histories = {}

def get_session_history(session_id: str):
    if session_id not in message_histories:
        message_histories[session_id] = ChatMessageHistory()
    return message_histories[session_id]

chatbot = RunnableWithMessageHistory(
    rag_chain,
    get_session_history,
    input_messages_key="question",
    history_messages_key="chat_history"
)

# Utilisation
response = chatbot.invoke(
    {"question": "Combien de jours de congés ai-je droit ?"},
    config={"configurable": {"session_id": "user_001"}}
)
print(response)

Gestion de la Mémoire Conversationnelle

La mémoire est essentielle pour un chatbot d'entreprise : elle permet les questions de suivi ("Et pour les RTT ?"), les clarifications, et maintient le contexte de la conversation. LangChain propose plusieurs stratégies :

Astuce production : Pour les chatbots à fort trafic, utilisez Redis comme backend de mémoire (RedisChatMessageHistory) au lieu du stockage en mémoire. Cela permet la persistance entre les redémarrages et le partage entre instances.

6 Optimisation et Qualité

Un chatbot RAG fonctionnel n'est que le début. Pour atteindre un niveau de qualité production, il faut optimiser le retrieval, implémenter le reranking, et mettre en place une évaluation continue. Cette section couvre les techniques avancées qui font la différence entre un prototype et un outil métier fiable.

Reranking : la clé de la pertinence

La recherche vectorielle initiale (bi-encoder) est rapide mais approximative. Le reranking utilise un cross-encoder plus puissant pour ré-ordonner les résultats et éliminer les faux positifs. C'est l'optimisation avec le meilleur retour sur investissement :

from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder

# Option 1 : Cohere Rerank (cloud, très performant)
cohere_reranker = CohereRerank(
    model="rerank-v3.5",
    top_n=3   # Garder les 3 meilleurs après reranking
)

# Option 2 : Cross-encoder local (self-hosted, gratuit)
cross_encoder = HuggingFaceCrossEncoder(
    model_name="cross-encoder/ms-marco-MiniLM-L-12-v2"
)
local_reranker = CrossEncoderReranker(
    model=cross_encoder, top_n=3
)

# Retriever avec reranking intégré
compression_retriever = ContextualCompressionRetriever(
    base_compressor=cohere_reranker,
    base_retriever=vectorstore.as_retriever(search_kwargs={"k": 20})
    # Récupère 20 docs, rerank garde les 3 meilleurs
)

Hybrid Search : le meilleur des deux mondes

La recherche hybride combine la recherche sémantique (dense vectors) avec la recherche lexicale (BM25/sparse). Cela couvre les cas où la recherche sémantique seule échoue, notamment pour les termes techniques spécifiques, les numéros de référence, ou les acronymes métier :

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# Retriever dense (sémantique)
dense_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})

# Retriever sparse (BM25 lexical)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 10

# Ensemble : fusion avec pondération
hybrid_retriever = EnsembleRetriever(
    retrievers=[dense_retriever, bm25_retriever],
    weights=[0.6, 0.4]  # 60% sémantique, 40% lexical
)

Évaluation avec RAGAS

L'évaluation d'un chatbot RAG nécessite des métriques spécifiques. Le framework RAGAS (Retrieval Augmented Generation Assessment) est devenu le standard en 2026 pour mesurer la qualité d'un pipeline RAG :

from ragas import evaluate
from ragas.metrics import (
    faithfulness, answer_relevancy,
    context_precision, context_recall
)
from datasets import Dataset

# Préparer le jeu de test
eval_data = {
    "question": [
        "Combien de jours de congés annuels ?",
        "Quelle est la procédure de télétravail ?",
        "Comment déclarer un accident de travail ?"
    ],
    "answer": [resp1, resp2, resp3],  # Réponses du chatbot
    "contexts": [ctx1, ctx2, ctx3],   # Chunks récupérés
    "ground_truth": [gt1, gt2, gt3]   # Réponses de référence
}

result = evaluate(
    Dataset.from_dict(eval_data),
    metrics=[faithfulness, answer_relevancy,
             context_precision, context_recall]
)
print(result)  # {'faithfulness': 0.92, 'answer_relevancy': 0.87, ...}

Recommandation : Constituez un jeu de test de 50-100 questions/réponses couvrant vos cas d'usage principaux. Faites-le valider par les experts métier. Exécutez l'évaluation RAGAS après chaque modification du pipeline (changement de chunk_size, nouveau modèle, ajout de documents).

7 Déploiement et Production

Le passage en production d'un chatbot RAG d'entreprise exige une attention particulière à la performance, la sécurité, le monitoring et la gestion des coûts. Voici un guide complet pour déployer et opérer votre chatbot de manière fiable et pérenne.

API avec FastAPI et LangServe

LangServe transforme votre chaîne LangChain en API REST production-ready avec documentation OpenAPI automatique, support du streaming, et playground intégré :

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from langserve import add_routes
from pydantic import BaseModel
import uvicorn

app = FastAPI(
    title="Chatbot RH - API RAG",
    version="1.0.0",
    description="API chatbot d'entreprise avec RAG et LangChain"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://intranet.entreprise.fr"],
    allow_methods=["POST"],
    allow_headers=["*"],
)

# Expose la chaîne RAG via LangServe
add_routes(
    app,
    chatbot,  # La chaîne RunnableWithMessageHistory
    path="/chat",
    enable_feedback_endpoint=True,
    enable_public_trace_link_endpoint=False
)

# Endpoint de santé
@app.get("/health")
async def health_check():
    return {"status": "healthy", "vector_count": vectorstore._collection.count()}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Monitoring et Observabilité

En production, vous devez surveiller chaque étape du pipeline RAG pour détecter les dégradations et optimiser en continu. Les outils de monitoring essentiels :

Sécurité et Conformité

La sécurité d'un chatbot d'entreprise est primordiale, surtout lorsqu'il accède à des données sensibles (RH, juridique, financier). Mesures essentielles à implémenter :

Gestion des Coûts

Les coûts d'un chatbot RAG se répartissent entre embeddings, LLM, infrastructure et monitoring. Voici une estimation typique pour un chatbot RH servant 500 utilisateurs/jour :

Maintenance de la Base Documentaire

Un chatbot RAG n'est utile que si sa base documentaire est à jour. Mettez en place un pipeline de mise à jour continue :

Checklist de déploiement production : Authentification SSO, rate limiting (10 req/min/user), circuit breaker sur l'API LLM, fallback gracieux ("Je ne peux pas répondre, contactez le service RH"), sauvegarde quotidienne du vector store, alertes sur latence P95 > 5s, revue mensuelle des métriques RAGAS, mise à jour documentaire hebdomadaire.

Ayi NEDJIMI - Expert Cybersécurité & IA

À Propos de l'Auteur

Ayi NEDJIMI • Expert Cybersécurité & IA

Ayi NEDJIMI est un expert senior en cybersécurité offensive et intelligence artificielle avec plus de 20 ans d'expérience en développement avancé, tests d'intrusion et architecture de systèmes critiques. Spécialisé en rétro-ingénierie logicielle, forensics numériques et développement de modèles IA, il accompagne les organisations stratégiques dans la sécurisation d'infrastructures hautement sensibles.

Expert reconnu en expertises judiciaires et investigations forensiques, Ayi intervient régulièrement en tant que consultant expert auprès des plus grandes organisations françaises et européennes. Son expertise technique couvre l'audit Active Directory, le pentest cloud (AWS, Azure, GCP), la rétro-ingénierie de malwares, ainsi que l'implémentation de solutions RAG et bases vectorielles (Milvus, Qdrant, Weaviate) pour des applications IA d'entreprise.

20+Ans d'expérience
100+Missions réalisées
150+Articles & conférences

Conférencier et formateur reconnu en cybersécurité, Ayi anime régulièrement des conférences techniques et participe activement au développement de modèles d'intelligence artificielle pour la détection de menaces avancées. Auteur de plus de 150 publications techniques, il partage son expertise de haut niveau pour aider les RSSI et architectes sécurité à anticiper les cybermenaces émergentes et déployer des solutions IA de nouvelle génération.

Options de lecture

Taille du texte
Espacement
Mode de lecture
Partager