Lección 13 de 16 · Nivel 4: Experto
RAG: cómo hacer que la IA responda con los documentos de tu empresa
- ⏱ 11 min de lectura
- ❓ 3 preguntas de repaso
- ✍️ Ejercicio con solución
En esta lección
- Entender por qué la IA no conoce los datos de tu empresa y las tres formas de dárselos.
- Explicar qué es RAG (generación aumentada por recuperación) y qué son los embeddings.
- Construir en Python un buscador de documentos y un prompt que responda solo con esa información.
- Evaluar un asistente con documentos y evitar sus fallos más comunes.
Bienvenido al Nivel 4: Experto. Ya sabes usar la IA, crear asistentes, automatizar y llamarla desde Python. En este nivel construirás soluciones que las empresas pagan bien: asistentes que responden con tus propios documentos, chatbots de atención al cliente y herramientas programadas con ayuda de la IA. Cerraremos con cómo convertir todo esto en ingresos. Empezamos por la técnica más usada en la IA empresarial: RAG.
El problema: la IA no conoce tu empresa
Un modelo de lenguaje aprendió de textos públicos hasta cierta fecha (lección 2). No sabe cuál es tu política de devoluciones, el horario de tu local nuevo ni lo que dice el contrato con tu proveedor. Si le preguntas, puede inventar una respuesta convincente. Hay tres formas de darle ese conocimiento:
| Opción | Cómo funciona | Cuándo usarla |
|---|---|---|
| Pegar el documento en la conversación | El texto completo entra en la ventana de contexto | Pocos documentos y consultas puntuales |
| Proyectos o asistentes con archivos (lección 8) | Subes documentos una vez y la herramienta los consulta en cada conversación | Un equipo pequeño, sin programar |
| RAG | Un sistema busca los fragmentos relevantes entre miles de documentos y solo esos se envían al modelo | Muchos documentos, que cambian, integrados en tu web, tu app o tu chatbot |
Muchas herramientas de "proyectos" y bases de conocimiento usan RAG por dentro. Entender cómo funciona te permite configurarlas mejor y, si sabes Python, construir la tuya.
Cómo funciona RAG en cuatro pasos
- Dividir: los documentos se cortan en fragmentos de uno o pocos párrafos (en inglés, chunks).
- Indexar: cada fragmento se convierte en una representación que permite buscarlo rápido.
- Recuperar: cuando llega una pregunta, se buscan los fragmentos más parecidos.
- Generar: se envían al modelo la pregunta y esos fragmentos, con la instrucción de responder solo con ellos y citar la fuente.
¿Qué son los embeddings?
Un embedding es una lista de números (un vector) que representa el significado de un texto. Textos con significado parecido tienen vectores cercanos, aunque no compartan palabras: "¿puedo devolver un café?" y "política de devoluciones" quedan cerca. Los proveedores de IA y varias bibliotecas abiertas ofrecen modelos de embeddings, y las bases de datos vectoriales los guardan y buscan entre millones en milisegundos.
1. ¿Qué se envía al modelo de lenguaje en un sistema RAG?
RAG recupera lo relevante y lo agrega al prompt. No modifica el modelo, por eso basta actualizar los documentos para que las respuestas cambien.
Constrúyelo en Python
Vamos a crear el asistente de Café Aurora. Para que puedas ejecutar la parte de búsqueda sin claves ni costos, usaremos una técnica clásica de búsqueda por palabras, TF-IDF, incluida en scikit-learn (pip install scikit-learn). Después verás por qué los embeddings la superan.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
documentos = [
{"fuente": "politica-devoluciones.txt",
"texto": "Aceptamos devoluciones de productos envasados sin abrir dentro de los 15 días "
"posteriores a la compra, con el comprobante. Las bebidas preparadas no tienen devolución."},
{"fuente": "horarios.txt",
"texto": "El local de Miraflores abre de lunes a sábado de 7:00 a 21:00 y los domingos "
"de 8:00 a 14:00. El local de San Isidro cierra los domingos."},
{"fuente": "delivery.txt",
"texto": "Hacemos delivery en un radio de 5 km. El pedido mínimo es de 30 soles y el envío "
"cuesta 6 soles; es gratis en pedidos desde 80 soles."},
{"fuente": "programa-fidelidad.txt",
"texto": "Con la tarjeta Aurora acumulas un sello por cada bebida. Al completar 9 sellos, "
"la décima bebida es gratis. Los sellos vencen a los 6 meses."},
{"fuente": "alergenos.txt",
"texto": "Todos los postres pueden contener trazas de frutos secos, gluten y lácteos. Tenemos "
"leche de almendras y de avena como alternativa sin lactosa."},
]
PALABRAS_VACIAS = ["a", "al", "de", "del", "el", "en", "es", "la", "las", "lo", "los",
"me", "mi", "no", "o", "que", "se", "su", "un", "una", "y"]
vectorizador = TfidfVectorizer(stop_words=PALABRAS_VACIAS)
matriz = vectorizador.fit_transform([d["texto"] for d in documentos])
def buscar(pregunta, k=2, minimo=0.1):
sim = cosine_similarity(vectorizador.transform([pregunta]), matriz)[0]
orden = sim.argsort()[::-1][:k]
return [documentos[i] | {"score": round(float(sim[i]), 2)}
for i in orden if sim[i] >= minimo]
for p in ["¿Cuánto cuesta el envío a domicilio?",
"¿Abren el domingo en San Isidro?",
"¿Puedo devolver un café que no me gustó?"]:
print(p, [(d["fuente"], d["score"]) for d in buscar(p)])
¿Cuánto cuesta el envío a domicilio? [('delivery.txt', 0.3)]
¿Abren el domingo en San Isidro? [('horarios.txt', 0.25)]
¿Puedo devolver un café que no me gustó? []
Las dos primeras preguntas encuentran el documento correcto. La tercera no encuentra nada: la pregunta dice "devolver" y el documento dice "devoluciones" y "devolución", palabras distintas para una búsqueda por palabras. Este es exactamente el problema que resuelven los embeddings, que comparan significados. En un sistema real, reemplazarías el vectorizador TF-IDF por un modelo de embeddings y el resto del código seguiría igual. Aun así, fíjate en algo bueno: como ningún fragmento superó el mínimo, el sistema sabe que no sabe, en lugar de enviar un documento irrelevante.
El prompt que evita respuestas inventadas
def armar_prompt(pregunta):
fragmentos = buscar(pregunta)
if not fragmentos:
return None # nada relevante: derivar a una persona
contexto = "\n\n".join(f"[{f['fuente']}]\n{f['texto']}" for f in fragmentos)
return (
"Responde la pregunta del cliente usando SOLO la información de los documentos.\n"
"Si la respuesta no está en los documentos, di que no lo sabes y ofrece derivar "
"a una persona.\n"
"Al final, indica entre corchetes la fuente que usaste.\n\n"
f"<documentos>\n{contexto}\n</documentos>\n\n"
f"Pregunta: {pregunta}"
)
Y la llamada al modelo, igual que en la lección 10:
import anthropic
cliente = anthropic.Anthropic() # lee la clave de la variable de entorno
def responder(pregunta):
prompt = armar_prompt(pregunta)
if prompt is None:
return "No tengo esa información. ¿Quieres que te comunique con una persona del equipo?"
r = cliente.messages.create(
model="claude-sonnet-5-5", # consulta los modelos vigentes en la documentación
max_tokens=400,
messages=[{"role": "user", "content": prompt}],
)
return r.content[0].text
print(responder("¿Cuánto cuesta el envío a domicilio?"))
Una respuesta típica: "El envío cuesta 6 soles dentro de un radio de 5 km, con un pedido mínimo de 30 soles. Si tu pedido es de 80 soles o más, el envío es gratis. [delivery.txt]".
2. ¿Por qué el prompt pide citar la fuente?
Las citas permiten auditar las respuestas: si cita un documento que no dice eso, sabes que hay un problema que corregir.
Lo que hace bueno (o malo) a un RAG
- Calidad de los documentos: si la política está desactualizada o hay dos versiones contradictorias, el asistente responderá mal con total seguridad. Antes de construir, ordena y actualiza los documentos.
- Tamaño de los fragmentos: muy pequeños pierden el contexto; muy grandes mezclan temas. Uno o dos párrafos con su título suele funcionar bien.
- Permisos: si el asistente tiene documentos de recursos humanos, un empleado no debería poder preguntarle por el sueldo de otro. Filtra los documentos según quién pregunta.
- Privacidad: los fragmentos se envían al proveedor del modelo; revisa sus condiciones y tu política de uso (lección 12).
- Evaluación: prepara una lista de 20 a 50 preguntas reales con su respuesta correcta y pruébala cada vez que cambies algo.
3. Tu asistente responde con una política de devoluciones que cambió hace tres meses. ¿Cuál es la causa más probable?
En RAG, el modelo responde con lo que recupera. Mantener los documentos al día (y borrar las versiones viejas) es la tarea más importante.
Ejercicio práctico: tu set de evaluación
- Agrega dos documentos al asistente: uno sobre medios de pago y otro sobre reservas para eventos.
- Escribe 8 preguntas de prueba con la fuente esperada, incluidas dos cuya respuesta no esté en ningún documento.
- Haz una función que recorra las preguntas, compare la primera fuente recuperada con la esperada e imprima el porcentaje de aciertos.
Ver solución
pruebas = [
("¿Cuánto cuesta el envío?", "delivery.txt"),
("¿A qué hora abren los domingos en Miraflores?", "horarios.txt"),
("¿Los sellos de la tarjeta vencen?", "programa-fidelidad.txt"),
("¿Tienen leche de avena?", "alergenos.txt"),
("¿Aceptan pagos con Yape o tarjeta?", "medios-de-pago.txt"),
("¿Puedo reservar el local para un cumpleaños?", "reservas-eventos.txt"),
("¿Venden acciones de la empresa?", None), # no está: debe derivar
("¿Cuál es la contraseña del wifi?", None),
]
def evaluar(pruebas):
aciertos = 0
for pregunta, esperada in pruebas:
r = buscar(pregunta)
obtenida = r[0]["fuente"] if r else None
ok = obtenida == esperada
aciertos += ok
print("✓" if ok else "✗", pregunta, "→", obtenida)
print(f"Aciertos: {aciertos}/{len(pruebas)} ({aciertos / len(pruebas):.0%})")
evaluar(pruebas)
Los fallos te dirán qué mejorar: sinónimos que la búsqueda no entiende (pasa a embeddings), documentos mal redactados o un umbral mínimo demasiado alto o bajo. Repite la evaluación tras cada cambio para no arreglar una cosa y romper otra.
Resumen
- La IA no conoce tus documentos: puedes pegarlos, usar proyectos con archivos o construir un RAG.
- RAG divide, indexa, recupera los fragmentos relevantes y genera la respuesta solo con ellos.
- Los embeddings comparan significados; la búsqueda por palabras falla con sinónimos y variantes.
- Pide responder solo con los documentos, admitir cuando no sabe y citar la fuente.
- Documentos al día, permisos, privacidad y un set de evaluación hacen que un RAG sea confiable.
En la próxima lección usarás estas piezas para diseñar un chatbot de atención al cliente para WhatsApp o tu web: flujos, tono, derivación a personas y métricas.
Crea tu cuenta en 30 segundos, marca tus lecciones y descarga el certificado al terminar.