METRO Markets: Rebuilding Search Relevance for a Six-Market Wholesale Marketplace
- Seed
- PoC
- MVP
- Production
- Chasing perfect
A year-long search-quality program for METRO Markets, a wholesale marketplace serving hotels, restaurants and cafes across six countries. Working with their team, we moved its keyword search (which matched the words people typed by their letters, missing the meaning) to a hybrid engine that also searches by meaning, added a language model that reads each query, and built a way to test every change before it ships. The lasting win: far fewer dead-end searches, and a testing setup the METRO Markets team now runs to keep improving search.
Six markets on keyword search, with room to improve
Keyword search missed the meaning
METRO Markets sells to hotels, restaurants and cafes across six countries, each with its own catalog in its own language. Search ran on keyword matching: the engine (Elasticsearch) looked for the exact words people typed, propped up over the years with a synonym list the team maintained by hand, near-spelling matches and typo correction.
Because it matched words by their letters, it could miss meaning, intent and synonyms, the kind of gap keyword-only search tends to leave. On a review of real traffic, about a quarter of queries came back with no results, which set the opportunity. A hand audit of the problem queries split the causes roughly in half: the data (wrong categories, the wrong language in a field, missing attributes) and the engine itself (no sense of meaning, near-spelling matches that misfired).

Finetuned CLIP beside BM25, fused with RRF
Hybrid retrieval, keyword and meaning
To close that gap, we worked with the METRO Markets team to make retrieval hybrid: it now searches by meaning as well as by words. A multilingual AI model (a finetuned CLIP model) turns each product and each query into a list of numbers that captures its meaning, an embedding. Items with nearby numbers are close in meaning.
Those embeddings live in the search index (Elasticsearch) beside the old word index, and the two result lists are merged so anything ranked high by either method rises to the top (reciprocal rank fusion). Building them for the whole catalog, more than a million items, ran on ordinary CPUs over a weekend, with no costly GPUs.
A cutoff then drops the weakest matches (a similarity threshold), so the top results stay clean, at the cost of missing a few borderline items.
- 01 Embed the catalog with finetuned multilingual CLIP
- 02 Index dense vectors in Elasticsearch, beside BM25
- 03 Retrieve: keyword (BM25) and vector kNN
- 04 Fuse with reciprocal rank fusion
- 05 Read the query with a language model, map to categories
- 06 Gate on the eval loop, then A/B
Stack

A frozen labelled set, real metrics, a logged registry
Nothing ships unless it is measured
The evaluation loop is what makes a change trustworthy. We freeze a fixed set of test searches: the most common ones, a few rare ones, and known failure cases. Domain experts then grade each result for each search from 0 (irrelevant) to 3 (a perfect match).
Every candidate model is scored on that set with the standard relevance measures: nDCG, which rewards putting the best matches near the top, with precision and recall alongside. A language model gives fast first-pass grades, and the expert grades stay the final word.
Every experiment lands in a log with its goal, a plain verdict, and a blunt note on what got worse. Weak gains are called noise and logged as such. Only a setup that wins this offline test reaches a live A/B test, where half the users see the new version and half the old.

A language model pulls out intent and maps it to the catalog
Understanding the query
Retrieval finds candidate products, but a short wholesale query still carries intent that keywords miss. So a language model reads each query and pulls out the meaningful parts: the brand, the size, the attributes, the product type. It works even for searches the store does not stock, which still need to land somewhere sensible.
That model also matches the query against the catalog's full category tree (its hierarchy of product categories) and returns a short list of the most likely ones, which powers a separate browse-and-navigate surface. One model covers all six countries and their languages, and answers are cached (stored and reused), so repeat searches stay fast and cheap.

Some queries need a different tool
Where it still breaks
Not every query needs meaning search. A bare model code, a string of letters and digits, has nothing to interpret, so the system routes it straight to exact matching. For codes that is the right tool, and meaning search would only add noise.
Searching by photo is the genuinely hard one. It helps for broad visual queries, but it cannot read a model number or an exact spec, and it confuses look-alike products. So it earns a place as an extra, though it cannot carry search on its own.
Meaning search closed much of the gap. What remains, the system hands to the right tool for each query: exact matching for codes, meaning and keyword search for everything else. The work continues where it counts: getting the right items found and the query understood.

The wins, and a team that can keep going without us
What METRO Markets runs now
The concrete wins are in the search itself. Far fewer searches dead-end, since queries that once came back empty now resolve. The query-reading layer added a browse-and-navigate surface that did not exist before, and the cutoff on weak matches keeps the top results clean.
The most durable win is the capability we handed over: the fixed test set, the experiment log and the A/B setup. The METRO Markets team can now check a change against the test set, ship it, and keep improving search quality without us. One AI model across all six markets keeps the upkeep low.
Who built this
From the Lab
