Aller au contenu principal

Frameworks RAG : LangChain, LlamaIndex, Haystack

Au-delà du RAG from scratch

Dans les leçons précédentes, vous avez construit un pipeline RAG complet en Python pur. En production, vous pouvez aussi utiliser des frameworks spécialisés qui simplifient l’implémentation et ajoutent des fonctionnalités avancées. Les trois principaux sont LangChain, LlamaIndex et Haystack, tous compatibles avec Mistral AI.

LangChain avec Mistral

LangChain est le framework le plus populaire pour les applications LLM. Il offre un écosystème riche d’intégrations et le module LangGraph pour les control flows avancés.

Installation

pip install langchain langchain-mistralai langchain-community faiss-cpu

RAG simple avec LangChain

from langchain_mistralai import ChatMistralAI, MistralAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# Modèles Mistral
embeddings = MistralAIEmbeddings(model="mistral-embed")
llm = ChatMistralAI(model="mistral-large-latest", temperature=0.1)

# Découpage et indexation
splitter = RecursiveCharacterTextSplitter(
    chunk_size=1500,
    chunk_overlap=200,
)
chunks = splitter.split_text(document_text)

# Créer le vector store
vectorstore = FAISS.from_texts(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# Chaîne RAG
prompt = ChatPromptTemplate.from_template(
    """Contexte : {context}

Question : {question}

Repondez en vous basant sur le contexte."""
)

rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# Utilisation
answer = rag_chain.invoke("Comment fonctionne FAISS ?")
print(answer)

LangGraph pour le Corrective/Self/Adaptive RAG

LangGraph permet de définir des control flows sous forme de graphes :

from langgraph.graph import StateGraph, END
from typing import TypedDict

class GraphState(TypedDict):
    question: str
    documents: list
    generation: str
    web_search_needed: bool

def retrieve_node(state):
    """Noeud de retrieval."""
    question = state["question"]
    docs = retriever.get_relevant_documents(question)
    return {"documents": docs, "question": question}

def grade_node(state):
    """Noeud de grading des documents."""
    question = state["question"]
    docs = state["documents"]
    relevant = []
    web_needed = False

    for doc in docs:
        # Utiliser le LLM pour évaluer la pertinence
        grade = grade_document(question, doc.page_content)
        if grade:
            relevant.append(doc)
        else:
            web_needed = True

    return {"documents": relevant, "web_search_needed": web_needed}

def generate_node(state):
    """Noeud de génération."""
    question = state["question"]
    docs = state["documents"]
    context = "\n\n".join([d.page_content for d in docs])
    generation = llm.invoke(f"Contexte: {context}\n\nQuestion: {question}")
    return {"generation": generation.content}

def route_after_grade(state):
    """Décision conditionnelle après le grading."""
    if state["web_search_needed"]:
        return "web_search"
    return "generate"

# Construire le graphe
workflow = StateGraph(GraphState)

# Ajouter les noeuds
workflow.add_node("retrieve", retrieve_node)
workflow.add_node("grade", grade_node)
workflow.add_node("generate", generate_node)

# Définir le flux
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "grade")
workflow.add_conditional_edges("grade", route_after_grade, {
    "generate": "generate",
    "web_search": "web_search",
})
workflow.add_edge("generate", END)

# Compiler
app = workflow.compile()

# Exécuter
result = app.invoke({"question": "Comment fonctionne le RAG ?"})
print(result["generation"])

LlamaIndex avec Mistral

LlamaIndex est optimisé spécifiquement pour le RAG et la gestion de documents structurés.

pip install llama-index llama-index-llms-mistralai llama-index-embeddings-mistralai
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.mistralai import MistralAI
from llama_index.embeddings.mistralai import MistralAIEmbedding
from llama_index.core import Settings

# Configuration globale
Settings.llm = MistralAI(model="mistral-large-latest", temperature=0.1)
Settings.embed_model = MistralAIEmbedding(model_name="mistral-embed")

# Charger les documents
documents = SimpleDirectoryReader("./data/").load_data()

# Créer l'index (chunking + embedding automatiques)
index = VectorStoreIndex.from_documents(documents)

# Créer le moteur de requêtes
query_engine = index.as_query_engine(similarity_top_k=3)

# Poser une question
response = query_engine.query("Quelles sont les étapes du RAG ?")
print(response)
print(f"\nSources: {[n.metadata for n in response.source_nodes]}")

Haystack avec Mistral

Haystack (deepset) adopte une approche par pipelines modulaires.

pip install haystack-ai mistral-haystack
from haystack import Pipeline
from haystack.components.writers import DocumentWriter
from haystack.components.preprocessors import DocumentSplitter
from haystack_integrations.components.embedders.mistral import (
    MistralDocumentEmbedder,
    MistralTextEmbedder,
)
from haystack_integrations.components.generators.mistral import MistralChatGenerator
from haystack.document_stores.in_memory import InMemoryDocumentStore

# Document store
doc_store = InMemoryDocumentStore()

# Pipeline d'indexation
indexing_pipeline = Pipeline()
indexing_pipeline.add_component("splitter", DocumentSplitter(
    split_by="passage", split_length=5
))
indexing_pipeline.add_component("embedder", MistralDocumentEmbedder(
    model="mistral-embed"
))
indexing_pipeline.add_component("writer", DocumentWriter(
    document_store=doc_store
))

indexing_pipeline.connect("splitter", "embedder")
indexing_pipeline.connect("embedder", "writer")

Comparaison des frameworks

Chaque framework a ses forces :

  • LangChain : écosystème le plus riche, LangGraph pour les control flows complexes, idéal pour les agents et le RAG avancé
  • LlamaIndex : le plus simple pour le RAG, gestion native des documents structurés, excellent pour les débutants
  • Haystack : approche pipeline modulaire, bon pour la production, fort en évaluation

Prochaines étapes

Vous avez maintenant toutes les bases pour construire des systèmes RAG avec Mistral AI :

  1. Embeddings texte avec mistral-embed (1024 dimensions)
  2. Embeddings code avec codestral-embed (jusqu’à 3072 dimensions)
  3. RAG from scratch avec FAISS et l’API Mistral
  4. RAG avancé : Corrective, Self et Adaptive RAG
  5. Frameworks : LangChain, LlamaIndex, Haystack

Pour aller plus loin, explorez les cookbooks officiels de Mistral AI et les notebooks de chaque framework. Le RAG est un domaine en évolution rapide : les techniques de chunking, de retrieval et de vérification s’améliorent constamment.

Points clés à retenir

  • LangChain + LangGraph est le choix principal pour les control flows RAG avancés
  • LlamaIndex est le plus simple pour un RAG standard avec Mistral
  • Haystack excelle en modularité et évaluation de pipelines
  • Les trois frameworks supportent nativement mistral-embed et mistral-large
  • Commencez par le RAG from scratch pour comprendre, puis migrez vers un framework pour la production