Qué es un sistema RAG y por qué importa
Antes de entrar en la parte técnica, conviene entender qué es un sistema RAG y por qué se ha convertido en un estándar en proyectos de inteligencia artificial aplicada a negocio. Conocer su definición, cómo se diferencia de un modelo tradicional y qué beneficios aporta a una empresa permitirá comprender mejor los pasos que veremos más adelante.
Definición de RAG (Retrieval-Augmented Generation)
Un sistema RAG combina dos componentes principales: la recuperación de información y la generación de texto. En lugar de depender solo de lo que sabe un modelo de lenguaje, el sistema busca en una base de conocimiento externa los fragmentos más relevantes y los entrega al modelo como contexto. El modelo, a partir de esa información, genera una respuesta más precisa y fundamentada.
En la práctica, esto significa que el modelo no “inventa” respuestas, sino que se apoya en datos actualizados y controlados por la organización. Esa es la gran diferencia respecto a una simple llamada a un LLM: el sistema se nutre de información curada y específica para cada caso de uso.
Diferencias frente a un modelo LLM tradicional
Un LLM tradicional responde en base a lo que aprendió en su entrenamiento, sin acceso a fuentes externas en tiempo real. Esto implica que puede devolver información desactualizada o incompleta. En cambio, un sistema RAG amplía sus capacidades al consultar documentos propios de la empresa, bases de datos o repositorios internos.
La diferencia práctica es clara: mientras un modelo solo responde “desde su memoria”, un RAG actúa como un consultor informado que primero busca y luego responde con mayor precisión. Esto lo hace mucho más fiable en entornos corporativos donde la exactitud es crítica.
Beneficios para empresas y casos prácticos
Implementar un sistema RAG aporta ventajas tangibles:
- Respuestas más precisas: al basarse en documentos actualizados, reduce errores y alucinaciones.
- Adaptación al negocio: puedes entrenarlo con tus propios manuales, políticas o bases de conocimiento.
- Ahorro de tiempo: empleados y clientes obtienen información rápida sin revisar manualmente documentos.
- Escalabilidad: un RAG bien diseñado puede crecer con la organización, incorporando nuevas fuentes de datos.
En empresas, los casos de uso más habituales son el soporte al cliente, la consulta de documentación técnica, la gestión de RRHH (como políticas internas o procesos de contratación) y la automatización de informes. Todos ellos comparten un objetivo común: transformar un LLM genérico en un sistema alineado con las necesidades de negocio.
Crea modelos de IA que marquen la diferencia
Adquiere las habilidades clave para construir sistemas inteligentes. Domina técnicas avanzadas para destacar en el sector tecnológico.
Preparativos antes de crear tu sistema RAG
Antes de empezar a escribir código es fundamental preparar el entorno de trabajo y asegurar que dispones de los requisitos técnicos necesarios. Una buena configuración inicial evita errores comunes y facilita que el desarrollo sea fluido y seguro.
Requisitos técnicos y librerías necesarias (LangChain, OpenAI, FAISS u otras)
Para construir un sistema RAG se necesitan unas bases mínimas:
- Python 3.9 o superior como lenguaje principal.
- Entorno virtual para aislar dependencias del proyecto.
- Librerías clave:
openaipara interactuar con la API de OpenAI.langchainpara gestionar el flujo de recuperación y generación.- Un almacén vectorial como FAISS, Chroma o Milvus para guardar embeddings y hacer búsquedas.
De forma opcional, se pueden añadir librerías de soporte como dotenv para gestionar claves de forma segura o tiktoken para controlar el uso de tokens.
Configuración del entorno de desarrollo
Lo más recomendable es trabajar en un entorno virtual, por ejemplo con venv o conda. Esto permite instalar dependencias específicas sin interferir con otros proyectos. Un editor ligero como VS Code es suficiente, aunque también puedes optar por Jupyter Notebook o Colab si prefieres un enfoque más interactivo.
En mi experiencia, iniciar el proyecto con un archivo requirements.txt facilita replicar la instalación en otros equipos y mantener consistencia en el desarrollo.
Buenas prácticas de seguridad y gestión de credenciales
La clave de la API de OpenAI es un dato sensible y nunca debe quedar expuesta en el código. Para evitar riesgos:
- Guarda la clave en un archivo
.envy cárgala con librerías comopython-dotenv. - Usa claves diferentes para entornos de desarrollo, pruebas y producción.
- Si trabajas en una empresa, integra un gestor de secretos como AWS Secrets Manager, HashiCorp Vault o Azure Key Vault.
De esta forma, tu sistema RAG será más seguro desde el primer momento y reducirá las posibilidades de fuga de información confidencial.
Paso 1: Preparar la base de conocimiento
Todo sistema RAG necesita una base de conocimiento sólida que funcione como la fuente de verdad a la que recurrirá el modelo. Cuanto más limpia, organizada y relevante sea la información que cargues, más fiables serán las respuestas generadas.
Selección y carga de documentos de referencia
El primer paso es elegir los documentos que formarán parte de tu RAG. Pueden ser manuales internos, artículos técnicos, políticas de recursos humanos, informes financieros o cualquier otro material útil. Lo importante es que sean fuentes oficiales, actualizadas y relevantes para el caso de uso.
Una vez definidos, los documentos deben cargarse en tu proyecto en formatos estándar como TXT, PDF o CSV. LangChain ofrece utilidades para leer y procesar muchos de estos formatos sin necesidad de trabajo manual adicional.
Preprocesamiento de datos: limpieza y fragmentación de textos
Los modelos no trabajan bien con textos demasiado largos. Por eso, los documentos deben dividirse en fragmentos (chunks) de tamaño manejable, normalmente entre 500 y 1.000 tokens. Antes de fragmentar, conviene limpiar el texto eliminando elementos innecesarios como cabeceras repetidas, pies de página o caracteres especiales.
En mi experiencia, dedicar tiempo a esta limpieza inicial marca la diferencia: un corpus más consistente se traduce en resultados más precisos.
Creación de embeddings y almacenamiento en un vector store
Una vez fragmentados, cada bloque de texto se transforma en un embedding, es decir, una representación numérica que captura su significado semántico. OpenAI ofrece modelos de embeddings optimizados que funcionan muy bien con LangChain.
Estos embeddings se almacenan en un vector store, como FAISS, Chroma o Milvus. Este componente permite realizar búsquedas semánticas rápidas y devolver los fragmentos más relevantes cuando el usuario hace una consulta. En esencia, el vector store es el “cerebro auxiliar” del sistema RAG.
Paso 2: Conectar LangChain con OpenAI
Con la base de conocimiento preparada, el siguiente paso es enlazarla con un modelo de lenguaje que pueda generar respuestas a partir de los fragmentos recuperados. Aquí es donde entran en juego LangChain y la API de OpenAI.
Configuración de la API y modelos disponibles
Para usar la API de OpenAI necesitas tu clave privada, que se puede gestionar de forma segura con un archivo .env. Una vez configurada, podrás acceder a los modelos más recientes como GPT-5, que destaca por su capacidad de razonamiento y su eficiencia en tareas complejas. Para entornos de prueba también puedes usar modelos más ligeros como gpt-4.1 o gpt-4.1-mini, que resultan más económicos.
La elección depende del caso de negocio: un prototipo puede funcionar con un modelo pequeño, mientras que una aplicación en producción debería optar por GPT-5 para maximizar fiabilidad.
Construcción del pipeline básico de RAG en LangChain
LangChain actúa como orquestador entre el modelo y la base de conocimiento. El pipeline básico de un sistema RAG con LangChain sigue este flujo:
- El usuario realiza una pregunta.
- El sistema busca en el vector store los fragmentos más relevantes.
- LangChain combina esos fragmentos con la consulta original.
- El modelo de OpenAI genera una respuesta fundamentada en la información recuperada.
Este proceso se configura con pocos bloques de código y constituye la base sobre la que añadiremos mejoras más adelante.
Primer “hola mundo” de recuperación y respuesta
La mejor manera de validar la conexión es hacer una prueba simple: lanzar una consulta al sistema y comprobar que el modelo responde utilizando datos de la base cargada. Aunque sea un ejemplo básico, te permitirá confirmar que la integración entre LangChain, OpenAI y el vector store funciona correctamente y ya puedes avanzar hacia casos de uso más avanzados.
# RAG "hola mundo" con LangChain + OpenAI + FAISS
# pip install langchain langchain-openai langchain-community faiss-cpu python-dotenv
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
load_dotenv()
llm = ChatOpenAI(model="gpt-5", temperature=0) # modelo recomendado
emb = OpenAIEmbeddings(model="text-embedding-3-large")
# 1) Corpus mínimo (en producción: carga de ficheros)
docs_raw = [
{"page_content": "La política de vacaciones permite 23 días laborables al año.", "metadata": {"tema": "RRHH"}},
{"page_content": "Para restablecer contraseña, usa el portal interno IT y 2FA.", "metadata": {"tema": "IT"}}
]
# 2) Split + indexación
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents([
type("Doc", (), d)() for d in [{"page_content": d["page_content"], "metadata": d["metadata"]} for d in docs_raw]
]) # crea objetos con atributos page_content/metadata
vs = FAISS.from_documents(chunks, emb)
retriever = vs.as_retriever(search_kwargs={"k": 3})
# 3) Cadena RAG básica (stuff)
prompt = ChatPromptTemplate.from_messages([
("system", "Eres un asistente conciso. Usa EXCLUSIVAMENTE el contexto proporcionado para responder."),
("human", "Pregunta: {input}\n\nContexto:\n{context}")
])
stuff_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, stuff_chain)
# 4) Consulta de prueba
q = "¿Cuántos días de vacaciones tenemos?"
resp = rag_chain.invoke({"input": q})
print(resp["answer"])
Paso 3: Mejorar la recuperación de información
Un sistema RAG solo es tan bueno como la calidad de la información que recupera. Si la búsqueda devuelve fragmentos poco relevantes, las respuestas del modelo serán menos útiles. Por eso es clave optimizar la forma en que almacenamos y consultamos los embeddings.
Estrategias de indexación y búsqueda (FAISS, Chroma, Milvus)
El vector store es el corazón de la recuperación. Existen varias opciones, entre las que destacan:
- FAISS: desarrollado por Meta, muy eficiente en búsquedas vectoriales y ampliamente utilizado.
- Chroma: pensado para integrarse de forma sencilla con LangChain.
- Milvus: orientado a entornos de alta escala, con soporte para grandes volúmenes de datos.
La elección dependerá de tus necesidades: para prototipos pequeños basta con Chroma, mientras que proyectos empresariales suelen optar por FAISS o Milvus.
Técnicas para aumentar la relevancia de los resultados
No basta con guardar y buscar: también se pueden aplicar técnicas adicionales para afinar resultados:
- Normalización de texto: limpiar tildes, mayúsculas y caracteres especiales antes de generar embeddings.
- Re-ranking: aplicar un modelo adicional que ordene los resultados según su relevancia real.
- Filtros por metadatos: usar etiquetas como fechas, categorías o departamentos para limitar la búsqueda.
Estas técnicas permiten que el sistema devuelva información más ajustada al contexto de la consulta.
Ejemplo práctico de consulta con resultados optimizados
Imagina que cargas en tu RAG un conjunto de manuales técnicos. Si un usuario pregunta “¿cómo restablecer la contraseña en el sistema interno?”, el vector store devolverá varios fragmentos relacionados. Al aplicar filtros por metadatos (por ejemplo, “documentación de IT”), el sistema prioriza las instrucciones correctas y evita ruido de otros documentos. Esto se traduce en una respuesta más rápida y precisa.
# Recuperación optimizada: MMR, filtros por metadatos y top-k
# pip install langchain langchain-openai langchain-community faiss-cpu
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
# Suponiendo que ya tienes 'vs' creado (FAISS con embeddings)
# 1) Re-ranking por MMR para diversidad de resultados
retriever_mmr = vs.as_retriever(search_type="mmr", search_kwargs={"k": 5, "fetch_k": 20, "lambda_mult": 0.5})
# 2) Búsqueda con puntuación para inspección rápida
query = "Política de vacaciones"
docs_scores = vs.similarity_search_with_score(query, k=4)
for d, score in docs_scores:
print(f"Score={score:.4f} | Texto={d.page_content[:60]}...")
# 3) Filtro por metadatos (ejemplo: solo documentos de RRHH)
# Nota: FAISS puro no indexa metadatos para filtrar. En repositorios grandes usa vectorstores con filtros (p. ej., Chroma/Milvus).
# Aquí simulamos un filtro previo en memoria:
docs_rrhh = [d for d, _ in docs_scores if d.metadata.get("tema") == "RRHH"]
for d in docs_rrhh:
print("RRHH ->", d.page_content[:80], "...")
Paso 4: Añadir memoria y contexto al sistema
Un sistema RAG básico es capaz de recuperar información y generar respuestas, pero puede quedarse corto en interacciones largas. Para que las respuestas mantengan coherencia a lo largo de la conversación, necesitamos añadir mecanismos de memoria y gestionar el contexto de forma inteligente.
Cómo mantener coherencia en interacciones largas
La memoria permite que el sistema recuerde información compartida previamente por el usuario y la use en respuestas posteriores. Por ejemplo, si en un primer turno el usuario indica que trabaja en el departamento de marketing, el agente debería recordarlo en las siguientes consultas sin necesidad de repetirlo. Esto mejora la experiencia y la naturalidad de la conversación.
No obstante, mantener coherencia no significa guardar absolutamente todo. Es recomendable aplicar reglas de filtrado para evitar que se acumulen datos irrelevantes o redundantes. En entornos empresariales, la clave está en decidir qué merece conservarse y durante cuánto tiempo. Con esta estrategia el sistema mantiene el foco y reduce el riesgo de mezclar información innecesaria.
Limitaciones de contexto y cómo mitigarlas
Los modelos de lenguaje tienen un límite en el número de tokens que pueden procesar. Si cargamos demasiado contenido en cada interacción, corremos el riesgo de superar ese límite y perder coherencia. Para evitarlo, se aplican técnicas como:
- Resúmenes dinámicos: condensar la conversación pasada en versiones más breves.
- Recuperación selectiva: elegir solo los fragmentos más relevantes para cada turno.
- Segmentación del diálogo: separar temas distintos y tratar cada uno de forma independiente.
Uso combinado de memoria + recuperación externa
El enfoque más eficaz suele ser híbrido: usar memoria para retener datos inmediatos de la conversación y combinarla con recuperación desde el vector store para mantener la información actualizada. Así, el sistema puede responder con precisión en interacciones largas sin perder de vista las fuentes oficiales. Este equilibrio convierte al RAG en una herramienta más robusta y lista para entornos empresariales.
En la práctica, esto se traduce en un agente que recuerda los datos relevantes del usuario (como su rol o preferencias) y que al mismo tiempo consulta documentos corporativos cuando se requiere información especializada. Esta combinación potencia la utilidad del sistema y lo convierte en una solución mucho más versátil para procesos críticos dentro de la organización.
# Memoria + RAG con LCEL: historial por sesión con RunnableWithMessageHistory
# pip install langchain langchain-openai langchain-community faiss-cpu
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains import create_retrieval_chain
llm = ChatOpenAI(model="gpt-5", temperature=0)
prompt = ChatP