Skip to content
Mark Liu

Chapter 03 · 2026 · Retail

Starbucks product recommender

A three-stage pipeline that turns a plain-language request like “iced tea under 100 calories” into a ranked list of Starbucks products.

Skills
Stack
Python · pandas · NumPy · Gemini API · Pydantic

Built for the UCLA Starbucks Data Challenge in January 2026, when the Starbucks team visited the UCLA MSBA program and asked students to build a recommendation system. It was a team project with four teammates. This page covers my implementation of the pipeline.

The product catalog and queries were provided by Starbucks and randomly generated. They do not reflect real customer or sales data.

Question

Given a request in plain language, return the right products from a 115-item catalog. The team had 100 training queries with known relevant products to measure against.

Approach

Three stages:

  1. Extract constraints. Gemini 2.0 Flash reads the request and returns typed fields (category, temperature, calorie limit, dairy, caffeine and so on), validated against a Pydantic schema.
  2. Filter. Pandas removes products that break a hard constraint, taking the catalog from 115 items to about 5–20.
  3. Rank. The remaining products are ranked by cosine similarity between the query and product embeddings. Product embeddings are computed once, so ranking is a single matrix product.

Filtering before ranking matters. Embeddings alone can rank a dairy latte highly for someone avoiding dairy, because the text is similar. The filter also makes every exclusion explainable.

Result

Ranking method NDCG@10 Recall@10 Cost per query
LLM re-ranking (Gemini API) 97.7% 90.1% Highest
Local BGE embeddings 96.1% 89.7% None
Rule-based scoring 85.1% 82.1% None

The team recommended local BGE embeddings. They give up 1.6 NDCG points against the API model, but cost nothing per query, run offline, and avoid depending on one vendor. At around 40 million monthly users, a per-query API fee adds up quickly. The notebook uses Gemini embeddings so it runs without downloading a model.

Limits and next steps

  • The first query waits on the API call for constraint extraction, about 0.8–1 second.
  • Caffeine thresholds are hand-set and could be learned from behavior data.
  • A cross-encoder re-ranker, or combining keyword and embedding search, would likely raise NDCG further.

← all work