← all work

Ariadne

A product search engine. Led the rewrite from hard filtering to soft filtering with weighted ranking, added ML-driven image similarity for vector search, and held the system to explicit p90 latency budgets that scale by manufacturer count.

21%
search accuracy lift
1.5s
p90 (top 50)
mounting weight
3
match-strength buckets

The problem

Hard filtering loses good results. If a customer's spec calls for a 4-inch mounting and the closest available product has a 4.25-inch mounting, hard filters drop it from the response — even though it's the right answer for that buyer 90% of the time. The previous Product Finder did this constantly, and search OKR metrics showed the cost: customers gave up early or fell back to manual catalogs.

The rewrite replaces hard filters with a soft-filtering ranker that surfaces strong matches first, weaker matches behind them, and never silently throws away a candidate. Plus ML-driven image similarity for queries where text alone misses.

Architecture

Search pipeline
Query + buyer ctx Filter parser soft constraints ES query builder + vector search Match scorer Strong / Med / Weak Ranker 5× / 2× / 1× Results + cost range de-duped, with inv data
One pass through the index. Soft filters never drop candidates — they only rank them.

Three Core Decisions

1. Soft filters, never hard drops

Filters declare preferences with weights, not gates. A 4-inch mounting requirement scores a 4-inch product highest, a 4.25-inch product slightly lower, and a 6-inch product lowest — but all three appear in the result set, ordered. The buyer keeps control instead of the index silently editing their query.

2. Weighted ranking by attribute meaning

Not all attribute matches are equal. Mounting size mismatches almost always matter, so it weighs . Application (commercial / residential / industrial) matters often, so it weighs . Other attributes weigh each. The weights are tunable per category and were calibrated against existing customer-spec data, not guessed.

Ranking weights
Mounting match
Application match
Other attributes
Weights are per-attribute multipliers stacked on the underlying ES score.

3. Match-strength buckets surfaced to the UI

Soft filtering only works if the buyer can see match quality. Each result is bucketed Strong / Medium / Weak based on how many of the high-weight attributes match. The PF card shows the bucket as a chip, so a Weak match never gets confused with a Strong one — even though both appear in the response.

Latency budgets — explicit and per-tier

A flat p90 budget breaks down once the manufacturer set a customer is searching against varies from 50 to 1000+. So the budgets are tiered against the size of the candidate set:

p90 latency targets by manufacturer count
Top 50 mfrs
≤ 1.5 s
100 mfrs
≤ 3 s
1000+ mfrs
≤ 6 s
Held in production via a separate latency-improvements workstream; p90 measured continuously and surfaced on internal latency dashboards.

ML image similarity — vector search alongside text

Buyers often have a photo or datasheet snippet but don't know the exact text query. We added an image-similarity vector index on top of Elasticsearch / OpenSearch — the system encodes the query image, runs k-NN against the indexed catalog vectors, and merges the result set with the text-side soft-filtered results. Net effect: 21% improvement in search accuracy on the OKR test set.

Datasheet de-duplication

Products from different manufacturers often share the same underlying datasheet. Without de-duplication, the same logical product surfaces 3–4 times in a result set under different SKUs, hurting both relevance and the latency budget. The de-dup layer runs at index time, not query time — datasheet hashes are computed and consolidated cost / lead-time onto the canonical key, so the query path stays clean.

Stack