Retour à l'accueil

RAG : fonctionnement et code Python minimal

Les systèmes RAG améliorent les modèles de langage en intégrant des données externes pour des réponses précises et à jour. Ce guide détaille le workflow complet : découpage, indexation, récupération et génération. Une implémentation Python minimale avec LangChain et Chroma est fournie pour une mise en pratique immédiate.

Implémentez RAG en Python : guide pratique et complet
Advertisement 728x90

Systèmes RAG : fonctionnement et implémentation minimale en Python

Les modèles de langage sont limités par leurs données d'entraînement : les connaissances sont statiques, ne couvrent pas l'actualité, et sont sujets aux hallucinations — invention de faits. La fenêtre de contexte aggrave le problème en tronquant les entrées au-delà des limites. La génération augmentée par récupération (RAG) résout cela en extrayant un contexte pertinent de sources externes pendant la génération, réduisant les erreurs et fournissant des citations sources.

RAG relie des documents, bases de données ou dépôts de code pour rendre les réponses vérifiables et à jour. C'est indispensable pour des domaines spécialisés non couverts par l'entraînement du modèle.

Découpage des documents

Le découpage divise le texte en fragments (chunks) pour l'indexation. Les LLM gèrent un nombre limité de chunks, donc la qualité des chunks détermine l'accès aux faits.

Google AdInline article slot

Les gros chunks ajoutent du bruit, augmentent les coûts et nuisent à la précision de recherche. Les petits cassent le contexte, séparant des idées liées. Stratégies :

  • Longueur fixe en caractères ou tokens.
  • Frontières sémantiques (paragraphes, titres).
  • Chevauchement pour maintenir la continuité.

Ajustez les paramètres empiriquement selon votre corpus et vos requêtes.

Étapes du workflow RAG

RAG couvre la prétraitement, la récupération et la génération :

Google AdInline article slot
  • Indexation : Les chunks deviennent des vecteurs stockés en base vectorielle.
  • Récupération : La requête est vectorisée, les meilleurs chunks extraits.
  • Augmentation : Résultats classés, doublons et bruit nettoyés.
  • Génération : Contexte ajouté à la requête pour le LLM.

Le RAG naïf basique reste simple. Le RAG avancé ajoute réécriture de requête et reranking. Le RAG modulaire utilise des modules comme le routage et la fusion de résultats.

RAG vs. Fine-tuning

RAG étend l'accès aux connaissances sans modifier le modèle, contrairement au fine-tuning qui exige des données et une grosse puissance de calcul. L'ingénierie de prompts ajuste les requêtes mais n'ajoute pas de données externes.

| Approche | Avantages | Inconvénients |

Google AdInline article slot

|--------------|----------------------------|---------------------------|

| RAG | Données fraîches, faible coût, citations | Dépend de la qualité de récupération |

| Fine-tuning | Personnalisation profonde | Ressources intensives, obsolète |

RAG excelle avec des données dynamiques ; fine-tuning pour domaines statiques.

Pipeline RAG minimal : mise en pratique

On construit un RAG naïf en Python avec Wikipédia (500 articles) et Qwen2.5-3B-Instruct. En utilisant LangChain, Chroma et sentence-transformers.

Étape 1 : Chargement et découpage

import torch
from datasets import load_dataset
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.documents import Document

device = "cuda" if torch.cuda.is_available() else "cpu"


dataset = load_dataset(
    "wikimedia/wikipedia",
    "20231101.ru",
    split="train[:500]"
)

documents = [
    Document(
        page_content=row["text"],
        metadata={"title": row["title"]}
    )
    for row in dataset
]

splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,
    chunk_overlap=100
)

chunks = splitter.split_documents(documents)

print("Chunks:", len(chunks))

Produit ~17 892 chunks de 800 caractères avec chevauchement de 100.

Étape 2 : Index vectoriel

from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings

embedding_model = HuggingFaceEmbeddings(
    model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
    model_kwargs={"device": device}
)

vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embedding_model
)

MiniLM multilingue pour les embeddings, Chroma pour le stockage.

Étape 3 : Récupération

import textwrap

def search(query, k=3, width=80):
    results = vectorstore.similarity_search(query, k=k)

    for i, doc in enumerate(results, 1):
        print(f"\n--- Résultat {i} ---")
        print("Titre:", doc.metadata["title"])
        print(textwrap.fill(doc.page_content[:1000], width))

search("Qui est Pouchkine ?")

Extrait des extraits pertinents des articles sur Pouchkine.

Étape 4 : Génération

Ajoutez un LLM pour générer à partir des chunks récupérés (code omis pour brièveté ; version complète dans la source).

Points clés

  • RAG réduit les hallucinations grâce à un contexte externe, sans retoucher le modèle.
  • Le succès repose sur le découpage et les embeddings : adaptez à votre domaine.
  • Commencez par RAG naïf, passez à avancé/modulaire pour la production.
  • LangChain simplifie le prototypage.
  • Testez sur de vrais datasets pour optimiser.

— Editorial Team

Advertisement 728x90

Lire ensuite