La mitad de las alucinaciones de un RAG son un índice desactualizado
El modelo respondió con fidelidad a los fragmentos que le pasó el retrieval, y esos fragmentos eran viejos. Tratar el índice vectorial como una caché y no como una construcción única evita buena parte del problema.

Buena parte de lo que en producción se registra como "el modelo alucinó" es, en realidad, un fallo de frescura. El modelo hizo su trabajo: se apoyó en lo que le devolvió la recuperación, y lo que le devolvió era antiguo. El índice vectorial es una caché del mundo, y como toda caché no falla dando error: sirve el pasado en silencio. El arreglo no está en el prompt, está en la tubería de datos.
Ese reencuadre importa porque cambia dónde se trabaja. Quien se pasa la semana ajustando instrucciones persigue un problema que no vive ahí; quien mira cuándo se verificó por última vez cada fragmento, sí.
La antigüedad no es un único fallo, son tres, y piden respuestas distintas. Contenido obsoleto: el documento sigue en origen, pero sus datos cambiaron (el precio, la política, la especificación) y el índice conserva el embedding del texto viejo. Contenido ausente: algo nuevo apareció en origen y nunca se rastreó, así que no es recuperable; el modelo pide contexto, no recibe nada útil y rellena el hueco como sabe. Contenido huérfano: el documento se retiró en origen y sigue en el índice, de modo que el modelo cita algo que ya no existe. Los tres nacen de lo mismo: el índice y el mundo se separaron y nadie se enteró.
Detectar el cambio en vez de re-embeddear todo
Re-rastrear y re-embeddear el corpus entero en cada ciclo es lento y caro, y empuja a espaciar los refrescos, justo lo contrario de lo que hace falta. El hash de contenido rompe la disyuntiva: se descarga la página, se normaliza (fuera plantillas, espacios homogéneos, fechas y precios en un formato estable) y se compara el sha256 con el guardado. Si coincide, la página cuesta una petición y ningún embedding: basta con actualizar la marca de verificación. Si no, se trocea, se embebe y se hace upsert.
La clave está en que los identificadores de fragmento sean deterministas, derivados de la URL y la posición, para que reindexar sobrescriba en lugar de acumular copias casi idénticas del mismo texto, que es una causa silenciosa de recuperación mala. Un upsert idempotente permite además borrar los fragmentos que ya no están en la página.
Un TTL distinto para cada fuente
Ninguna programación global acierta: va rápida de más para la documentación de referencia y lenta de más para precios o inventario. Lo razonable es asignar una política de frescura por fuente o por plantilla según su volatilidad, y gastar el presupuesto finito de rastreo e inferencia donde el contenido se mueve de verdad. El TTL de una página es una promesa sobre la peor antigüedad de lo que se va a servir desde ella, así que se fija en función del daño que hace una respuesta vieja.
Mantener el índice al día es solo la mitad. La otra es que la frescura llegue hasta la consulta: si cada fragmento viaja con su fecha de verificación y su origen, el retrieval puede descartar o degradar lo que ya pasó su vida útil antes de que el modelo lo lea. Es menos vistoso que afinar el prompt, pero es trabajo sobre infraestructura propia, y ahí sí se puede avanzar.

