Inspiration

Shopping rarely begins with a perfect query. People start broadly, reveal constraints gradually, reject recommendations, or change direction completely. Conventional keyword search often treats each message in isolation, so shoppers repeat themselves or keep scrolling through stale results. We built Shopping Copilot to preserve that conversational intent and identify the exact catalog product sooner.

What it does

Shopping Copilot is a headless conversational retrieval agent for the official 50,000-product TechJam catalog. On every turn it returns a natural-language response, a structured clarification attribute, and up to ten unique catalog-valid product IDs.

The agent handles Buying, Browsing, Focused, and Intent Override behavior. It accumulates compatible evidence, respects explicit “no preference” answers, rotates previously rejected recommendations, and revokes stale constraints when the shopper changes direction. Broad requests receive a diverse shortlist and one high-information clarification; turn ten never asks another question.

How we built it

At startup, the agent normalizes nested and malformed catalog fields and builds three local retrieval structures:

  • field-weighted SQLite FTS5 over titles, categories, features, and details;
  • reliable structured facet maps for material, color, brand, category, and budget;
  • a 256-dimensional catalog-derived signed feature-hash index.

Evidence activates multiple retrieval routes. Their rankings are combined with fixed weighted reciprocal-rank fusion, followed by confidence-aware filtering and top-100 reranking. Typed session state tracks hard and soft evidence, evidence decay, no-preference tombstones, intent generations, profile priors, and rejected recommendations.

The frozen competition configuration runs fully offline with Python’s standard library. We also implemented an optional GPT-5.6 Luna enhancement behind explicit opt-in, strict schema validation, a two-call session limit, timeout, and circuit breaker. It remained disabled for every reported result because the deterministic path already performed strongly and no credentialed holdout trial justified enabling it.

Challenges we ran into

The hardest problem was deciding when conversation history should help and when it should be discarded. Keeping every earlier preference harmed override sessions, while resetting too eagerly harmed gradual refinement. Intent generations let us preserve category context while revoking stale non-category evidence.

Broad queries created another challenge: a relevant item could exist in a huge candidate set with almost no score separation. Diverse shortlists, information-gain clarification, and candidate rotation proved more useful than simply adding model complexity.

We also preserved a complete network-disabled path because judging may disable external access. That meant catalog normalization, retrieval, state, clarification, validation, and evaluation all had to remain deterministic and local.

Accomplishments that we're proud of

On the unmodified 200-session public evaluator, the frozen offline agent achieved:

  • HitRate@10: 0.985
  • MRR: 0.556740
  • MTTC: 3.21
  • TechnicalScore: 0.815322, compared with the official weak baseline of 0.106710
  • Response latency: 20.7 ms p50 / 55.5 ms p95
  • Model usage and API cost: 0 tokens / $0.00

Ablations showed that conversational state, clarification, and recommendation rotation each made material contributions. The repository includes deterministic demos, contract and failure-path tests, a locked evaluation split, ablations, clean-room verification, and complete reproduction documentation.

What we learned

Strong conversational retrieval depends on disciplined state and question policy, not just semantic matching. A clarification question is valuable only when it meaningfully separates the remaining candidates, and an earlier preference should never become permanent after the shopper revokes it.

What's next

We would move the dense index to a disk-backed representation to reduce the current 733 MB peak-memory tradeoff, expand Boundary evaluation beyond the ten public examples, and run controlled holdout trials of profile-aware ranking and the optional model reranker.

All reported metrics apply only to the released public evaluator; we make no claim about the organizer’s private judging set.

Built With

  • conversational-ai
  • feature-hashing
  • fts5
  • information-retrieval
  • openai-responses-api
  • python
  • sqlite
Share this project:

Updates

Submission history