El demo funcionaba
Todos hemos visto la misma película.
Montas un RAG en una tarde. Metes un PDF, haces una pregunta, el modelo responde con una cita perfecta. Lo enseñas en la reunión y alguien dice “esto lo cambia todo”. Subes a producción.
Y entonces, con datos reales y usuarios reales, el chatbot empieza a inventarse cosas con una seguridad pasmosa. Cita un artículo de una política que no existe. Mezcla el manual de 2022 con el de 2025. Responde con aplomo a una pregunta cuya respuesta no está en ningún sitio.
La conclusión fácil es “el modelo alucina”. Casi nunca es verdad. El modelo hace lo que sabe hacer: redactar de forma plausible con el contexto que le das. Si el contexto es malo, la respuesta es plausible y falsa. El fallo está antes del modelo, en la recuperación.
RAG en una frase
RAG (Retrieval-Augmented Generation) es buscar primero y redactar después. En vez de confiar en lo que el LLM memorizó durante el entrenamiento, le pasas fragmentos relevantes de tus documentos y le pides que responda solo con eso.
El truco está en ese “relevantes”. Toda la calidad del sistema se decide en el paso de búsqueda, no en el de redacción. Un GPT carísimo con fragmentos malos responde peor que un modelo modesto con fragmentos buenos.
Por qué falla la recuperación
Cuatro causas explican la mayoría de las alucinaciones que verás en producción.
El troceado destruye el sentido. Partir los documentos cada 500 caracteres a ciegas corta tablas por la mitad, separa una pregunta de su respuesta y deja fragmentos que, fuera de contexto, no dicen nada. El modelo recibe ruido y rellena los huecos por su cuenta.
Recuperas algo aunque no haya nada. Una búsqueda por similitud siempre devuelve los k fragmentos más cercanos, incluso cuando ninguno responde a la pregunta. Si no filtras por un umbral mínimo, le estás entregando al modelo el material menos malo y pidiéndole que haga magia.
Solo buscas por significado. Los embeddings capturan semántica, pero fallan con lo literal: un código de error, una referencia legal, el nombre exacto de un producto. “Error 0x80070057” no se parece semánticamente a nada.
El contexto está sucio o desactualizado. Si en tu índice conviven tres versiones del mismo manual, el modelo no sabe cuál es la buena. Y tú tampoco se lo has dicho.
Qué arreglar, y en qué orden
| Síntoma | Causa probable | Arreglo |
|---|---|---|
| Cita cosas que no existen | No filtras por relevancia | Umbral mínimo de score; si nada lo supera, responder “no lo sé” |
| Mezcla versiones | Índice con duplicados | Metadatos de versión y fecha; filtrar antes de buscar |
| Falla con términos exactos | Solo búsqueda vectorial | Búsqueda híbrida (vectorial + léxica BM25) |
| Responde a medias | Fragmentos descontextualizados | Trocear por estructura, no por longitud fija |
El orden importa. Antes de cambiar de modelo o de afinar el prompt, mira qué fragmentos está recibiendo. El 80 % de los problemas se ven ahí.
El cambio que más rinde: dejar que diga “no lo sé”
La mejora de mayor impacto y menor esfuerzo es filtrar por un umbral de relevancia y permitir explícitamente la no-respuesta.
def recuperar(pregunta, indice, k=5, umbral=0.75):
resultados = indice.buscar(pregunta, k=k)
# Quédate solo con lo que de verdad se parece a la pregunta
relevantes = [r for r in resultados if r.score >= umbral]
return relevantes
def responder(pregunta, indice, llm):
contexto = recuperar(pregunta, indice)
if not contexto:
return "No tengo información suficiente para responder a esto."
prompt = f"""Responde usando solo el contexto. Si el contexto no contiene
la respuesta, di que no lo sabes. No inventes.
Contexto:
{formatear(contexto)}
Pregunta: {pregunta}"""
return llm.generar(prompt)
Un chatbot que admite “no lo sé” parece menos impresionante en la demo y es infinitamente más útil en producción. La confianza de tus usuarios se construye con lo que el sistema no responde tanto como con lo que responde.
Mídelo, no lo intuyas
“A mí me funciona” no es una métrica. Monta un conjunto de 30 o 40 preguntas reales con sus respuestas correctas y, para cada una, comprueba dos cosas por separado: si la recuperación trajo el fragmento correcto, y si la redacción usó bien ese fragmento. Separar ambos pasos te dice exactamente dónde está el fallo en lugar de obligarte a adivinar.
Cuando una respuesta sea mala, la pregunta no es “¿por qué alucina el modelo?”, sino “¿tenía delante la información correcta?”. Casi siempre la respuesta es no.
En resumen
Un RAG que alucina no suele tener un problema de inteligencia, sino de dieta. Cuida el troceado, filtra por relevancia, combina búsqueda semántica y léxica, mantén limpio el índice y deja que el sistema reconozca sus límites. El modelo es la parte fácil; la recuperación es donde se gana o se pierde.