Inicio / Artículos

Crea un asistente de chat para Wikipedia basado en RAG con LlamaIndex y ReAct

Traduzca las páginas del índice de Wikipedia según sea necesario, incorpore fragmentos con un pequeño codificador y permita que un agente ReAct llame a una herramienta de motor de consultas para que las respuestas de Chainlit se basen en evidencias obtenidas.

Editor: REACTAPP.TOP6 min de lectura1383 palabras

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

Introducción

Los modelos de lenguaje grandes son fluidos en su expresión, pero esa fluidez no equivale a saber si una respuesta es precisa o actual. Pueden inventar falsedades plausibles cuando una pregunta está fuera del rango de entrenamiento o cuando su confianza supera a las pruebas disponibles.

Un asistente de chat RAG para Wikipedia que sea práctico cierra esa brecha al combinar indexación de páginas bajo demanda, recuperación semántica, agrupación de pruebas, un agente ReAct que decide cuándo buscar y una interfaz de usuario conversacional que responde a partir del texto recuperado. Los materiales de origen para su desarrollo se encuentran en la muestra agentic-ai wiki RAG del repositorio GitHub data-etl-ml.

¿Por qué RAG?

Sin recuperación de información, el camino es corto pero frágil:

  User Question
      ↓
      LLM
      ↓
    Answer

Todo depende de lo que el modelo memorizó durante su entrenamiento.

Con RAG, las pruebas se introducen antes de la generación:

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

El modelo responde a partir de los fragmentos recuperados. Eso generalmente significa menos alucinaciones, hechos más oportunos, sin necesidad de un ciclo de ajuste fino para actualizar los conocimientos, y una forma sencilla de cambiar o ampliar el corpus.

Objetivo del proyecto

Crear un asistente de chat que responda a partir de las páginas de Wikipedia que el usuario elija para indexar. Ejemplo de solicitud:

Please index:
2023 United States banking crisis

Luego preguntar:

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

La respuesta debe citar el contenido de la página recuperada en lugar de depender únicamente de la memoria del modelo.

Descripción general de la arquitectura

A un nivel alto, el sistema se ve así:

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

Hay dos flujos importantes: un pipeline de indexación que crea el almacén vectorial buscable, y un pipeline de consulta que recupera fragmentos y genera respuestas.

Paso 1: Leer la clave API de OpenAI

Las credenciales no deben estar en el código fuente. Evite codificarlas directamente:

api_key = "xxxxx"

Cargue desde un archivo de configuración en su lugar:

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

    return config["OPENAI_API_KEY"]

Los secretos permanecen separados de la lógica de la aplicación.

Paso 2: Comprender la estructura del código

El proyecto consta de tres módulos en Python:

utils.py
index_wikipages.py
chat_agent.py

utils.py carga las claves de API y la configuración. index_wikipages.py analiza las solicitudes de páginas, descarga el texto de Wikipedia, incrusta los fragmentos y crea índices. chat_agent.py conecta el agente ReAct, la herramienta de motor de consultas y la interfaz de Chainlit.

Paso 3: Extraer páginas de Wikipedia mediante salida estructurada

Los usuarios pueden escribir listas en formato libre:

Please index:
London, Birmingham, New York

El indexador necesita un array ordenado:

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

En lugar de usar divisiones de cadenas frágiles, un modelo Pydantic captura la salida estructurada:

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

El modelo convierte el lenguaje natural en una lista de páginas con tipos definidos automáticamente.

Paso 4: Carga de páginas de Wikipedia

LlamaIndex incluye un cargador práctico:

WikipediaReader

La inserción se realiza con unas pocas líneas:

loader = WikipediaReader()

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

En este punto, el pipeline contiene los documentos de página en formato raw.

Paso 5: División de los documentos en fragmentos

Los modelos manejan mal las páginas grandes como bloques únicos. Es necesario dividirlas en fragmentos superpuestos:

SentenceSplitter(
    chunk_size=150,
    chunk_overlap=45
)

La superposición permite conservar las ideas que se extienden más allá de los límites entre fragmentos:

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

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

Paso 6: Creación de embeddings

El texto en formato raw no es suficiente para la búsqueda semántica. Cada fragmento se convierte en un vector. El modelo de embeddings utilizado aquí es:

BAAI/bge-small-en

Una consulta como esta:

"What is Databricks?"

se traduce en un vector denso:

[0.21, -0.44, 0.87 ...]

Los fragmentos semánticamente relacionados se agrupan cerca unos de otros en ese espacio.

Paso 7: Creación del índice vectorial

LlamaIndex se encarga de la construcción del almacenamiento:

index = VectorStoreIndex(nodes)

El resultado es un índice vectorial en memoria que puede responder a búsquedas de similitud como:

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

Paso 8: Creación del motor de búsqueda

Exponer el índice como un motor de consultas:

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 controla cuántos fragmentos vecinos se utilizan para generar la respuesta.

Paso 9: Construcción del agente ReAct

ReAct significa:

Reason + Act

Un bot ingenuo pasa directamente de la pregunta a la respuesta:

Question
→ Answer

Un agente ReAct incluye razonamiento y uso de herramientas:

Question
↓
Reason
↓
Choose Tool
↓
Observe Output
↓
Answer

La recuperación de información se vuelve dinámica en lugar de estar siempre activa o nunca activa.

Creación de herramientas

Envolver el motor de consultas como una herramienta que el agente pueda llamar:

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

De esta manera, el agente sabe que existe la capacidad de realizar búsquedas en Wikipedia.

ReAct Loop

The agent internally performs:

Internamente, el bucle se ve así:

Thought:
Need information about the banking crisis.

Action:
Wikipedia Tool

Observation:
Found relevant passages.

Answer:
Grounded response.

Ese patrón es más fiable que una simple completación de chat sin herramientas.

Paso 10: Crear la interfaz de usuario con Chainlit

Chainlit ofrece una estructura para chats con un código mínimo. Un panel de configuración muestra:

Model
Wikipedia Pages

Ejemplo de configuración:

MODEL:
gpt-5-nano

Wikipedia Pages:
Please index:
2023 United States banking crisis

La configuración inicializa el índice vectorial antes de que comience la conversación.

Demostración

Después del indexado:

2023 United States banking crisis

una pregunta como:

Which bank experienced the fastest
bank run in US history?

produce una respuesta basada en evidencias reales como:

Silicon Valley Bank (SVB)

Approximately $42 billion
was withdrawn in 10 hours.

Las cifras provienen de pruebas obtenidas, no de invenciones arbitrarias.

Aprendizajes

Lo que funcionó bien

LlamaIndex mantiene el proceso de indexado breve:

Documents
→ Nodes
→ Index

Los agentes ReAct mejoran las decisiones sobre cuándo recuperar información, de modo que la búsqueda se realiza solo cuando es necesaria. Chainlit sigue siendo una de las vías más rápidas para obtener una interfaz de chat con IA utilizable.

Desafíos

La compatibilidad con Python 3.13 afectó a varios conjuntos de herramientas: las combinaciones de Chainlit, Pydantic y LlamaIndex resultaron inestables. Fijar las versiones:

Python 3.11

fue mucho más fiable.

La calidad de la recuperación determina la calidad de las respuestas. Los fragmentos de mala calidad generan vecinos de mala calidad, lo que a su vez produce respuestas deficientes. La lección clave: la calidad de la recuperación suele ser más importante que el modelo de chat utilizado.

Mejoras futuras

Los siguientes pasos lógicos incluyen la búsqueda híbrida:

Keyword Search
+
Semantic Search

Reclasificación después de una primera fase de recuperación amplia: recuperar:

Top 50

Luego, comprimir hasta obtener las mejores opciones. Citas que muestren los párrafos correspondientes a cada afirmación. Y una b base de datos vectoriales persistente en lugar de una efímera:

VectorStoreIndex

con opciones como Chroma, Pinecone, Weaviate o Milvus.

Reflexiones finales

El proyecto ofrece una visión concisa de los patrones agentes modernos: RAG, embeddings, búsqueda vectorial, herramientas ReAct, interfaz Chainlit y orquestación LlamaIndex. El punto estratégico radica en algo más que en una sola biblioteca. Los sistemas fiables surgen de combinar modelos con mecanismos de recuperación, herramientas y bucles de razonamiento, no solo de buscar cantidades cada vez mayores de parámetros. Clona la muestra 6_wiki_rag_react_project dentro de la carpeta agentic-ai del proyecto GitHub data-etl-ml para experimentar con toda la estructura.

Lecturas relacionadas

  • Cuando un bot RAG cita el deducible de seguro incorrecto — Un divisor de tamaño fijo distribuye una cantidad en dólares en varias líneas; es necesario reconstruir el análisis y ascender por cuatro niveles de división, desde líneas base recursivas hasta la recuperación del documento padre, antes de confiar en las respuestas.
  • Construir aplicaciones web nativas de IA con JavaScript y WebGPU en el navegador — Ejecutar modelos transformers localmente con WebGPU, workers, tokens en streaming y RAG opcional del lado del cliente, al tiempo que se planifica el tamaño del modelo, la VRAM, el consumo de batería y las soluciones alternativas.
  • Construir un pipeline simple de GraphRAG con Neo4j, Gemini y LangChain — Extracción de grafos relacionados con accidentes en la cocina restringida por esquemas, consultas de vecindad, rutas de múltiples saltos y conversión de texto a Cypher solo de lectura con Gemini.
  • Asistente de documentos RAG con servicios pruebables y Next.js Chat — Separar las solicitudes HTTP de los servicios en Python puro, indexar documentos, citar segmentos y crear una interfaz de dos paneles sin necesidad de modificar el proceso de recuperación de información.