Generative AI

Cómo construir un pipeline RAG: guía de configuración paso a paso

Respuesta corta (agosto de 2026): un pipeline RAG recupera fragmentos relevantes de tus propios documentos y los inyecta en el prompt de un LLM antes de la generación, de modo que el modelo responde con tus datos en lugar de su memoria de entrenamiento. Necesitas cuatro componentes: un cargador de documentos, un divisor de texto, un modelo de embeddings y un almacén vectorial. El punto de partida más rápido es pip install langchain langchain-openai langchain-chroma chromadb, una API key de OpenAI y una tarde. El modelo text-embedding-3-small de OpenAI cuesta $0.02 por millón de tokens en su API estándar, así que indexar un corpus de 50,000 fragmentos desde cero suele costar menos de $0.50.

Última verificación: 17 de agosto de 2026, según documentación oficial y páginas de precios.

Cómo funciona un pipeline RAG

RAG son las siglas de retrieval-augmented generation (generación aumentada por recuperación). La mecánica: conviertes tus documentos en embeddings vectoriales de antemano, los almacenas en una base de datos vectorial y, en el momento de la consulta, embedas la pregunta del usuario con el mismo modelo y recuperas los fragmentos semánticamente más similares. Esos fragmentos van al prompt del LLM junto con la pregunta.

Cada consulta ejecuta cuatro etapas:

Indexación (se ejecuta una sola vez): carga los documentos, los divide en fragmentos, genera embeddings de cada fragmento y escribe los vectores en la base de datos.

Recuperación: genera el embedding de la consulta entrante, ejecuta una búsqueda de vecino más cercano y devuelve los k fragmentos más relevantes.

Aumentación: inserta esos fragmentos en una plantilla de prompt junto a la pregunta del usuario.

Generación: envía el prompt completo al LLM; el modelo responde usando el contexto recuperado como base.

La propiedad clave que te aporta RAG: el LLM solo puede citar lo que la recuperación encontró. Las alucinaciones no desaparecen, pero se reducen considerablemente porque el modelo tiene texto concreto al que referirse. Si tu paso de recuperación no encuentra el fragmento relevante, el modelo no tiene nada con qué trabajar; por eso la calidad de la recuperación es la palanca principal que debes optimizar.

Elige tu stack

Dos frameworks de Python concentran la mayor parte de los workloads RAG en producción: LangChain (v1.3.15 a agosto de 2026) y LlamaIndex (llama-index-core v0.14.23 a junio de 2026). Admiten los mismos almacenes vectoriales y modelos de embeddings, así que migrar entre ellos no es un drama, aunque sus modelos de programación son distintos.

El modelo de composición de LangChain, LCEL (LangChain Expression Language), conecta los pasos con el operador |. Te da control explícito sobre cada etapa, algo que importa cuando quieres agregar reranking, enrutamiento o bucles agénticos. Si planeas construir agentes de IA junto a tu pipeline RAG, LangChain integra ese trabajo de forma más natural.

LlamaIndex está diseñado específicamente para Q&A con documentos intensivos en datos. Su llamada VectorStoreIndex.from_documents() gestiona la carga, el fragmentado, el embedding y la indexación en una sola línea. Menos partes móviles que administrar, pero también menos hooks para personalizar cada paso. Por defecto usa text-embedding-ada-002 de OpenAI para los embeddings; tienes que sobreescribirlo explícitamente para usar un modelo más reciente.

Para el almacén vectorial, tu elección determina tanto la carga operacional como el costo a escala:

Vector Store Nivel gratuito Precio de pago inicial Opción autoalojada Mejor para
Chroma Gratuito (open source, corre en proceso) Chroma Cloud: $5 de créditos, luego pago por uso Sí (Apache 2.0) Desarrollo local; prototipos en proceso
Qdrant Gratuito sin límite de tiempo: 0.5 vCPU, 1 GB RAM, 4 GB de disco Standard: facturación por hora según uso Sí (Apache 2.0) Autoalojamiento en producción; búsqueda filtrada
Pinecone Starter: 2 GB de almacenamiento, 5 índices serverless Builder: $20/month, tarifa fija No (solo nube administrada) Despliegues administrados sin operaciones
pgvector Gratuito (extensión de PostgreSQL) Los costos de tu hosting de Postgres actual Equipos que ya usan Postgres

Chroma es la opción predeterminada correcta para desarrollo local. El nivel gratuito en la nube de Qdrant está bien aprovisionado para un prototipo que necesita persistir entre reinicios. Cambia a Pinecone o a un clúster de Qdrant en producción cuando necesites SLAs de disponibilidad.

Instala y configura tu entorno

LangChain con Chroma:

pip install langchain langchain-openai langchain-text-splitters langchain-chroma chromadb

Configura tu API key:

export OPENAI_API_KEY="sk-..."

LlamaIndex con el almacén en memoria predeterminado:

pip install llama-index-core llama-index-llms-openai llama-index-embeddings-openai

LlamaIndex 0.10 y versiones posteriores usan una estructura de paquetes modular. Instala solo las integraciones que necesites. Para usar Qdrant como almacén vectorial, agrega llama-index-vector-stores-qdrant. Para Pinecone, agrega llama-index-vector-stores-pinecone. Ambos frameworks leen OPENAI_API_KEY de tu entorno automáticamente.

Coloca tus documentos en una carpeta llamada data/ antes de pasar al siguiente paso. Ambos frameworks procesan PDFs, texto plano, Markdown y HTML sin configuración adicional.

Fragmenta tus documentos

Los divisores de texto dividen los documentos en fragmentos recuperables. El tamaño del fragmento influye tanto en la calidad de la recuperación como la elección del modelo de embeddings, así que defínelo con cuidado.

El punto de partida consensuado actualmente es de 512 tokens por fragmento con un 10 percent de solapamiento (aproximadamente 50 tokens para un fragmento de 512). Los fragmentos más pequeños ofrecen una recuperación más precisa para preguntas factuales. Los más grandes dan al modelo más contexto por fragmento recuperado, lo que ayuda cuando las respuestas requieren razonamiento de varios párrafos.

El divisor recursivo por caracteres es el predeterminado más fiable. Intenta cortar primero en los límites de párrafo, luego en oraciones y después en palabras, preservando las unidades semánticas donde es posible.

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import DirectoryLoader

loader = DirectoryLoader("data/")
documents = loader.load()

splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
)
chunks = splitter.split_documents(documents)
print(f"Created {len(chunks)} chunks")

Una advertencia: un solapamiento por encima de cierto umbral añade costo de almacenamiento y embedding sin una mejora mensurable en la recuperación en la mayoría de los benchmarks. Si tu recall es bajo, prueba con fragmentos más pequeños o un modelo de embeddings mejor antes de aumentar el solapamiento.

Genera embeddings e indexa

El embedding convierte cada fragmento en un vector de números de punto flotante que codifica el significado semántico. Ejecutas este paso una sola vez en el momento de la indexación; el mismo modelo vuelve a ejecutarse en el momento de la consulta sobre la pregunta del usuario.

Los modelos de embeddings actuales de OpenAI, verificados en su página oficial de precios:

  • text-embedding-3-small: $0.02 por millón de tokens, 1,536 dimensiones, límite de entrada de 8,192 tokens
  • text-embedding-3-large: $0.13 por millón de tokens, 3,072 dimensiones, límite de entrada de 8,192 tokens

text-embedding-3-small es la opción predeterminada correcta para la mayoría de los workloads RAG. El modelo large obtiene 64.6% en los benchmarks MTEB frente al 62.3% del small, una ganancia de calidad modesta a un precio 6.5x mayor. Empieza con small; haz un benchmark de ambos con tus consultas de recuperación reales antes de pagar por large.

Indexación con LangChain y Chroma:

from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db",
)
print(f"Indexed {vectorstore._collection.count()} vectors")

Con LlamaIndex, sobreescribe el modelo de embeddings predeterminado antes de construir el índice:

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.openai import OpenAIEmbedding

Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")

documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)

Sin la configuración de Settings.embed_model, LlamaIndex usa text-embedding-ada-002 por defecto ($0.10/M tokens), un modelo más antiguo que text-embedding-3-small supera a una quinta parte de su costo.

Consulta: recupera y genera

En el momento de la consulta, el pipeline genera el embedding de la pregunta, recupera los k fragmentos más relevantes y los pasa al LLM. El parámetro k es el ajuste más determinante en esta etapa.

Patrón LangChain LCEL:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

prompt = ChatPromptTemplate.from_template(
"Answer using only the context below. "
"If the context does not contain the answer, say so.\n\n"
"Context: {context}\n\nQuestion: {question}"
)

llm = ChatOpenAI(model="gpt-4o-mini")

chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)

answer = chain.invoke("What does the refund policy cover?")
print(answer)

Patrón LlamaIndex:

query_engine = index.as_query_engine(similarity_top_k=4)
response = query_engine.query("What does the refund policy cover?")
print(response)

Empieza con k=4. Súbelo a 6 o 8 si el modelo dice con frecuencia que le falta contexto. Cada fragmento adicional recuperado consume tokens de la ventana de contexto y eleva el costo de inferencia, así que hay un equilibrio real que gestionar. La instrucción en el prompt "if the context does not contain the answer, say so" reduce de forma notable las alucinaciones en producción.

Preguntas frecuentes

¿Importa más el modelo de embeddings que la estrategia de fragmentación?
Un estudio con revisión de pares en NAACL 2025 (Vectara) concluyó que las decisiones de fragmentación influyen tanto en la calidad de la recuperación como la elección del modelo de embeddings. Define tu tamaño de fragmento con cuidado antes de actualizar a un modelo más costoso.

¿Puedo ejecutar todo esto de forma local sin llamadas a APIs externas?
Sí. Reemplaza OpenAI con un modelo local vía Ollama para la inferencia del LLM e instala llama-index-embeddings-huggingface o un paquete similar para los embeddings locales. Chroma corre completamente en proceso sin llamadas de red. Espera menor rendimiento y, por lo general, menor calidad de respuesta en comparación con los modelos alojados.

¿Qué pasa cuando un documento supera el límite de 8,192 tokens del modelo de embeddings?
El documento debe fragmentarse antes de generar el embedding. Tanto los divisores de texto de LangChain como los analizadores de nodos de LlamaIndex lo gestionan automáticamente. Mantén el tamaño del fragmento cómodamente por debajo de 8,000 tokens; el tokenizador del modelo usa un vocabulario fijo y tus estimaciones basadas en caracteres pueden ser ligeramente inexactas.

¿Es pgvector suficientemente bueno para reemplazar un almacén vectorial dedicado?
Para corpus más pequeños con un índice HNSW, pgvector rinde de forma comparable a los almacenes vectoriales dedicados y elimina un servicio que administrar. A mayor escala o cuando necesitas rendimiento avanzado en búsqueda filtrada, Qdrant y Pinecone ofrecen más opciones de ajuste.

¿Cómo actualizo el índice cuando cambian mis documentos?
La mayoría de los almacenes vectoriales admiten operaciones de upsert identificadas por un ID de documento. Asigna IDs estables (funciona un hash de la ruta del archivo más la posición del fragmento), luego elimina y vuelve a hacer upsert solo los fragmentos del documento modificado. Pinecone y Qdrant admiten este patrón de forma nativa. Evita la reindexación completa en cada actualización; con 50,000 fragmentos eso cuesta $0.50 cada vez.


Más sobre patrones agénticos que extienden los sistemas RAG en la guía de configuración de agentes de AI Weekly. Consigue AI Weekly gratis, 3 ediciones por semana, leídas por más de 40,000 profesionales.