Recherche de site Web

Un guide pratique du RAG avec Haystack et LangChain


Introduction

La génération augmentée par récupération (RAG) est une architecture d'IA qui combine la recherche d'information classique avec les grands modèles de langage génératif (LLM) dans un même pipeline. Plutôt que de se fier entièrement aux connaissances statiques préalablement entraînées dans un LLM (qui peuvent être incomplètes, obsolètes, ou les deux), le RAG enrichit dynamiquement le processus de génération en injectant des informations récupérées à partir de sources externes. Le résultat est une génération plus précise et contextuellement pertinente qui tire parti du meilleur de la technologie de récupération et de génération.

L'idée derrière un pipeline RAG est conceptuellement simple. Cependant, créer un pipeline RAG prêt pour la production peut être complexe. Il y a de nombreuses décisions relatives aux outils et des compromis de conception qui doivent être pris en compte. Cela inclut le choix d'un framework (Haystack vs. LangChain), la sélection et l'optimisation de la base de données vectorielle, les stratégies de découpage des documents, les exigences en matière d'ingénierie et les stratégies de déploiement.

L'objectif de ce guide est d'expliquer, d'un point de vue technique, comment construire des pipelines RAG prêts pour la production.

Points clés

  • Les pipelines RAG augmentent les réponses des LLM avec des informations récupérées en temps réel pour des réponses plus précises.
  • Haystack offre des pipelines modulaires prêts pour la production, et LangChain excelle dans le prototypage, le MLOps et les intégrations avec d'autres outils.
  • Le choix de la bonne base de données vectorielle (FAISS, ChromaDB, Pinecone, et d'autres) détermine l'évolutivité, la vitesse et les fonctionnalités de votre système.
  • Le modèle d'intégration et la stratégie de découpage influencent la qualité de la récupération et la qualité de la réponse finale.
  • La mise en œuvre d'un pipeline RAG dans des environnements de production nécessite des approches spécialisées, une évaluation, une surveillance, des retours d'utilisateurs et les meilleures stratégies de déploiement.

Comprendre l'architecture RAG

Un pipeline RAG comporte généralement divers composants qui interagissent les uns avec les autres. Les éléments constitutifs les plus essentiels sont les suivants :

  • Ingestion et prétraitement des données : Les sources de connaissances brutes sous diverses formes, telles que des documents, des pages web et des PDF, sont chargées dans le système et prétraitées (conversion en un format standard, extraction de contenu, normalisation, etc.), ainsi que diverses techniques de prétraitement de texte.
  • Segmentation : Chaque document est divisé en plus petits blocs sémantiquement significatifs. L'étape de segmentation est essentielle pour un accès efficace, car elle détermine la granularité à laquelle les informations sont indexées et récupérées à partir de la base de données.
  • Génération d'Embedding : Chaque segment est intégré dans un vecteur de haute dimension à l'aide d'un modèle de langage ajusté pour l'embedding.
  • Base de données vectorielle : La base de données vectorielle (ou index) stocke tous les embeddings des segments tout en prenant en charge la recherche par similarité.
  • Moteur de Récupération : Lorsqu'une requête utilisateur est reçue, elle est d'abord convertie en vecteur, et le composant de récupération extrait les k embeddings (morceaux) les plus similaires dans la base de données vectorielle.
  • Pipeline de génération : Un LLM (composant génératif) reçoit enfin la requête de l’utilisateur ainsi que les morceaux de contexte récupérés pour générer une réponse bien informée.

Les composants circulent de manière linéaire dans le pipeline, et les systèmes de production peuvent également introduire des branches, des boucles ou d'autres étapes supplémentaires (par exemple, le reclassement des résultats récupérés avant de les transmettre au LLM). L'objectif est que tous les composants travaillent ensemble et transforment les données brutes en une réponse précise, pertinente contextuellement et à jour.

Comparaison des cadres : Haystack vs. LangChain

Pour ceux qui intègrent le RAG dans des applications de production, les frameworks de haut niveau sont souvent préférés. La principale caractéristique et avantage de ces frameworks est qu'ils fournissent des composants et des abstractions préconstruits pour créer des pipelines efficaces. Haystack (par Deepset) et LangChain sont de loin les outils les plus populaires et connus dans cette catégorie. Les deux visent le même cas d'utilisation général - la facilité de création d'applications autour des LLM. Cependant, ils ont des principes de conception sous-jacents différents et des forces relatives distinctes.

Haystack : Architecture centrée sur le pipeline

Haystack (par Deepset) est un framework open-source axé sur le RAG et autres cas d'utilisation pour les LLM. La caractéristique centrale de Haystack, mise davantage en avant dans la version la plus récente, est son architecture modulaire centrée sur les pipelines. Haystack adopte une approche de type graphe, où chaque composant (lecteur, récupérateur, générateur, etc.) représente un nœud dans un pipeline en graphe acyclique dirigé (DAG). Les pipelines Haystack sont composables et personnalisables - les nœuds peuvent être ajoutés, supprimés et remplacés avec un minimum d'effets secondaires sur les autres composants. Ci-dessous se trouve un tableau résumant certains des principaux avantages de Haystack :

Avantage cléDescription
Conception de pipeline modulaireLa modularité de la conception du pipeline dans Haystack, avec des connexions de composants clairement définies, permet un échange simple des composants (par exemple, remplacer BM25 par un récupérateur à vecteurs denses) ou l'intégration de modules supplémentaires (comme les re-rankers) sans réécrire l'ensemble de l'application, ce qui aboutit à une architecture plus propre et plus modulaire, plus facile à déboguer.
Fonctionnalités prêtes pour la productionHaystack offre un support intégré pour l'évaluation, la surveillance et l'évolutivité. Il est également fourni avec des cadres d'évaluation dédiés (tels que RAGAS et DeepEval) pour le benchmarking de la récupération et de la génération (intégrés dans Haystack 2.0)
Documentation SupérieureHaystack fournit une documentation et des exemples complets et faciles à suivre, souvent considérés comme plus clairs que ceux de LangChain. Cela améliore la vitesse de développement et réduit le temps de dépannage, en particulier pour les équipes en phase de production.
Optimisé RAGConçu pour la réponse aux questions basée sur la récupération, Haystack propose un support et des utilitaires prêts à l'emploi pour les astuces populaires et les nouvelles techniques telles que HyDE et l'expansion de requête. Les pipelines multi-sauts, les agents et d'autres schémas de récupération complexes sont pris en charge dans Haystack 2.0.

Exemple technique (pipeline Haystack)

En utilisant du pseudocode (inspiré par la syntaxe de Haystack 2.0), un pipeline RAG simple pourrait être construit comme suit :

# Step 1: Install required packages
#pip install haystack-ai openai python-dotenv

# Step 2: Load environment variables
import os
from dotenv import load_dotenv

load_dotenv()  # Loads variables from a .env file if present

# OPTIONAL: Set the API key directly if not using .env
# os.environ["OPENAI_API_KEY"] = "your-openai-api-key"

# Step 3: Haystack imports
from haystack import Document
from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever

# Step 4: Create the DocumentStore
doc_store = InMemoryDocumentStore()

# Step 5: Add raw documents
documents = [
    Document(content="The Eiffel Tower is located in Paris, France."),
    Document(content="Haystack is a framework for building NLP applications."),
    Document(content="LangChain is often used to build LLM-based agents."),
    Document(content="RAG stands for Retrieval-Augmented Generation.")
]
doc_store.write_documents(documents)

# Step 6: Embed and store document embeddings
embedder = OpenAITextEmbedder(model="text-embedding-ada-002")
for doc in doc_store.filter_documents():
    embedding = embedder.run({"text": doc.content})["embedding"]
    doc.embedding = embedding
doc_store.update_documents(documents)

# Step 7: Build the pipeline
pipeline = Pipeline()

# Add components with API key if needed (optional)
pipeline.add_component("embedder", OpenAITextEmbedder(model="text-embedding-ada-002"))
pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store=doc_store))
pipeline.add_component("generator", OpenAIGenerator(model="gpt-3.5-turbo"))

# Connect the components
pipeline.connect("embedder.embedding", "retriever.query_embedding")
pipeline.connect("retriever.documents", "generator.documents")

# Step 8: Run the pipeline with a query
query = "What is RAG in NLP?"
result = pipeline.run({"embedder": {"text": query}})

# Step 9: Print the answer
print("\n Answer:", result["generator"]["replies"][0])

Dans ce code, Haystack connecte un composant d'embedding à un récupérateur dense puis à un générateur. Vous devez vous assurer que OPENAI_API_KEY est défini soit via .env, soit par affectation directe dans le code.

LangChain : Cadre Basé sur des Chaînes

LangChain est un autre framework open-source qui a gagné en popularité pour prototyper rapidement des applications LLM. Il a une philosophie légèrement différente. Au lieu de déclarer un graphe de pipeline statique, on enchaîne souvent les composants dans le code (ou avec des abstractions de niveau supérieur comme « Chains » ou « Agents »).
LangChain est connu pour ses intégrations étendues, sa flexibilité et son support pour les fournisseurs de LLM, les magasins de vecteurs et les outils (comme un navigateur web ou une calculatrice) intégrés via un mécanisme d’agent. Le tableau suivant présente certains des principaux avantages de l’utilisation de LangChain :

Avantage cléDescription
Intégrations étenduesLangChain est compatible avec une large gamme de modèles (OpenAI, Anthropic, HuggingFace), de bases de données vectorielles (Pinecone, Weaviate, FAISS, Chroma) et d'API. Les développeurs peuvent mélanger et assortir les composants facilement en utilisant des modules plug-and-play.
Cadre d'AgentEn utilisant LangChain, nous pouvons créer des agents alimentés par des LLM qui peuvent choisir dynamiquement quels outils utiliser (recherche sur le web, calculatrice, API et plus encore). Parfait pour les flux de travail qui nécessitent une logique complexe en plusieurs étapes et l'orchestration d'outils.
Prototypage rapideExpérience de développement conviviale avec des abstractions de haut niveau qui gèrent les cas d'utilisation courants (QA par récupération, chaînes de mémoire, etc.). Créez des preuves de concept et des démonstrations avec seulement quelques lignes de code.
Communauté et ÉcosystèmeGrande communauté active d'utilisateurs avec de nombreux tutoriels, plugins et intégrations tierces. Même pour les outils qui ne sont pas officiellement pris en charge, il y a probablement une solution apportée par la communauté.

Exemple technique (Chaîne RAG LangChain)

LangChain représente souvent RAG comme une chaîne RetrievalQA. Par exemple :

# Step 1: Install required packages (run this once)
# pip install -qU langchain_community faiss-cpu openai python-dotenv

# Step 2: Imports
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
from langchain.schema import Document
import os
from dotenv import load_dotenv

# Step 3: Load environment variables (e.g. OpenAI key)
load_dotenv()
# Optionally, you can set manually
# os.environ["OPENAI_API_KEY"] = "your-openai-api-key"

# Step 4: Prepare your documents
raw_documents = [
    "The Eiffel Tower is located in Paris, France.",
    "Haystack is a framework for building NLP applications.",
    "LangChain is often used to build LLM-based agents.",
    "RAG stands for Retrieval-Augmented Generation."
]

# Step 5: Split documents into chunks
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=100
)
chunks = text_splitter.create_documents(raw_documents)

# Step 6: Initialize embeddings
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

# Step 7: Create vector store (FAISS is in-memory and fast)
vectorstore = FAISS.from_documents(chunks, embedding=embeddings)

# Step 8: Initialize RetrievalQA pipeline
qa_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(model_name="gpt-3.5-turbo"),  # default temperature is 0.7
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
    chain_type="stuff",  # stuff = concatenate retrieved docs into prompt
    return_source_documents=True  # useful for debugging and transparency
)

# Step 9: Run a query
query = "What is RAG in NLP?"
result = qa_chain(query)

# Step 10: Print result
print("\n Answer:\n", result["result"])

# Optional: Show retrieved docs
print("\n Retrieved Documents:")
for doc in result["source_documents"]:
    print("-", doc.page_content)

Cet extrait de code crée un index vectoriel FAISS en mémoire des textes de tous les documents. Il appelle ensuite la chaîne RetrievalQA de LangChain, qui intègre en interne la requête, recherche dans le magasin vectoriel et construit une invite pour le LLM avec les résultats. chain_type=“stuff” concatène les documents récupérés (« les bourrer ») dans l’invite du LLM avec la question. D’autres types de chaînes sont disponibles dans LangChain, comme « map-reduce » (résumant chaque document, puis les agrégeant) ou « refine » (construisant une réponse de manière itérative), pour gérer des contextes plus complexes et plus volumineux.

Quand choisir lequel ?

Nous recommanderons Haystack si votre objectif est un système maintenable, évaluable et prêt pour la production, et si vous suivez en grande partie un modèle de FAQ par récupération ou un modèle similaire. Si vous essayez de prototyper quelque chose rapidement ou avez besoin de comportements/intégrations complexes d'agents, LangChain peut vous aider à y parvenir plus rapidement. Certaines équipes utilisent Haystack pour le pipeline principal et ajoutent des agents LangChain lorsque nécessaire, donc ces solutions ne sont pas non plus exclusives.

Sélection et optimisation de bases de données vectorielles

La base de données vectorielle est un composant fondamental de tout pipeline RAG. Elle stocke les embeddings de vos documents et effectue une recherche de similarité. Le magasin vectoriel que vous choisissez impactera les performances (latence des requêtes, vitesse), mais également des fonctionnalités comme le filtrage, la mise à l'échelle et la facilité d'intégration. Comparons quelques magasins vectoriels populaires et leurs cas d'utilisation :

Base de données vectorielleForcesCompromis/LimitationsCas d'utilisation typiques
FAISS (Recherche de Similarité IA de Facebook)Bibliothèque C++ avec liaisons Python optimisée pour la recherche de similarité. Prend en charge des index avancés : IVF, HNSW, Quantification de Produits, et accélération GPU. Requêtes en mémoire extrêmement rapidesMémoire uniquement—nécessite une persistance sur disque et un découpage manuel. Pas de support intégré pour les métadonnées ; une base de données externe est nécessaire. Le passage à plus d’une machine nécessite une configuration personnalisée.Charges de travail de récupération à latence ultra-faible (par exemple, recherche en temps réel, systèmes de trading). Prototypes ou systèmes haute performance tenant en RAM
ChromaDBOpen-source avec stockage persistant et APIs Python. Excellente intégration avec LangChain. Support des métadonnées et outils solides pour une utilisation locale.Limité à une utilisation locale/en cours de traitement ; ne dispose pas de clustering natif. La mise à l'échelle manuelle est requise pour les charges de travail en production. Vitesse de requête modéréePrototypage rapide et applications petites à moyennes. Les projets nécessitent de la persistance et un filtrage de métadonnées léger.
Pomme de pinService cloud entièrement géré et sans serveur avec mise à l'échelle automatique. Ensemble de fonctionnalités riche : filtres de métadonnées, multi-locataires, surveillance.Latence plus élevée en raison de la surcharge du réseau (des centaines de ms). Coûts de service et certaine dépendance vis-à-vis des fournisseurs via une API propriétaire. Limites de dimensions/charges maximales selon les spécifications de l'API.Applications d'entreprise à grande échelle avec une charge opérationnelle minimale. Cas d'utilisation nécessitant des filtres de métadonnées et la prise en charge multi-locataire.
  • Vous pouvez utiliser FAISS pour des requêtes locales rapides sur des données de taille raisonnable que vous pouvez tenir en mémoire et pour lesquelles vous souhaitez un contrôle total. (par exemple, <10 millions de vecteurs)
  • Continuez avec ChromaDB pour un déploiement simple si votre jeu de données n'est pas énorme et que vous souhaitez la persistance et l'intégration Python. C'est parfait comme magasin de vecteurs en mémoire pour une application sur un seul serveur ou comme magasin de vecteurs intégré.
  • Utilisez Pinecone (ou un service géré similaire, comme Weaviate Cloud, Azure AI Search, etc., pour une application en production qui pourrait nécessiter une mise à l'échelle jusqu'à des milliards d'embeddings ou plusieurs régions. La latence supplémentaire de Pinecone peut généralement être masquée avec la mise en cache ou les requêtes par lots, et sa cohérence et ses fonctionnalités (comme le filtrage basé sur les métadonnées) sont extrêmement précieuses pour des cas d'utilisation complexes.

Exemple : Développement local avec ChromaDB
Pendant le développement, vous pourriez commencer avec Chroma pour plus de commodité. Considérons le pseudo-code suivant utilisant Langchain :

# Install required packages
#pip install langchain langchain-community chromadb pypdf tiktoken python-dotenv

# Additional for document loading
#pip install beautifulsoup4 html2text lxml


# ===== CHROMA/LANGCHAIN RAG PIPELINE PSEUDO-CODE =====

# 1. ENVIRONMENT SETUP
import os
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader

# 2. CONFIGURATION
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")  # Required environment variable
PERSIST_DIR = "./chroma_db"                  # Storage directory
COLLECTION_NAME = "corporate_docs"           # Vector collection name
EMBEDDING_MODEL = "text-embedding-3-large"   # OpenAI model

# 3. DOCUMENT PROCESSING
# - Load documents from multiple sources
documents = PyPDFLoader("sample_financial_report.pdf").load()  # sample source

# - Semantic-aware chunking
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,      # Character limit per chunk
    chunk_overlap=200,    # Context preservation overlap
    separators=["\n\n", "\n", ". ", " "]  # Natural language boundaries
)
chunks = text_splitter.split_documents(documents)

# 4. EMBEDDING INITIALIZATION
embeddings = OpenAIEmbeddings(
    model=EMBEDDING_MODEL,
    openai_api_key=OPENAI_API_KEY  # Secure credential handling
)

# 5. VECTOR STORE CREATION
vectorstore = Chroma(
    collection_name=COLLECTION_NAME,
    embedding_function=embeddings,
    persist_directory=PERSIST_DIR,

    # Optional production parameters
    client_settings={
        "anonymized_telemetry": False  # Compliance setting
    }
)

# 6. DOCUMENT INJECTION
vectorstore.add_documents(
    documents=chunks,
    ids=[f"doc_{idx}" for idx in range(len(chunks))],  # Unique identifiers
    metadatas=[chunk.metadata for chunk in chunks]  # Preserve context
)

# 7. PERSISTENCE OPERATION
vectorstore.persist()  # Critical for disk storage

# 8. RETRIEVAL VERIFICATION
query = "Q3 financial projections"
results = vectorstore.similarity_search(
    query=query,
    k=5,  # Top 5 results
    filter={"department": "finance"}  # Metadata-based filtering
)

Les scripts précédents créent un pipeline RAG prêt pour la production construit avec LangChain et Chroma. Il charge des documents PDF, les divise de manière sémantique, les intègre en utilisant le modèle d’intégration d’OpenAI, les stocke dans une base de données vectorielle Chroma persistante, et utilise une recherche de similarité filtrée pour récupérer le contexte pertinent pour les requêtes. Ce pipeline sera prêt pour le déploiement après :

  1. Installation des packages requis
  2. Ajouter des documents au répertoire docs/
  3. Définir la clé API OpenAI dans le fichier .env
  4. Exécution du script

Stratégies d'optimisation des performances

Peu importe la base de données vectorielle que vous choisissez, certaines bonnes pratiques s'appliquent :

  • Utiliser la recherche approximative pour l'échelle : La recherche k-NN exacte est coûteuse et ne s'adapte pas nécessairement bien à des ensembles de données très volumineux. Des algorithmes comme HNSW (Hierarchical Navigable Small World) ou IVF (Inverted File Index) peuvent accélérer la recherche au prix d'une certaine perte contrôlable de précision. Les paramètres exacts pour cela sont configurables avec FAISS et la plupart des autres services (par exemple, Pinecone effectue une recherche approximative en arrière-plan). Dans FAISS, vous choisiriez explicitement un type d'index (IVF1000_HNSW32, etc.) et ajusteriez les paramètres de l'index (HNSW M (connexions par nœud), efsearch (profondeur de parcours de recherche), etc.)
  • Considérations sur les dimensions et les modèles : La recherche vectorielle peut être plus lente pour des embeddings de très haute dimension (par exemple, 1536 dimensions avec ada-002, ou plus de 2048 avec les modèles plus récents), en raison de la malédiction de la dimensionnalité. Pour y remédier, vous pouvez essayer la PCA ou une autre réduction de dimensionnalité pour compresser les vecteurs, ou utiliser un modèle d'embedding plus petit si nécessaire.
  • Filtrage et Partitionnement : Si vos données sont organisées en catégories (par temps, par source, etc.), vous pouvez partitionner votre index ou utiliser des filtres (en maintenant des index séparés pour différents types de documents et en interrogeant uniquement celui(s) pertinent(s), par exemple). Cela réduit l'espace de recherche et la latence des requêtes. Certaines bases de données prennent en charge nativement le partitionnement ou la segmentation des données (Milvus, Weaviate), tandis que d'autres peuvent nécessiter une segmentation manuelle.
  • Maintenir les métadonnées : Des métadonnées utiles (source, ID du document, titre de la section, etc.) peuvent être stockées avec chaque vecteur dans l'index, ce qui permet de filtrer et d'améliorer les invites et le débogage en aval (par exemple, si vous connaissez la source, vous pouvez préfixer une réponse par « Selon la source X… »).

La base de données vectorielle est votre magasin d'informations. Vous pouvez choisir celle qui s'adapte à vos besoins et répond aux contraintes de déploiement, puis utiliser les fonctionnalités pour équilibrer au mieux la vitesse, la précision et l'effort de développement.

Modèles d'Embedding et Stratégies pour les Pipelines RAG

Choisir les bons embeddings est une décision fondamentale dans l'architecture de toute pipeline RAG. Les embeddings influencent à la fois la qualité de la récupération et l'efficacité computationnelle. Des embeddings optimaux garantissent des correspondances précises entre les requêtes des utilisateurs et les documents pertinents. Cela influence directement l'efficacité des applications de recherche sémantique et des applications LLM conscientes du contexte.

text-embedding-ada-002 d’OpenAI : Une valeur sûre par défaut

L'un des modèles commerciaux les plus populaires utilisés en production a été text-embedding-ada-002 d'OpenAI.

  • Les vecteurs de 1536 dimensions utilisés par ce modèle offrent un excellent équilibre entre capacité de représentation et coût computationnel.
  • Avec une fenêtre de contexte généreuse de 8191 jetons, ada-002 peut traiter des passages plus longs, des paragraphes entiers, ou même des segments de conversations à plusieurs tours sans tronquer.
  • Performance compétitive : Sur le classement MTEB (Multilingual Text Embedding Benchmarks) pour les modèles d'encodage, ada-002 figurait parmi les meilleurs modèles pour les tâches en anglais.
  • Débit élevé : L'API prend en charge le traitement par lots. Ainsi, des milliers d'embeddings par seconde peuvent être fournis en production.

Les dernières générations d’OpenAI (en particulier text-embedding-3-small et text-embedding-3-large, publiées à la fin de 2024) ont encore amélioré la qualité ou réduit les prix, mais ada-002 reste largement disponible et un « choix par défaut sûr » pour la plupart des scénarios de production.

Alternatives Open-Source et Spécialisées

Pour de nombreuses organisations, les options open-source ou auto-hébergées sont préférables pour des raisons de confidentialité, d'affinage ou d'évitement des coûts.

  • Modèles d'instructeur : Les modèles de style instructeur (par exemple, hkunlp/instructor-xl) sont entraînés avec des instructions ou des invites pour spécialiser les embeddings pour différentes tâches ou domaines.
  • Famille Sentence-BERT (SBERT) (par exemple, all-MiniLM-L6-v2, all-mpnet-base-v2) : Les modèles SBERT sont légers, efficaces et faciles à exécuter sur du matériel CPU/GPU standard. Ces modèles sont excellents pour la recherche générale, le prototypage rapide et dans des situations où l'infrastructure de déploiement doit être extrêmement légère.
  • Modèles multilingues (par exemple, LaBSE, distiluse-base-multilingual-cased-v2) : Si vous développez des applications pour des publics internationaux ou multilingues, ces modèles fourniront des représentations de haute qualité pour des dizaines de langues. Ils sont essentiels pour la recherche non anglaise ou la recherche cross-linguale.
  • Modèles spécifiques à un domaine (par exemple, PubMedBERT pour le biomédical, CodeBERT pour le code) : Si vos pipelines RAG fonctionnent dans des domaines spécialisés (comme la médecine, le droit, l’ingénierie, etc.), alors ces modèles amélioreront considérablement la récupération en comprenant le vocabulaire et la structure sémantique spécifiques à ces domaines.

Les tendances récentes favorisent les stratégies à double encodage : vous pouvez utiliser un encodeur moins coûteux et plus rapide (comme le text-embedding-3-small d’OpenAI) pour récupérer un ensemble de candidats pour le rappel, puis reclasser les résultats avec un modèle plus précis ou spécialisé. Cela peut offrir un bon compromis entre vitesse, coût et performance de récupération.

Stratégies de segmentation pour une récupération optimale

Choisir la stratégie de découpage appropriée est essentiel pour optimiser la précision de récupération et la performance globale des LLM dans les pipelines RAG. Chaque méthode présente des compromis entre la simplicité de mise en œuvre, la qualité de récupération et la consommation de ressources. Le tableau ci-dessous décrit les stratégies de découpage les plus courantes et explique leur mise en œuvre dans LangChain ainsi que les considérations clés :

StratégieComment ça fonctionneAvantagesLimitations
Segmentation de taille fixeDiviser le texte en morceaux de taille égale (par exemple, 1000 jetons), souvent avec chevauchement (par exemple, 200 jetons)Simple à mettre en œuvre. Nombre de fragments/embeddings prévisible. Fonctionne pour du texte homogène ou non structuré.Peut interrompre des phrases/des concepts en plein morceau. Le chevauchement cause des duplications. N’est pas conscient de la structure ni de la sémantique.
Segmentation sémantiqueDiviser le texte en fonction des limites sémantiques, telles que les sujets, les paragraphes ou les sections alignés avec le sens.Les fragments sont sémantiquement cohérents. Améliore la précision et le rappel de récupération. Gère bien les documents structurés.Nécessite des outils de traitement du langage naturel pour la séparation. Taille de segment variable. Plus complexe et coûteux en calcul.
Niveau de phrase (granulaire)Chaque morceau est une phrase ou un petit groupe de phrases ; il peut utiliser une fenêtre glissante pour un contexte minimal.Précision maximale de récupération. Les réponses sont faciles à extraire. Utile pour les tâches de réponse directe.Perte de contexte plus large. La taille de l'index augmente (plus de segments/embeddings). La construction de l'invite LLM peut devenir complexe.

Il n'existe pas une seule approche optimale pour le fractionnement en blocs. Votre choix devrait dépendre de la structure de vos données, de vos objectifs de récupération et du niveau de complexité que vous pouvez gérer. Le fractionnement en blocs de taille fixe offre rapidité et simplicité, tandis que les stratégies sémantiques et au niveau des phrases peuvent fournir des résultats plus précis et contextuellement pertinents, mais peuvent impliquer plus de frais généraux en termes de configuration et de calcul. Il est important d'expérimenter ces stratégies si vous voulez développer un système RAG performant et prêt pour la production.

Techniques RAG Avancées

Au-delà de la configuration de base « intégrer -> récupérer -> générer », des techniques supplémentaires peuvent être appliquées pour optimiser un pipeline RAG. Voici quelques techniques que les praticiens de RAG peuvent utiliser pour améliorer la pertinence et la qualité des réponses :

Réécriture et expansion de requête : L'expansion de requête aborde le problème de l'inadéquation du vocabulaire requête-document en créant plusieurs variantes de la requête de l'utilisateur afin d'améliorer le rappel en élargissant le champ de récupération.

Flux de travail typique:

  1. L'utilisateur soumet une requête initiale.
  2. Un LLM génère diverses requêtes alternatives, telles que des paraphrases, des extensions ou des décompositions.
  3. Chaque requête générée est dirigée vers le magasin de vecteurs ou le système de récupération.
  4. Les résultats sont combinés (souvent en un ensemble unique) afin de maximiser la couverture globale de la réponse.

HyDE (Hypothetical Document Embeddings) : Au lieu d'intégrer et de rechercher directement avec la requête de l'utilisateur, créez d'abord une réponse/document hypothétique pour la requête en utilisant un LLM, puis intégrez cela et recherchez.

Flux de processus :

  1. Générez une réponse hypothétique en utilisant un LLM.
  2. Intégrez la réponse hypothétique.
  3. Utilisez l'embedding pour la recherche de similarité.
  4. Récupérer les documents pertinents en fonction de la similitude des réponses.

Évaluation et suivi

Les métriques traditionnelles d'évaluation de QA et de recherche doivent s'adapter pour s'aligner sur le contexte RAG. Notre évaluation inclut la performance de l'étape de récupération et la qualité globale des réponses. Donc, pour commencer, examinons les différents éléments que nous pourrions vouloir évaluer dans notre pipeline RAG :

Mesures spécifiques à la RAG

Métriques de récupération :

  • Rappel du contexte : Le rappel du contexte est la proportion de documents pertinents selon la vérité terrain qui ont été récupérés.
  • Précision du Contexte (Pertinence du Contexte) : La précision du contexte tente de mesurer la fraction des morceaux récupérés qui étaient réellement pertinents et/ou utiles. Si 5 morceaux ont été récupérés mais que seulement 2 étaient pertinents et en lien avec le sujet, nous dirions que la précision est de 0,4.
  • Classement de la pertinence contextuelle : Si votre processus classe les résultats, vous voudrez peut-être vous assurer que les résultats les plus pertinents sont classés en premier.

Métriques de génération :

  • Pertinence de la réponse : Il s'agit d'une mesure de savoir si la réponse générée est pertinente par rapport à la requête originale.
  • Fidélité: Cela mesure à quel point la réponse générée est fidèle au contexte.
  • Exactitude factuelle : Cette mesure indique dans quelle mesure la réponse correspond à la référence.

Des frameworks tels que DeepEval et RAGAS fournissent des outils pour calculer ces métriques. Par exemple, DeepEval peut utiliser un LLM pour évaluer la fidélité en comparant la réponse et le contexte.

Surveillance en production

Au-delà de l'évaluation hors ligne, vous souhaitez surveiller le pipeline en production pour détecter des anomalies :

  • Journaux de récupération : Enregistrer quels documents ont été récupérés pour une requête donnée (les pipelines de Haystack prennent en charge le retour des ID de documents). En échantillonnant les journaux, vous pourriez être capable de remarquer si des éléments sans rapport sont récupérés ou si certaines requêtes échouent à récupérer des documents.
  • Boucles de rétroaction : Si votre application prend en charge les retours des utilisateurs (par exemple, « Cette réponse a-t-elle été utile ? » ou un système de notation), renvoyez-les à l'analyse. Des réponses régulièrement mal notées peuvent être corrélées à certains types de requêtes, ou certaines parties du processus peuvent ne pas fonctionner correctement.
  • Latence et débit : Surveillez la durée de chaque étape (intégration, récupération, génération par le LLM). Une augmentation soudaine du temps de récupération pourrait indiquer un problème d'index. Un retard dans la génération pourrait signifier que le LLM rencontre des difficultés (par exemple, le contexte fourni était trop long).
  • Dérive du contenu : Si votre base de connaissances est sujette à des changements, ou si les modèles de requêtes des utilisateurs évoluent, surveillez des métriques telles que la pertinence au fil du temps. Il peut être nécessaire de réindexer ou d'affiner périodiquement les récupérateurs pour rester à jour.

Stratégies de déploiement en production

Déployer un pipeline RAG en production implique des considérations de scalabilité, de sécurité et de fiabilité opérationnelle. Le tableau ci-dessous fournit un résumé rapide des stratégies et des meilleures pratiques essentielles :

ZoneStratégie/TechniqueDescription et exemplesConsidérations clés
Évolutivité et performanceMise à l'échelle horizontaleExécutez plusieurs répliques du service RAG derrière un équilibreur de charge (par exemple, via des conteneurs/Kubernetes). Utilisez une base de données vectorielle distribuée ou répliquée (par exemple, Pinecone, Weaviate) pour un accès partagé.Assurez la cohérence des index/données ; la base de données vectorielle doit supporter la mise à l'échelle et l'accès simultané.
Mise en cacheMettez en cache les embeddings de requête, les documents récupérés et (le cas échéant) les réponses du LLM pour accélérer les requêtes répétées et réduire les coûts de calcul.Invalidation du cache et confidentialité ; toutes les sorties ne sont pas mises en cache si les requêtes sont fortement personnalisées.
Traitement asynchroneUtilisez des files de messages et des pools de travailleurs pour gérer des volumes de requêtes élevés, en découplant le traitement des demandes de la récupération et de la génération.Concevoir pour un traitement au moins une fois ou exactement une fois ; gérer la livraison des résultats aux utilisateurs.
Orchestration KubernetesDéployer RAG en tant qu'ensemble de pods avec des limites de ressources, une mise à l'échelle automatique et des contrôles de santé robustes. Utiliser des manifestes YAML pour la configuration (par exemple, définir les réplicas, les demandes/limites de ressources et les secrets pour les clés API).Surveiller la santé des pods, l'utilisation des ressources et mettre en œuvre l'autoscaling en fonction de la demande.
Optimisation de la latenceServices de colocationHébergez vos serveurs de base de données vectorielle et vos serveurs d'application RAG dans la même région afin de minimiser la latence du réseau.Évitez les sauts inter-régions/inter-clouds pour maintenir des temps de requête bas.
Échauffement LLM et StreamingChauffer les modèles LLM au démarrage ; diffuser les réponses LLM aux utilisateurs au fur et à mesure qu'elles sont générées pour améliorer la latence perçue.Réduit les pénalités liées au démarrage à froid et améliore l'expérience utilisateur.
Échec & RécupérationNouvelle tentative et solutions de repliImplémentez une logique de réessai avec un retour exponentiel pour les API externes ; concevez une récupération de secours (par exemple, recherche par mot-clé) si la recherche vectorielle échoue ; vérifications régulières de l'état et surveillance des requêtes échantillons.Assurez la fiabilité et la dégradation élégante en cas de scénarios de défaillance.
Sécurité & ConfidentialitéChiffrement des donnéesChiffrez toutes les données au repos (stockage, base de données vectorielle) et en transit (HTTPS/TLS entre les services). Par exemple, activez KMS ou le chiffrement de disque sur les bases de données cloud et gérées.Respectez les politiques et règlements de l'entreprise (par exemple, RGPD, HIPAA).
Contrôle d'accèsMarquez les documents/vecteurs avec les rôles ou permissions des utilisateurs ; filtrez la récupération en fonction de l'identité de l'utilisateur (par exemple, le filtre de métadonnées de Pinecone).Appliquez des logs d'accès et d'audit stricts ; assurez-vous qu'il n'y ait aucune fuite de données entre utilisateurs ou entre locataires.
Isolation et multi-locationUtilisez des espaces de noms/collections par client ou locataire pour isoler les données dans les déploiements multi-locataires.Prévient les fuites de données à travers les frontières organisationnelles ; simplifie la conformité.
Filtrage de contenuAppliquez un filtrage ou une modération des sorties (par exemple, l’API de modération d’OpenAI) pour empêcher le LLM de divulguer du contenu sensible ou inapproprié.Réduit le risque de fuites de données et aide à faire respecter l'utilisation acceptable.
Confidentialité différentielleAjoutez du bruit aux embeddings ou aux sorties (par exemple, via le mécanisme de Laplace) pour empêcher l'extraction d'informations sensibles ; ou masquez/extrayez les jetons sensibles lors du prétraitement.Équilibrez la confidentialité avec les performances de récupération ; peut affecter la pertinence si trop utilisé.
Conformité réglementaireMettre en place des mécanismes de suppression des données (« droit à l'oubli »), obtenir le consentement des utilisateurs pour l'utilisation des données, et éviter d'envoyer des données à des tiers sans consentement.Restez conforme au RGPD, au CCPA et aux normes de l'industrie.
Surveillance et auditConsigner les documents sources pour chaque réponse, surveiller les modèles d'accès/de requêtes inhabituels et maintenir les journaux du système et de la sécurité.Facilite la confiance, le dépannage et les enquêtes réglementaires.

En suivant ces stratégies, les organisations peuvent réaliser des déploiements RAG évolutifs, sécurisés et fiables. La containerisation, les contrôles d'accès et la surveillance, lorsqu'ils sont intégrés dès le départ, aideront votre système à rester résilient à mesure qu'il se développe et mûrit en production.

FAQ

Qu'est-ce que la génération augmentée par récupération (RAG) et pourquoi devrais-je m'en soucier ? La RAG est une architecture d'intelligence artificielle puissante qui associe la recherche d'informations classique à de grands modèles de langage pour générer des réponses enrichies par des connaissances externes à jour. Elles sont plus factuellement exactes et contextuellement pertinentes que les LLM seuls.

Comment décider entre Haystack et LangChain pour construire une pipeline RAG ? Choisissez Haystack si vous avez besoin d'une pipeline prête pour la production, modulaire et évaluable avec une documentation complète. Vous pouvez choisir LangChain pour prototyper rapidement de nouveaux modèles, construire des flux de travail basés sur des agents, ou pour des intégrations plus flexibles avec divers modèles/stores vectoriels.

Quel est le rôle de la base de données vectorielle dans un pipeline RAG ? La base de données vectorielle stocke les embeddings haute dimension de vos documents et permet une recherche de similarité efficace pour récupérer le contexte le plus pertinent à utiliser pour informer la réponse du LLM.

Quels sont les meilleurs bases de données vectorielles pour les pipelines RAG, et comment en choisir une ?

  • FAISS : Open-source, extrêmement rapide pour la recherche en mémoire ; idéal pour les configurations plus petites, locales ou à haute performance. Nécessite une persistance et une mise à l'échelle manuelles.
  • ChromaDB : Open-source, facile à utiliser, prend en charge la persistance et les métadonnées. Bon pour les charges de travail locales ou de production petites à moyennes.
  • Pinecone/Weaviate/Azure Cognitive Search : Services cloud gérés avec des fonctionnalités riches, filtrage des métadonnées, mise à l'échelle et intégration facile. Convient aux charges de travail volumineuses, distribuées ou d'entreprise.
  • Règle générale : Pour des données locales/petites, commencez avec FAISS ou Chroma ; pour des systèmes à grande échelle ou multi-locataires, utilisez Pinecone, Weaviate ou des similaires.

Conclusion

La conception d'une pipeline RAG prête pour la production nécessite une considération attentive de plusieurs niveaux. Elle va bien au-delà des bases de la récupération et de la génération. Le succès dépend de faire les bons choix à chaque étape, depuis la sélection du framework approprié (Haystack ou LangChain), des modèles d'intégration, des bases de données vectorielles, des stratégies de découpage, de l'évaluation, des pratiques de déploiement, et des mesures de sécurité. Pour vous emmener plus en profondeur dans les étapes pratiques et les meilleures pratiques, voici quelques tutoriels pertinents pour construire et exploiter des pipelines RAG avancés :

  • Conversations interactives avec des PDF en utilisant Langchain
  • Pipelines RAG conteneurisés sur des Droplets GPU
  • Apprenez à créer une application RAG en utilisant des Droplets GPU
  • Au-delà des vecteurs - Graphes de connaissances et RAG utilisant Gradient
  • Comment choisir la bonne base de données vectorielle pour votre architecture RAG

En concevant chaque couche du pipeline méticuleusement et en suivant les meilleures pratiques en matière de scalabilité, de surveillance et de sécurité, vous pouvez fournir des solutions RAG précises, fiables et sécurisées. Comme le paysage des technologies RAG évolue rapidement, il est essentiel de rester flexible et d’évaluer continuellement les composants de votre pipeline pour maintenir une solution efficace et pérenne.

Références et ressources

  • Haystack vs LangChain
  • Construire une application RAG prête pour la production : un guide pratique
  • Construire des applications RAG avancées avec Haystack et LangChain : un guide complet
  • Comment l'expansion de requête (HyDE) améliore la précision de votre RAG
  • RAG avancé : Expansion de requête
  • RAGXplain : De l'évaluation explicable à l'orientation exploitable des pipelines RAG
  • ARES : Un cadre d'évaluation automatisé pour les systèmes de génération augmentée par récupération

Merci d'apprendre avec la communauté Linux-Console.net.