
When you train an AI model, the quality and type of data matters more than the algorithm or computing power.
"Training data has always been the hard part of machine learning. Not the architecture, not the compute, but the data itself."
Before LLMs, the challenge was labeling and feature engineering. With LLMs, the challenge shifts to teaching behavior:
| Old Problem | New Problem |
|---|---|
| Label this image as "cat" or "dog" | Teach the model how to behave in ambiguous situations |
| Feature engineering | Knowing when to refuse a request |
| Data volume | Data diversity and coverage of edge cases |
Production logs (real user interactions) only capture successes. Failed or impossible requests never make it into training data. So the model learns from a biased sample of reality.
A structural gap in training data caused by how production systems work.
User makes request
↓
Model handles it successfully
↓
Gets evaluated and logged ✓
↓
Enters training corpus
But what about this path?
User makes impossible request
↓
Model should refuse... but doesn't know how
↓
Model improvises badly
↓
Never logged as a "refusal example"
↓
Never enters training corpus ✗
The model is trained entirely on successful queries. When it encounters something impossible, it has no learned behavior to fall back on. It improvises — usually badly.
A merchant asks: "Find me customers who are doctors."
Shopify doesn't store occupation data. The correct answer is: "I can't do that."
Instead, the model generated a query that returned zero results — giving the merchant the false impression that no doctors exist in their customer base, rather than that the request was impossible.
Sidekick is Shopify's AI assistant for merchants. It has two layers:
Merchant Request: "Send a discount to my best customers"
↓
┌─────────────────┐
│ Outer Planner │ ← Interprets overall intent
└────────┬────────┘
│ Routes to...
┌────────────┼────────────┐
↓ ↓ ↓
Segmentation Analytics Email
Skill Skill Skill
Each skill model is specialized. The segmentation skill, for example, converts plain English into Shopify's domain-specific query syntax — a language most merchants can't write themselves.
The segmentation skill was fine-tuned on production data — all successful queries. It had zero refusal examples. So it never learned to say "I can't do that."
Shopify partnered with Toloka (a data annotation team) to create ~600 refusal examples. Then they tried the obvious fix:
Production data (successes) + Toloka data (refusals) = Merged dataset → Fine-tune
The same query appeared in both datasets with opposite labels:
Production data says: "Find customers who bought last month" → ✓ VALID
Toloka data says: "Find customers who bought last month" → ✗ REFUSE
The model received contradictory training signals for semantically similar inputs. This caused:
You can't just merge datasets with conflicting labels. You need a way to resolve conflicts at scale — which manual annotation can't do cheaply.
Instead of hiring more human annotators, use frontier LLMs as automated judges to evaluate and label training data.
Small high-quality Toloka dataset (seed)
↓
Calibrate 4 LLM judges using seed
↓
Run judges across full production corpus
↓
Judges label AND resolve conflicts
A single LLM judge can be wrong or inconsistent. Using four independent judges creates a panel — similar to peer review in science.
Before judging anything, each LLM is shown few-shot examples from the Toloka dataset:
"Here's a query. Here's what a human expert said about it. Now use this as your reference."
This anchors the judges to human ground truth, not the model's own assumptions about what Shopify can or can't do.
A label is only accepted if all four judges agree on:
Judge A: REFUSE (because Shopify doesn't store occupation data)
Judge B: REFUSE (because Shopify doesn't store occupation data)
Judge C: REFUSE (because Shopify doesn't store occupation data)
Judge D: REFUSE (because Shopify doesn't store occupation data)
↓
✓ CONSENSUS REACHED → Label accepted
Judge A: REFUSE
Judge B: REFUSE
Judge C: VALID
Judge D: REFUSE
↓
✗ NO CONSENSUS → Example discarded (sent to human review)
| Priority | Meaning | Choice made |
|---|---|---|
| Precision | Only accept labels you're confident about | ✓ Chosen |
| Recall | Capture as many valid examples as possible | ✗ Sacrificed |
"Better to miss a valid refusal than to mislabel a legitimate merchant request."
Noisy labels in training data are worse than missing data. A wrong label actively teaches the model bad behavior. A missing example just means less coverage.
If categories overlap, judges will disagree — not because the task is hard, but because the categories themselves are ambiguous.
| Category | Meaning | Example |
|---|---|---|
| Solvable with more context | Planner needs to fetch more info first | "Show me customers like my VIPs" (needs VIP definition) |
| Missing capability | Feature doesn't exist in Shopify yet | "Find customers who are doctors" |
| Wrong skill | Not a segmentation task; route elsewhere | "What were my sales last month?" → Analytics skill |
| Ambiguous | Needs clarification from merchant | "Find my good customers" (what does "good" mean?) |
Overlapping categories → Judge disagreements
↓
Inconsistent labels
↓
Unstable fine-tuning
↓
Worse model behavior
Clean categories → faster calibration, more consistent labels, more stable training.
A self-reinforcing feedback loop where each model deployment generates data that improves the next version.
┌─────────────────────────────────────────────────────┐
│ │
│ 1. Improved model ships to production │
│ ↓ │
│ 2. Real merchant queries come in (including │
│ new edge cases, new phrasings) │
│ ↓ │
│ 3. Judge ensemble labels new queries │
│ (discards disagreements) │
│ ↓ │
│ 4. Accepted labels added to training corpus │
│ ↓ │
│ 5. Next fine-tuning run starts with MORE │
│ data and CLEANER labels │
│ ↓ │
│ 6. Better model ships → back to step 1 ──────────►│
└─────────────────────────────────────────────────────┘
Production traffic cannot just sit in dashboards. It must become the input to the next training run.
| Metric | Value |
|---|---|
| Segmentation score (before any refusal data) | 0.619 |
| Segmentation score (after flywheel) | 0.798 |
| Relative gain | +28.9% |
| Naive merge pass rate | 0.762 |
| Automated curation pass rate | 0.798 |
| Refusal accuracy | 86.3% |
| False positive rate (wrongly refusing valid requests) | 4.6% |
| Judge agreement with ground truth | ~90% |
| Cohen's Kappa (judge reliability) | >0.75 (substantial agreement) |
It measures inter-rater reliability — how much agreement exists beyond random chance:
| Kappa | Interpretation |
|---|---|
| < 0.20 | Slight agreement |
| 0.21–0.40 | Fair agreement |
| 0.41–0.60 | Moderate agreement |
| 0.61–0.75 | Good agreement |
| > 0.75 | Substantial agreement ✓ |
Most teams think of refusals as failures — the model couldn't do something.
Shopify reframes this: a truthful refusal is a product feature.
| Scenario | Outcome |
|---|---|
| Model hallucinates an answer | Merchant acts on false information → bad targeting, confused users, lost trust |
| Model refuses clearly | Merchant knows to try something else → outer planner can redirect → conversation stays productive |
"We spent a lot of time teaching the model when to say yes. We should have started with when to say no."
A refusal, ideally paired with a suggestion ("I can't find customers by occupation, but I can segment by purchase history"), keeps the user experience intact.
PROBLEM: Production data has no refusal examples
↓
SEED: Small high-quality human annotations (Toloka, ~600 examples)
↓
JUDGES: 4 frontier LLMs calibrated on seed data
↓
TAXONOMY: 4 mutually exclusive categories (no ambiguity)
↓
CONSENSUS GATE: All 4 judges must agree on decision + reasoning
↓
CORPUS: Cleaned, conflict-resolved training data
↓
FINE-TUNING: Model learns to refuse impossible requests
↓
DEPLOYMENT: Better model ships
↓
FLYWHEEL: New production traffic → new labels → next training run
↓
(loop continues, improving each cycle)
| Lesson | Why it matters |
|---|---|
| Small seed datasets punch above their weight | Quality > quantity; judges inherit seed biases, so seed quality is critical |
| Mutual exclusivity in taxonomy is non-negotiable | Overlapping categories cascade into inconsistent labels and unstable training |
| Consensus beats confidence | Unanimous agreement keeps precision high when you're still learning the problem space |
| Refusals are product features | A truthful "I can't do that" is always better than a confident wrong answer |