Sistema RAG

Fusiono BM25 y búsqueda vectorial en vez de elegir uno.

Trabajo
Búsqueda híbrida sobre un catálogo de precios
Rol
Diseño de la arquitectura y construcción
Periodo
2025 — 2026
  • Búsqueda híbrida
  • RAG
  • MCP
  • FastAPI

El encargo

Un catálogo de 73 productos con 537 fechas y 37,893 filas de precios, y un equipo que preguntaba por él en lenguaje natural. La búsqueda por palabra clave fallaba en cuanto la consulta mezclaba un producto con un periodo. Diseñé y construí el sistema completo: indexación, recuperación, evaluación y la superficie por la que se consume.

Cómo está construido

La búsqueda por palabra clave fallaba en las consultas que mezclaban producto y periodo, y la puramente vectorial perdía los códigos exactos. Fusiono las dos con Reciprocal Rank Fusion y evalúo el resultado contra un gold set de 32 casos que redacté yo, de los que 29 puntúan para recall.

El sistema expone 8 herramientas por un servidor MCP y 13 rutas por FastAPI, sobre un dominio de 73 productos, 537 fechas y 37,893 filas de precios.

Una advertencia

Este sistema no es el buscador de esta página. El de aquí lo escribí para este sitio y es mucho más chico: 39 pasajes contra 9,125 fragmentos, y sin piso determinista. Ya tiene gold set propio, de 26 preguntas, y sus cifras están más abajo en la portada. PrecioVivo corre sobre un catálogo de precios, no sobre mi CV.

Medida, fuente sin publicar: salida de la evaluación del gold set1.00recall@1029 de 29 casos perfectos, con el embebedor real jina-embeddings-v3 a 256 dimensiones. El piso determinista solo, sin búsqueda, ya alcanza 1.00: este número no es mérito de la fusión
Medida, fuente sin publicar: salida de la evaluación del gold set0.816MRREl mismo gold set, granularidad semanal. El grano mensual da 0.955 y se descartó igual, porque promedia 29 días de evidencia contra 5
Medida, fuente sin publicar: script de indexación9,125fragmentos73 productos, 537 fechas, 37,893 filas
chunk_3311 chunk_3295 chunk_3357
LA PREGUNTAprecio de P-065 en marzoBM25palabras exactasVECTORIALsignificadoRRFfusiona los dos1P-070·marzo2P-067·marzo3P-066·marzo4P-065·marzo5P-004·marzo6P-006·marzo1P-065·marzo2P-065·083P-065·104P-065·septiembre5P-065·junio6P-065·111P-065·marzo2P-070·marzo3P-066·marzo4P-067·marzo5P-065·086P-065·104.º → 1.ºclaro = coincide con la pregunta, gris = no coincide
LA PREGUNTAprecio de P-065 en marzoBM25palabrasVECTORsignificadoRRFfusion1070·mar2067·mar3066·mar4065·mar5004·mar1065·mar2065·083065·104065·sep5065·jun1065·mar2070·mar3066·mar4067·mar5065·084.º → 1.ºclaro coincide, gris no
Un índice vectorial, visto de cerca. 1,334 de 9,125 puntos con la estructura de agrupación que tiene un catálogo real, proyectados con t-SNE. Los vectores son un sustituto, no embeddings reales: esto demuestra la técnica, no mide un sistema. La búsqueda por coseno sobre ellos sí es real, y los tres marcados son su argmax.BM25 acierta el mes y falla el producto. La vectorial acierta el producto y falla el mes. De sus 6 primeros comparten 1: P-065 · marzo, la respuesta. Por eso RRF la deja 1.º, cuando era 4.º para una y 1.º para la otra.

Dónde se rompe

Medida, fuente sin publicar: la corrida de evaluación con el embebedor real

Papaya devuelve papa, y no lo arreglé en recuperación

Dónde y por qué

Preguntar por un producto que no está en el catálogo devuelve el más parecido por nombre. Papaya puntúa 0.6444 y papa 0.6656: dos centésimas. Probé el umbral obvio y no funciona, porque cualquier corte que las separe mata las preguntas agregadas, que puntúan 0.5151. Lo resolví avisando al modelo desde el filtro léxico, que ya sabía que ninguna palabra coincidía con el catálogo. La evaluación sigue reportando las dos violaciones: no relajé el gold set.

Medida, fuente sin publicar: el gold set completo

El recall@10 vale dentro del dominio indexado

Dónde y por qué

El gold set son 32 casos que redacté yo sobre 73 productos y 537 fechas. Es una muestra pequeña y de autor único: sirve para detectar regresiones, no para afirmar que el sistema generaliza.