El lado de ingesta e indexado de un pipeline RAG
Yo construí la mitad de ingesta e indexado. Los comentarios estaban en el almacén analítico como datos crudos, así que el primer problema fue diseñar una nueva estructura para ellos: qué se convierte en documento, y para cada campo, si tenía que ser SimpleField, SearchableField, sortable, filterable o facetable. Ese esquema es sobre lo que corre todo lo que viene después. Construí un proceso batch para transformar los comentarios históricos e indexarlos, un proceso diario para seguir indexando los nuevos a medida que llegaban, y lancé una versión de prueba para que los clubes pudieran probarlo antes de abrirlo a todos.
PROBLEMA
Los clubes reciben miles de comentarios de texto libre por año, y leerlos todos es un trabajo para el que nadie tiene tiempo. El producto permite preguntar sobre ese feedback en lenguaje natural, lo cual solo funciona si primero se puede encontrar el puñado correcto de comentarios.
DECISIONES QUE DEFIENDO
Un club nunca puede ver los comentarios de otro
El aislamiento entre tenants empieza en el esquema, que fue mi mitad: el ID de cuenta es un campo filtrable en cada documento, así que una búsqueda se puede acotar a un solo club antes de rankear o devolver nada. Eso convierte al aislamiento en una propiedad del índice y no en una instrucción del prompt, y como el modelo no puede emitir una consulta propia, lo que le llega solo pueden ser documentos de un club.
El índice guarda el texto, no solo los IDs
Guardar el texto del comentario y de la pregunta en el índice es lo que lo hace un índice de búsqueda y no una tabla de lookup. Guardar solo IDs implicaría un segundo viaje a la fuente por cada resultado, y el ranking no tendría sobre qué rankear.
LO QUE CONSTRUÍ
- ▸El esquema del índice y su configuración semántica. La regla que apliqué: buscable solo donde el texto realmente se busca, filtrable donde algo acota una consulta, facetable solo donde la UI ofrece un desglose. Cada capacidad cuesta tamaño de índice, así que no las activás todas.
- ▸El pipeline que trae los comentarios del almacén analítico, enriquece cada uno con el contexto de su club y su pregunta, los deduplica y los empuja al índice.
- ▸Cargas por lotes para el backfill histórico: alrededor de mil documentos por lote, tres lotes corriendo en paralelo. Suficiente para mover mucha data, sin que los errores se vuelvan difíciles de razonar.
- ▸Reintentos con backoff exponencial, y rollback cuando sigue fallando: los documentos parciales se borran del índice y la marca de indexado del comentario queda sin valor, así una ejecución posterior lo vuelve a tomar. Una respuesta nunca queda indexada a medias.
- ▸Una función programada que mantiene buscables los comentarios nuevos, más la capa de suscripción y cuota de prueba y las APIs detrás de ella.
QUÉ FUE MÍO
Mío: el esquema del índice y su configuración semántica, la ingesta y la transformación, el indexador por lotes con reintentos y rollback, el refresco programado y la capa de cuota de prueba. No mío: el asistente en sí, los prompts, la UI de chat y el endpoint de consulta.
STACK