The Paradox Why Won't Whine How It Works ✦ Pro
Try It Free →
⚙️ How It Works

From Feeling to Bottle: The Engine Behind Won't Whine

Won't Whine Editorial June 2026 8 min read
Diagram showing how Won't Whine matches mood to wine

Won't Whine doesn't just ask how you feel and show you a list. There's a pipeline underneath — emotion chips, flavour mathematics, nearest-neighbour geometry, semantic search, and a reasoning agent that ties it all together. Here's how it works, in plain language.

Step 1 — Emotion Chips to a Flavour Vector

When you select chips like "Romantic," "Date Night," or "Floral & Delicate," each one carries a hidden payload: a set of flavour dimension weights. These aren't guesses — they're derived from sommelier literature, sensory science, and pattern analysis across thousands of wine reviews.

Wine has 14 flavour dimensions in our model:

DimensionWhat it captures
FruityBerries, stone fruit, citrus, tropical notes
EarthySoil, mushroom, forest floor, leather, tobacco
TannicGrip, astringency, structure, mouth-drying texture
AcidicBrightness, crispness, zesty lift
SweetResidual sugar, honey, jam, off-dry character
DryBone-dry, austere, bone-lean, no residual sugar
ComplexLayered, evolving, multi-dimensional
BoldFull-bodied, powerful, high alcohol, concentrated
LightDelicate, gossamer, pale, ethereal
FloralRose, violet, lavender, jasmine, blossom
SpicyPepper, clove, cinnamon, anise
MineralFlint, chalk, slate, wet stone, saline
OakyVanilla, cedar, toast, smoke, barrel influence
HerbalGrassy, thyme, eucalyptus, mint, green

Each emotion chip maps to a subset of these dimensions. "Romantic," for example, loads heavily on Floral (90), Fruity (75), Light (65), and Acidic (55) — a profile that points toward elegant, aromatic wines. "Contemplative" loads on Complex (100), Earthy (75), Dry (85), and Tannic (60) — structured, intellectually rewarding bottles that reward slow attention.

When you select multiple chips, the dimension weights are averaged together into a single 14-component vector. This is your taste fingerprint for tonight.

Fourteen wine flavor notes converging into one matched glass of wine
Fourteen flavor dimensions turn a feeling into a profile the search engine can compare.
Example: Romantic + Date Night + Floral & Delicate
Floral
88
Fruity
75
Light
70
Acidic
62
Complex
55
Tannic
18
Bold
22

Step 2 — Finding Nearest-Neighbour Wines

The flavour vector becomes a point in 14-dimensional space. Every wine in our database also occupies that same space — each with its own coordinates across the 14 dimensions, calibrated from tasting notes, sommelier descriptions, and chemical data.

We use a kD-tree (a binary space-partitioning tree) to search this space efficiently. The kD-tree finds the wines closest to your vector by Euclidean distance — in other words, the bottles whose flavour fingerprint most closely matches the profile you've described through your emotion selections.

🎭
Emotion chips selected
Romantic · Date Night · Floral & Delicate → each maps to a partial flavour vector
📐
Averaged into a 14D vector
Floral:88, Fruity:75, Light:70, Acidic:62, Complex:55 … all 14 dims
🌲
kD-tree nearest-neighbour search
Queries the flavour-space tree → returns top 5 wines by Euclidean distance
🔍
Semantic review search (Chroma)
Parallel semantic search over 70+ wine descriptions and reviews using OpenAI embeddings
🤖
ReAct agent reasons & selects
LangGraph agent cross-references flavour matches, reviews, and any filters → drafts a recommendation
🍷
A sommelier response, streamed to you
GPT-4o mini generates a warm, conversational recommendation with specific bottles and rationale

Step 3 — The Agentic RAG Layer

The kD-tree gives us candidate wines. But the recommendation logic is handled by a LangGraph ReAct (Reasoning + Acting) agent — an AI that can call tools, inspect results, reason about what it found, and call more tools if needed.

The agent has six tools at its disposal:

# Available tools for the ReAct agent RecommendByFlavor # kD-tree search by 14D vector SearchWinesByEmotion # semantic similarity over reviews GetWineDetails # exact name lookup in the database FilterWines # structured filters: style, country, price GetDatasetStats # aggregate statistics about the collection SearchWineOnline # Tavily web search for wines not in local DB

When you add a free-text note like "red wine only" or "under $30," the agent picks up the constraint and calls FilterWines alongside RecommendByFlavor. If you ask about a specific bottle, it uses GetWineDetails. If the wine you want isn't in our database, SearchWineOnline performs a live web search and brings back current information.

The agent doesn't just pick the top result and hand it to you. It reasons: Does this wine fit the occasion? Does the description match the emotional vector? Are there better options across different price points? Then it writes the final response as a knowledgeable sommelier would — with warmth, context, and a rationale you can act on.

A wine bottle selected from a connected archive of tasting notes
The agent cross-references flavor profiles, descriptions, filters, and the wider cellar before choosing.

Step 4 — The Dataset

The quality of the recommendation depends entirely on the quality of the wine data. Won't Whine uses a layered dataset:

70+ hand-curated wines

A core collection of 70 wines, hand-authored with accurate taste profiles across all 14 dimensions — covering Bordeaux, Burgundy, Barolo, Champagne, Riesling, and more. Each wine has name, winery, country, region, grape varieties, vintage, price, alcohol, and a tasting profile built from expert sources.

WineSensed (NeurIPS 2023)

We draw on the WineSensed dataset — 897k wine label images and 824k Vivino reviews covering 350k+ unique vintages. Review text is parsed for flavour keywords to score additional wines across the 14 dimensions, expanding the database.

UCI Wine Quality (Kaggle)

Portuguese Vinho Verde wines from the UCI Wine Quality Dataset are included via chemistry-to-flavour mapping. Properties like pH, residual sugar, sulphates, and alcohol content are deterministically converted to flavour dimensions (e.g., pH → Acidic, residual sugar → Sweet, alcohol → Bold). KMeans clustering reduces 1,143 chemical analyses to ~120 representative wine entries.

"The goal was never to index every wine on Earth. It was to have enough well-characterised wines that every emotional profile finds a genuinely good match."

Why Streaming?

Won't Whine streams the recommendation token by token — you see the response forming in real time. This is done via Server-Sent Events (SSE): as the language model generates each token, it flows immediately to your browser. You also see the agent's reasoning steps as they happen — which tools it called, what it searched for — so the sommelier's thinking process is transparent.

Streaming matters because wine recommendations benefit from reading the full answer, not just a headline. You want the context, the pairing notes, the tasting language. Seeing it arrive word by word keeps you engaged and lets you start reading before the response is complete.

See it working live.

Pick a mood, pick an occasion — Dion will walk you through the reasoning and serve the right bottle.

Try Won't Whine →