El modelo no miente, rellena huecos
Le preguntas a un LLM por una función de una librería que no existe y te la escribe entera, con firma, argumentos y un ejemplo de uso convincente. No hay maldad ni error de cálculo. El modelo hizo exactamente su trabajo: continuar el texto de la forma más plausible que conoce. Que esa continuación fuera falsa es un detalle que a él le da igual.
Ese es el malentendido de fondo con las alucinaciones. Las tratamos como un bug que aparece de vez en cuando, cuando en realidad son la cara B de cómo funciona un modelo generativo. Entenderlo cambia la estrategia: no intentas eliminar un fallo, acotas un comportamiento por defecto.
Por qué ocurre: plausibilidad, no verdad
Un LLM se entrena para una sola cosa: predecir el siguiente token dado lo anterior. No hay ningún módulo que compruebe si lo que va a decir es cierto. No tiene una base de datos interna que consultar ni una señal de “esto no me lo sé”. Lo que tiene es una distribución de probabilidad sobre palabras, y elige de ahí.
Cuando la respuesta correcta está bien representada en el entrenamiento, la continuación más probable coincide con la verdad y todo parece magia. Cuando no lo está —un dato de nicho, una API reciente, tu documentación interna— el modelo no se calla. Sigue siendo un generador de texto plausible, así que genera algo plausible. Y lo plausible se parece muchísimo a lo verdadero: por eso las alucinaciones son tan difíciles de pillar a simple vista.
Hay además un incentivo perverso en cómo evaluamos los modelos. La mayoría de benchmarks premian responder y penalizan igual una respuesta en blanco que una equivocada. Con esas reglas, adivinar siempre renta más que abstenerse, igual que en un examen tipo test sin puntos negativos. El modelo aprende a no dejar preguntas sin contestar, aunque no tenga ni idea.
Los tres sabores que verás en producción
No todas las alucinaciones son iguales ni se atacan igual. Distinguirlas ahorra tiempo.
| Tipo | Qué pasa | Dónde duele |
|---|---|---|
| Factual | Inventa un dato del mundo (fecha, cifra, cita) | Chatbots de conocimiento general |
| No fundamentada | Contradice o ignora el contexto que le diste | RAG mal montado |
| Fabricación de fuentes | Cita papers, URLs o funciones que no existen | Asistentes de investigación y de código |
La factual es la más conocida, pero en un sistema con RAG la que te va a morder es la segunda: le pasas los fragmentos correctos y aun así el modelo responde con lo que “cree recordar” en lugar de con lo que tiene delante. Y la tercera es especialmente traicionera en código, porque el ejemplo compila en tu cabeza hasta que lo ejecutas.
Lo que sí reduce las alucinaciones
No hay un interruptor, pero hay palancas que funcionan y se acumulan.
- Dale la respuesta, no confíes en su memoria. Un RAG bien montado es la mayor palanca: si el dato correcto está en el contexto, el modelo tiene mucho menos margen para inventar. La condición es que recuperes bien; basura recuperada es basura fundamentada.
- Ánclalo al contexto de forma explícita. Instruye al modelo a responder solo con lo que aparece en los fragmentos y a decir “no está en las fuentes” si no lo encuentra. Darle permiso para abstenerse es la mitad de la batalla.
- Baja la temperatura en tareas factuales. Con
temperature=0reduces la creatividad del muestreo. No elimina las alucinaciones, pero deja de sortear caminos improbables cuando lo que quieres es el dato exacto. - Exige citas verificables. Si cada afirmación tiene que apuntar a una fuente concreta, puedes comprobarla después de forma programática. Una cita que no existe es una alucinación que se delata sola.
- Verifica con una segunda pasada. Para lo crítico, un segundo paso que contraste la respuesta contra las fuentes atrapa buena parte de lo que se cuela. Cuesta tokens; a veces sale a cuenta.
Obligar al modelo a citar y verificarlo
La idea es sencilla: no te fíes de la prosa, fíate de las citas y compruébalas contra las fuentes que tú controlas. Pides salida estructurada con el índice del fragmento que respalda cada afirmación y descartas lo que no cuadre.
import json
import openai
client = openai.OpenAI()
def responder_con_citas(pregunta: str, fragmentos: list[str]) -> dict:
"""Responde citando el fragmento que respalda cada afirmación.
Cada cita es el índice de un fragmento real; así podemos verificarla.
"""
contexto = "\n".join(f"[{i}] {f}" for i, f in enumerate(fragmentos))
respuesta = client.chat.completions.create(
model="gpt-5-6",
messages=[
{
"role": "system",
"content": (
"Responde SOLO con lo que aparezca en los fragmentos. "
"Si el dato no está, di que no consta. "
"Devuelve JSON: {afirmaciones: [{texto, fuente}]} "
"donde 'fuente' es el índice del fragmento que la respalda."
),
},
{"role": "user", "content": f"{contexto}\n\nPregunta: {pregunta}"},
],
temperature=0,
response_format={"type": "json_object"},
)
datos = json.loads(respuesta.choices[0].message.content)
# Verificación: descartamos afirmaciones cuya fuente no existe
validas = [
a for a in datos["afirmaciones"]
if isinstance(a.get("fuente"), int) and 0 <= a["fuente"] < len(fragmentos)
]
return {"afirmaciones": validas, "descartadas": len(datos["afirmaciones"]) - len(validas)}
No es infalible: el modelo puede citar un fragmento que no dice lo que él afirma. Pero convierte una alucinación silenciosa en algo que puedes medir, registrar y, sobre todo, filtrar antes de que llegue al usuario.
Qué hacer el lunes
Empieza por medir. Coge veinte preguntas reales de tu dominio, incluye algunas cuya respuesta el modelo no puede saber, y cuenta cuántas veces se inventa algo en lugar de abstenerse. Ese número es tu línea base; sin él, cualquier mejora es una corazonada.
Después, ataca por orden de impacto: fundamenta con contexto lo que puedas, dale permiso explícito para decir “no lo sé” y exige citas en lo que sea verificable. No persigas el cero absoluto, porque no existe con esta tecnología. Persigue que, cuando el modelo no sepa algo, lo diga en vez de rellenarlo con algo bonito. Un asistente que se calla a tiempo vale más que uno que siempre tiene respuesta.
Fuentes
- Ji et al., “Survey of Hallucination in Natural Language Generation” (2022).
- Lin, Hilton y Evans, “TruthfulQA: Measuring How Models Mimic Human Falsehoods” (2021).