I fuse BM25 and vector search instead of picking one.
- Work
- Hybrid search over a price catalogue
- Role
- Architecture and build
- Period
- 2025 — 2026
- Hybrid search
- RAG
- MCP
- FastAPI
A catalogue of 73 products across 537 dates and 37,893 price rows, and a team asking about it in plain language. Keyword search failed the moment a query mixed a product with a period. I designed and built the whole system: indexing, retrieval, evaluation, and the surface it is consumed through.
Keyword search failed on queries mixing a product with a period, and pure vector search lost exact codes. I fuse both with Reciprocal Rank Fusion and evaluate the result against a gold set of 32 cases I wrote myself.
The system exposes 8 tools over an MCP server and 13 routes over FastAPI, across a domain of 73 products, 537 dates and 37,893 price rows.
This system is not the search on this page. The one here I wrote for this site and it is far smaller: 39 passages against 9,281 chunks, and no deterministic floor. It does now have a gold set of its own, 26 questions, and its figures are further down the home page. PrecioVivo runs over a price catalogue, not over my CV.
Papaya returns potato, and I did not fix it in retrieval
Asking for a product that is not in the catalogue returns the closest one by name. Papaya scores 0.6444 and potato 0.6656: two hundredths apart. I tried the obvious threshold and it does not work, because any cut that separates them kills the aggregate questions, which score 0.5151. I solved it by warning the model from the lexical filter, which already knew no word matched the catalogue. The evaluation still reports both violations: I did not relax the gold set. ↗
recall@10 holds inside the indexed domain
The gold set is 32 cases I wrote myself over 73 products and 537 dates. It is a small, single-author sample: it catches regressions, it does not prove the system generalises. ↗