Inspiration

Online shopping search often fails when users cannot describe exactly what they want in one query. Their requirements may emerge gradually, they may have no preference for certain attributes, or they may change their minds during the conversation.

We built Shopping Copilot to turn this evolving conversation into structured search intent. Our goal was to create an agent that understands multi-turn shopping needs, asks useful clarification questions, and finds the correct product as early and as highly ranked as possible.

What it does

Shopping Copilot is a multi-turn conversational product-search agent operating on a fixed catalog of 50,000 products.

It can:

  • Distinguish buying intent from exploratory browsing
  • Extract category, brand, material, color, size, style, budget, feature, and use-case requirements
  • Separate hard constraints, soft preferences, and negative constraints
  • Remember requirements across multiple conversation turns
  • Handle no-preference responses and explicit field removal
  • Replace stale constraints when the user changes their mind
  • Ask structured clarification questions
  • Retrieve products using BM25 with optional TF-IDF scoring
  • Rank candidates using relevance, attribute matching, and popularity
  • Optionally rerank candidates through DeepSeek
  • Fall back to an offline SQLite FTS5 search path
  • Return only valid and unique catalog product IDs

The agent follows the competition's required Agent.reset(...) and Agent.respond(...) interface and enforces the official ten-turn and top-10 recommendation limits.

How we built it

We designed Shopping Copilot as an offline-first modular pipeline:

User Message -> Intent Routing and Slot Extraction -> Structured Session Memory -> Hard and Negative Constraint Filtering -> BM25 Candidate Retrieval -> Optional TF-IDF Scoring -> Deterministic Rule-Based Ranking -> Optional DeepSeek Reranking -> Response Validation and Clarification The intent layer uses catalog-derived vocabulary and deterministic language rules to classify buying and browsing behavior and extract structured product requirements. The memory layer stores one isolated state per session. It applies additions, removals, replacements, and intent overrides atomically. It also supports rollback, bounded conversation history, request idempotency, and clarification bookkeeping. The retrieval layer first applies hard and negative constraints. It then uses an optimized BM25 inverted index to produce a bounded candidate pool. TF-IDF can optionally provide an additional lexical relevance signal without performing full-catalog semantic ranking on every turn. The ranking layer combines keyword relevance, category match, attribute match, semantic score, average rating, and review popularity. Buying and browsing requests use different ranking weights. For optional model-based reranking, we integrated the DeepSeek OpenAI-compatible Chat Completions API using deepseek-v4-flash. The model can only reorder IDs from the supplied candidate set. Invalid responses, network failures, and timeouts preserve the deterministic local ranking. We evaluated the complete system through the same starter.agent.Agent interface used by the competition harness.

Challenges we ran into

One major challenge was representing evolving intent without keeping obsolete constraints. A phrase such as “Actually, ignore my earlier preference” must be treated differently from a negative product constraint such as “without leather.” We addressed this with explicit add, remove, replace, override, and no-preference state operations. Another challenge was searching a 50,000-item catalog within practical CPU and memory limits. Full-catalog TF-IDF processing was too expensive, so we optimized BM25 with inverted postings and restricted optional TF-IDF scoring to a bounded candidate pool. Integrating independently developed components also required one canonical contract for products, candidates, intent results, retrieval results, and session state. This prevented the final system from accumulating incompatible adapters. Finally, adding an external LLM without making it a reliability risk required strict JSON parsing, product-ID validation, token accounting, bounded calls, and a fully offline fallback.

Accomplishments that we're proud of

Built a complete multi-turn shopping agent that follows the official evaluator contract Integrated intent understanding, memory, retrieval, ranking, clarification, evaluation, and fallback into one coherent system Correctly handles intent override, negative constraints, and no-preference scenarios Supports both offline retrieval and optional DeepSeek reranking Prevents fabricated, invalid, and duplicate product IDs Keeps API credentials and private local files outside Git Added automated unit and integration coverage, with 55 tests passing Successfully completed the full 200-session public evaluation

What we learned

We learned that conversational product search is primarily a state-management and candidate-recall problem, not simply an LLM prompting problem. Structured constraints and explicit state transitions were essential for reliable multi-turn behavior. We also learned that hard constraints, soft preferences, and negative constraints must have different effects: hard and negative constraints determine eligibility, while soft preferences should influence ranking. Our evaluation showed that retrieval quality defines the upper bound for downstream reranking. DeepSeek improved ranking positions but did not increase Hit Rate@10 because it could only reorder existing candidates. We also learned the importance of measuring performance, memory usage, token consumption, fallback behavior, and reproducibility alongside ranking quality.

What's next for Shopping Copilot

Given more time, we would:

  • Add stage-level Recall@N diagnostics to separate filtering, retrieval, and ranking errors
  • Build field-specific inverted indexes for faster constraint filtering
  • Convert anonymized aggregate user profiles into safe, calibrated soft-ranking signals
  • Select clarification questions using expected information value
  • Schedule DeepSeek calls after meaningful state changes instead of always using the first eligible turn
  • Add a compact dense semantic retriever
  • Improve paraphrase and implicit-preference coverage
  • Evaluate latency, memory, and model cost across more environments
  • Add a lightweight user interface for interactive demonstrations

Built With

Share this project:

Updates

Submission history