Inspiration

Every one of us has opened a shopping app and typed something vague like "running shoes" only to get overwhelmed by thousands of results that don't fit what we actually needed. The real problem isn't that we don't know what we want. It's that we discover what we want as we go, and most search systems treat every message as a brand new query, forgetting everything we said a moment ago. We wanted to build something that behaves more like a good salesperson: it listens, asks the right follow up question, and gets sharper with every answer instead of starting over.

What it does

Narrow is a conversational shopping agent that finds a specific product across a catalogue of 50,000 real apparel items, without ever using an LLM or an external API. Instead of asking you to write the perfect search query up front, it treats the problem as progressive narrowing. Each turn, it asks the single question most likely to shrink the pool of candidates, learns from your answer, and returns a ranked top 10 list. Over a few turns, thousands of products collapse down to the handful that actually match what you're looking for.

How we built it

We built the whole system on standard library Python with an in memory full text index, which indexes the entire catalogue in about 3 seconds. Every turn runs through four stages:

  1. Dialogue State classifies whether the shopper is still browsing or ready to buy, and detects when they change their mind so we drop outdated constraints.
  2. Retrieval turns the conversation so far into a weighted search query against the in memory index, falling back to longer phrase matching when needed.
  3. Ranking scores each candidate product on wording, category, and the constraints we've learned so far, using a rules based scoring system rather than a model.
  4. Next Question looks at what's still ambiguous in the results and decides the one question that would resolve the most uncertainty.

We tested against the organiser's evaluator, which simulates a shopper holding a hidden target product and only reveals requirements when asked. Running all 200 public sessions, our technical score rose from a baseline of 0.107 to 0.926, hit rate went from 0.125 to a perfect 1.0, mean reciprocal rank rose from 0.068 to 0.827, and the average number of turns needed to find the product dropped from 9.81 to 2.11.

Challenges we ran into

The hardest part wasn't building a search system, it was building one that knows what it doesn't know. Getting the agent to ask genuinely useful questions, instead of generic ones, meant constantly tuning how we measured "what's still ambiguous" in the candidate pool. We also had to be careful about shoppers changing their mind mid conversation. Early versions kept stale constraints around, which quietly tanked accuracy on some sessions until we added explicit intent and change detection to the dialogue layer.

What we learned

We learned that a lot of the value in conversational search comes from the questions, not just the ranking. A simple rules based ranker performed remarkably well once it was paired with a dialogue layer that asked the right thing at the right time. We also learned how much you can get out of a lightweight, model free system when the problem is framed well. No LLM calls, no API keys, and no internet connection turned out to be a feature, not a limitation.

What's next

Because the architecture doesn't depend on a model, we think it can scale to much larger catalogues and other domains beyond apparel, from electronics to home goods, wherever shoppers start out with a vague idea and narrow it down as they go.

Built With

Share this project:

Updates

Submission history