Volver al inicio

Sistemas RAG en Python: Guía práctica

Los sistemas RAG mejoran los modelos de lenguaje recuperando contexto externo para respuestas precisas y actualizadas. Esta guía explica su funcionamiento, compara con ajuste fino y ofrece una implementación mínima en Python con LangChain y Chroma sobre datos de Wikipedia.

¡Implementa RAG en Python ya! Guía completa
Advertisement 728x90

# Sistemas RAG: Cómo funcionan e implementación mínima en Python

Los modelos de lenguaje están limitados por sus datos de entrenamiento: el conocimiento es estático, no cubre eventos actuales y tiende a alucinar, inventando hechos. La ventana de contexto agrava el problema al descartar entrada cuando se alcanza el límite. La Generación Aumentada por Recuperación (RAG) soluciona esto recuperando contexto relevante de fuentes externas durante la generación, reduciendo errores y proporcionando citas de fuentes.

RAG conecta documentos, bases de datos o repositorios de código para hacer las respuestas verificables y actualizadas. Es esencial para dominios especializados en los que el modelo no fue entrenado.

División de documentos en fragmentos

La división en fragmentos (chunking) descompone el texto en pedazos para indexarlos. Los LLM manejan un conjunto limitado de fragmentos, por lo que la calidad de los chunks determina el acceso a los hechos.

Google AdInline article slot

Fragmentos grandes añaden ruido, elevan costos y perjudican la precisión de búsqueda. Fragmentos pequeños rompen el contexto, separando ideas relacionadas. Estrategias:

  • Longitud fija de caracteres o tokens.
  • Límites semánticos (párrafos, encabezados).
  • Solapamiento para mantener la continuidad.

Ajusta los parámetros empíricamente según tu corpus y consultas.

Etapas del flujo de trabajo RAG

RAG abarca preprocesamiento, recuperación y generación:

Google AdInline article slot
  • Indexación: Los fragmentos se convierten en vectores y se almacenan en una base de datos vectorial.
  • Recuperación: La consulta se vectoriza y se extraen los fragmentos más relevantes.
  • Aumentación: Los resultados se clasifican, se eliminan duplicados y ruido.
  • Generación: Se añade el contexto a la consulta para el LLM.

El RAG Naive básico lo mantiene simple. El RAG Avanzado añade reescritura de consultas y reranking. El RAG Modular usa módulos como enrutamiento y fusión de resultados.

RAG vs. Ajuste fino

RAG amplía el acceso al conocimiento sin cambiar el modelo, a diferencia del ajuste fino que requiere datos y mucho cómputo. La ingeniería de prompts ajusta consultas pero no añade datos externos.

| Enfoque | Ventajas | Desventajas |

Google AdInline article slot

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

| RAG | Datos frescos, bajo costo, citas | Depende de la calidad de recuperación |

| Ajuste fino | Personalización profunda | Consume muchos recursos, se queda obsoleto |

RAG brilla con datos dinámicos; el ajuste fino para dominios estáticos.

Pipeline RAG mínima: En la práctica

Construiremos un RAG Naive en Python usando Wikipedia (500 artículos) y Qwen2.5-3B-Instruct. Aprovechando LangChain, Chroma y sentence-transformers.

Paso 1: Carga y división

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))

Produce ~17.892 fragmentos de 800 caracteres con solapamiento de 100.

Paso 2: Índice vectorial

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 multilingüe para embeddings, Chroma para almacenamiento.

Paso 3: Recuperación

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--- Resultado {i} ---")
        print("Título:", doc.metadata["title"])
        print(textwrap.fill(doc.page_content[:1000], width))

search("¿Quién es Pushkin?")

Extrae fragmentos relevantes de artículos sobre Pushkin.

Paso 4: Generación

Añade un LLM para generar a partir de los fragmentos recuperados (código omitido por brevedad; versión completa en la fuente).

Lecciones clave

  • RAG reduce alucinaciones con contexto externo, sin modificar el modelo.
  • El éxito depende de la división en fragmentos y embeddings: adáptalos a tu dominio.
  • Empieza con RAG Naive, escala a Avanzado/Modular para producción.
  • LangChain simplifica el prototipado.
  • Prueba con datasets reales para optimizar.

— Editorial Team

Advertisement 728x90

Leer después