Inspiration

Traditional search asks which products should be ranked.

Conversational shopping adds a harder decision: should the agent show another product now, or is one more question more valuable?

Showing too many products improves coverage but can bury the correct item at a low rank. Asking too many questions improves confidence but creates friction.

We built InverseCart to optimize both decisions together: what to recommend and when to ask for more information.

What It Does

InverseCart is a stateful shopping agent for a 50,000-product catalog.

Instead of treating every message as a new search query, it maintains a set of products that could still explain the entire conversation.

As the customer reveals more information, incompatible products are removed. If the request is still ambiguous, InverseCart can deliberately show fewer products and ask for another detail instead of filling the entire Top-K list.

The result is a dynamic recommendation policy that balances coverage, ranking quality, and conversation length.

Why It Matters

Customers do not want ten weak guesses, but they also do not want to answer unnecessary questions before seeing anything useful.

InverseCart tries to find the smallest useful recommendation set at each turn.

For commerce platforms, the same design is fast and auditable: the submitted runtime requires no LLM calls, external APIs, credentials, or network access.

How We Built It

The key insight came from reversing the released customer-generation process.

Each target product has a category and an ordered set of details that may be revealed during the conversation.

So instead of repeatedly asking:

Which products match this message?

InverseCart asks:

Which products could have generated this conversation?

1. Products become hypotheses

At startup, every product is converted into an intent card containing its category, hard constraints, softer preferences, searchable metadata, and belief weight.

The 50,000 products therefore become 50,000 possible hypotheses about what the customer wants.

2. The conversation eliminates impossible hypotheses

After every turn, InverseCart compares the observed dialogue against the remaining intent cards.

A product survives only if it could have produced the same category request, ordered other disclosures, and Intent Override behavior.

If the conversation continues after a recommendation turn, previously shown products are known misses and can be removed.

Intent Override is handled separately: recommendations made before the customer changed intent were based on the old request, so they may become valid again.

3. Uncertain NLP remains reversible

Exact catalog-grounded evidence can safely remove products.

Uncertain language only creates a high-priority focus set. The last trusted candidate set remains available underneath it.

This means a parser interpretation can improve ranking without permanently deleting the correct product.

4. Dynamic programming chooses how many products to show

After filtering and ranking the candidates, InverseCart must decide the recommendation depth K.

For every K from 1 to 10, a finite-horizon dynamic program compares:

expected reward from showing the first K products now

against

expected future reward after another clarification

If the target is not inside the first K products, each remaining candidate predicts what the customer would reveal after the next other response.

Candidates predicting the same reply form one future branch. The planner evaluates these branches through turn ten and chooses the K with the highest expected Technical Score.

In simple terms, it asks:

Is the next product worth more than the next piece of information?

The planner optimizes recommendation depth for the current candidate ordering. The clarification type remains other.

5. A prior improves ordering, not eligibility

Among products already compatible with the conversation, InverseCart uses a smoothed recent verified-review count as a belief prior.

Popularity can change ranking and probability, but it can never override a category or hard constraint.

This produced the following progression on the organizer’s public-development set:

System Technical Score Mean Turns ↓
Released weak BM25 0.106710 9.810
Inverse hypotheses + uniform DP 0.963350 2.795
+ Catalog popularity 0.979900 2.005
+ Recent verified-review prior 0.983200 1.840

The largest improvement came from changing the problem itself: from repeated search to hypothesis filtering plus sequential planning.

Challenges We Ran Into

False elimination

Exact filtering is powerful, but treating an uncertain interpretation as a hard fact can permanently remove the target.

We solved this by separating ranking focus from trusted eligibility.

Competing objectives

A larger K improves immediate coverage but may reduce reciprocal rank. A smaller K gives the agent more opportunities to learn but consumes additional turns.

Dynamic programming allowed us to optimize this trade-off instead of hard-coding one recommendation count.

Intent Override

A recommendation rejected before the customer changes intent is not necessarily wrong for the new intent.

We therefore distinguish pre-override history from genuine misses under the active intent.

Distribution-dependent priors

The recent-review prior improved the public-development result but slightly underperformed uniform belief on a roughly uniform generated holdout.

This reinforced an important lesson: a prior is an assumption about the target distribution, not a universally better ranking rule.

Accomplishments

On the organizer’s 200 labeled public-development sessions, InverseCart achieved:

  • 100% Hit Rate@10
  • 1.000 MRR
  • 1.84 mean turns to conversion
  • 0.9832 Technical Score

Every successful hit appeared at rank one.

For comparison, the released weak BM25 baseline scored 0.106710.

On 2,000 generated-development sessions whose target products have zero overlap with the public 200, InverseCart achieved:

  • 0.9945 Hit Rate@10
  • 0.978687 MRR
  • 2.62 mean turns to conversion
  • 0.958456 Technical Score

The final runtime handles all 50,000 products with:

  • 17.5 ms mean response latency
  • 0 runtime model calls
  • 0 external APIs
  • 66 passing tests

The public-development set was used to select the final review prior, so 0.9832 is a development result, not a claim about private-test performance.

What We Learned

Conversational recommendation is not just a ranking problem. It is a sequential decision problem.

Sometimes the best action is another product. Sometimes it is another question.

We also learned that uncertain information does not need to be either fully trusted or completely ignored. It can guide ranking while remaining reversible.

Finally, simple deterministic components can be extremely effective when the structure of the problem is understood well. Our final runtime needs no online LLM while remaining fast, reproducible, and easy to inspect.

What’s Next

The largest remaining limitation is general semantic understanding.

The current parser works well when catalog values remain recognizable, but it cannot reliably map arbitrary paraphrases such as:

“something that won’t get wet in the rain”

to:

“waterproof”

Our next step would be to add a semantic matcher as a soft ranking signal while preserving the same recovery guarantees.

We would also extend the planner beyond recommendation depth so it can choose which clarification question provides the most information, and add customer-facing explanations and production serving infrastructure.

Sometimes the best next recommendation is one question away.

Built With

Python 3.10+, Python standard library, Git, GitHub, GitHub Actions, Make, the organizer-supplied evaluator, and the Amazon Reviews 2023-derived product catalog.

OpenAI Codex was used during development for repository inspection, code review, testing, benchmark orchestration, and documentation. Codex is not imported or called by the submitted runtime.

Runtime external APIs: None
Runtime third-party libraries: None
Runtime language or embedding models: None
Runtime credentials: None
Runtime network access: None after the catalog is available
Runtime model tokens: Zero

Dataset and Assets

The system uses the organizer-supplied 50,000-product Clothing_Shoes_and_Jewelry catalog derived from Amazon Reviews 2023.

The final prior stores one verified_reviews_365d count per product and uses:

verified_reviews_365d + 1

as its belief weight.

The smoothing keeps zero-review products possible. The prior only affects probability and ordering among products already compatible with the conversation.

It contains no review text, individual review rows, user identifiers, public-session mappings, or organizer-private labels.

Team Member Contributions

Nguyễn Tuệ Vy
Product story and presentation. Owns the end-to-end demo narrative, three-minute video production, and final Devpost/release QA.

Vũ Đăng Khoa
Evaluation studio and adaptive-policy research. Built the conversation viewer, target-free diagnostics and playback, and implemented and benchmarked the adaptive-K experiment.

Lưu Phúc Vinh
Alternative recommendation policy. Implemented and evaluated the conservative dynamic-K candidate for policy comparison and regression testing.

Lê Xuân Sơn
NLP, integration, and release engineering. Built the wrapper-tolerant parser and evaluation harness, integrated the production backend and offline prior, and handled documentation, CI, and reproducible release packaging.

Nguyễn Tùng Lâm
Core retrieval and planning. Designed and implemented inverse intent-card filtering, constraint state management, finite-horizon dynamic programming, preprocessing, prior tooling, and the core tests used by the submitted system.

Reproduction

git clone https://github.com/sonlexuan3000/Techjam.git
cd Techjam

make setup
make test
make demo
make integration-check

Built With

  • git
  • github
  • github-actions
  • make
  • python-3.10+
  • the-organizer-supplied-evaluator
  • the-python-standard-library
Share this project:

Updates

Submission history