Accueil / Articles

Créer un assistant de chat basé sur Wikipedia RAG à l’aide de LlamaIndex et ReAct

Indexer les pages de Wikipédia sur demande, intégrer des extraits à l’aide d’un petit encodeur, et permettre à un agent ReAct d’appeler un outil de moteur de requêtes afin que les réponses de Chainlit restent fondées sur des preuves obtenues.

Éditeur : REACTAPP.TOP6 min de lecture1383 mots

Sources: **I Built a ChatGPT-Like Wikipedia Assistant Using RAG, ReAct Agents, and LlamaIndex in Under 300 Lines of Python**

Introduction

Les grands modèles de langage sont fluides dans leur expression, mais cette fluidité ne signifie pas qu’ils savent si une réponse est exacte ou à jour. Ils peuvent inventer des fausses informations plausibles lorsque la question dépasse les limites de leur entraînement ou lorsque leur confiance dépasse les preuves disponibles.

Un assistant de chat RAG pour Wikipedia comble cette lacune en combinant un indexage de pages sur demande, une récupération sémantique, l’agrégation des preuves, un agent ReAct qui décide quand effectuer des recherches, ainsi qu’une interface conversationnelle qui répond à partir du texte récupéré. Les matériaux sources pour sa création se trouvent dans l’exemple RAG agentic-ai wiki sur le répertoire GitHub data-etl-ml.

Pourquoi RAG ?

Sans récupération de données, le processus est court mais fragile :

  User Question
      ↓
      LLM
      ↓
    Answer

Tout dépend de ce que le modèle a mémorisé lors de son entraînement.

Avec RAG, les preuves sont intégrées avant la génération du texte :

User Question
      ↓
    Retriever
      ↓
Relevant Documents
      ↓
     LLM
      ↓
Grounded Answer

Le modèle répond en s’appuyant sur des extraits récupérés. Cela signifie généralement moins d’hallucinations, des faits plus récents, pas de cycle de fine-tuning nécessaire pour actualiser les connaissances, ainsi qu’une manière simple de remplacer ou d’élargir le corpus.

Objectif du projet

Créer un assistant de conversation qui répond en s’appuyant sur les pages Wikipédia que l’utilisateur choisit d’indexer. Exemple de demande :

Please index:
2023 United States banking crisis

Puis demandez :

Which bank experienced the fastest bank run
in US history during 2023?

La réponse doit citer le contenu de la page récupérée plutôt que se fier à la mémoire du modèle seule.

Aperçu de l’architecture

À un niveau général, le système se présente comme suit :

Wikipedia Pages
        │
        ▼
 WikipediaReader
        │
        ▼
 SentenceSplitter
        │
        ▼
 Embeddings
 BAAI/bge-small-en
        │
        ▼
 VectorStoreIndex
        │
        ▼
 Query Engine
        │
        ▼
 QueryEngineTool
        │
        ▼
 ReAct Agent
        │
        ▼
 Chainlit UI

Deux flux sont importants : un tuyau d’indexation qui crée le stockage vectoriel consultable, et un tuyau de requête qui récupère des extraits et génère des réponses.

Étape 1 : Lire la clé API d’OpenAI

Les identifiants ne doivent pas figurer dans le code source. Évitez de les coder directement :

api_key = "xxxxx"

Chargement depuis un fichier de configuration plutôt :

def get_apikey():
    with open("apikeys.yml") as file:
        config = yaml.safe_load(file)

    return config["OPENAI_API_KEY"]

Les secrets restent séparés de la logique de l’application.

Étape 2 : Comprendre la structure du code

Le projet se compose de trois modules Python :

utils.py
index_wikipages.py
chat_agent.py

utils.py charge les clés API et la configuration. index_wikipages.py analyse les demandes de pages, télécharge le texte de Wikipédia, insère des extraits et crée des index. chat_agent.py relie l’agent ReAct, l’outil de moteur de requêtes et l’interface Chainlit.

Étape 3 : Extraire les pages de Wikipédia à l’aide d’une sortie structurée

Les utilisateurs peuvent saisir des listes en format libre :

Please index:
London, Birmingham, New York

L’indexeur a besoin d’un tableau propre :

[
 "London",
 "Birmingham",
 "New York"
]

Au lieu d’une segmentation de chaînes fragile, un modèle Pydantic capture une sortie structurée :

class WikiPageList(BaseModel):
    pages: List[str]

Le modèle transforme automatiquement le langage naturel en une liste de pages typées.

Étape 4 : Chargement des pages Wikipedia

LlamaIndex fournit un chargeur pratique :

WikipediaReader

La saisie se fait en quelques lignes seulement :

loader = WikipediaReader()

documents = loader.load_data(
    pages=["2023 United States banking crisis"]
)

À ce stade, le pipeline contient des documents de pages bruts.

Étape 5 : Division en blocs des documents

Les modèles ont du mal à gérer de grandes pages en tant que blocs uniques. Il faut les diviser en parties superposées :

SentenceSplitter(
    chunk_size=150,
    chunk_overlap=45
)

La superposition permet de conserver les idées qui se situent à la frontière entre deux parties :

Chunk A:
---------------------
Paragraph 1
Paragraph 2

Chunk B:
---------------------
Paragraph 2
Paragraph 3

Étape 6 : Création des embeddings

Le texte brut n’est pas suffisant pour une recherche sémantique. Chaque bloc devient un vecteur. Le modèle d’embedding utilisé ici est :

BAAI/bge-small-en

Une requête telle que :

"What is Databricks?"

est traduite en un vecteur dense :

[0.21, -0.44, 0.87 ...]

Les blocs sémantiquement liés se regroupent à proximité dans cet espace.

Étape 7 : Création de l’index vectoriel

LlamaIndex gère la construction de cet index :

index = VectorStoreIndex(nodes)

Le résultat est un index vectoriel en mémoire qui peut répondre à des recherches de similarité telles que :

Find chunks similar to:
"fastest bank run in history"

Étape 8 : Création du moteur de recherche

Exposer l’index en tant que moteur de requêtes :

query_engine = index.as_query_engine(
    response_mode="compact",
    similarity_top_k=10,
    verbose=True
)
similarity_top_k = 10

Return 10 most relevant chunks

similarity_top_k détermine le nombre de blocs voisins qui alimentent la réponse.

Étape 9 : Construction de l’agent ReAct

ReAct signifie :

Reason + Act

Un bot naïf passe directement de la question à la réponse :

Question
→ Answer

Un agent ReAct intègre du raisonnement et l’utilisation d’outils :

Question
↓
Reason
↓
Choose Tool
↓
Observe Output
↓
Answer

La récupération devient dynamique au lieu d’être constamment active ou jamais active.

Création d’outils

Encadrer le moteur de requêtes en tant qu’outil que l’agent peut appeler :

QueryEngineTool(
    query_engine=query_engine,
    metadata=ToolMetadata(
        name="Wikipedia"
    )
)

L’agent sait alors qu’une fonction de recherche sur Wikipedia est disponible.

ReAct Loop

The agent internally performs:

En interne, la boucle ressemble à ceci :

Thought:
Need information about the banking crisis.

Action:
Wikipedia Tool

Observation:
Found relevant passages.

Answer:
Grounded response.

Celui-ci est plus fiable qu’une simple complétion de chat sans outils.

Étape 10 : Création de l’interface utilisateur avec Chainlit

Chainlit fournit une interface de chat avec un minimum de code pré-rempli. Un panneau de paramètres expose :

Model
Wikipedia Pages

Exemple de configuration :

MODEL:
gpt-5-nano

Wikipedia Pages:
Please index:
2023 United States banking crisis

Les paramètres initialisent l’index vectoriel avant le début de la conversation.

Démonstration

Après l’indexation :

2023 United States banking crisis

une question telle que :

Which bank experienced the fastest
bank run in US history?

produit une réponse fondée sur des données concrètes comme :

Silicon Valley Bank (SVB)

Approximately $42 billion
was withdrawn in 10 hours.

Les chiffres proviennent de preuves récupérées, et non d’inventions arbitraires.

Leçons apprises

Ce qui a bien fonctionné

LlamaIndex permet de garder le processus d’indexation court :

Documents
→ Nodes
→ Index

Les agents ReAct améliorent les décisions concernant le moment de récupérer les données, de sorte que la recherche ne s’exécute qu’en cas de besoin. Chainlit reste l’un des moyens les plus rapides pour obtenir une interface de chat IA utilisable.

Défis

La compatibilité avec Python 3.13 a posé des problèmes à plusieurs stacks : les combinaisons Chainlit, Pydantic et LlamaIndex étaient instables. Le verrouillage des versions :

Python 3.11

était bien plus fiable.

La qualité de la récupération influence fortement la qualité des réponses. Des données de mauvaise qualité entraînent des résultats médiocres. Leçon importante : la qualité de la récupération est souvent plus cruciale que le modèle de chat utilisé.

Améliorations futures

Les prochaines étapes logiques incluent la recherche hybride :

Keyword Search
+
Semantic Search

Le réclassement après une première phase de récupération massive — puis la récupération des résultats pertinents :

Top 50

ensuite, compresser les résultats pour n’en garder que les meilleurs. Des citations qui mettent en évidence les paragraphes correspondant à chaque affirmation. Et une base de données vectorielle persistante plutôt qu’une temporaire :

VectorStoreIndex

avec des options telles que Chroma, Pinecone, Weaviate ou Milvus.

Considerations finales

Ce projet offre un aperçu concis des modèles agents modernes : RAG, embeddings, recherche vectorielle, outils ReAct, interface Chainlit et orchestration LlamaIndex. L’aspect stratégique réside dans la combinaison de modèles avec des mécanismes de récupération d’informations, des outils et des boucles de raisonnement — et non uniquement dans la recherche de modèles dotés d’un nombre toujours croissant de paramètres. Clonez l’exemple 6_wiki_rag_react_project situé dans le dossier agentic-ai du projet GitHub data-etl-ml pour expérimenter avec l’ensemble de la structure.