
After studying this material, you should be able to:
Instead of clicking filters, users type free-form queries like:
To train a search model, you need two things:
| Requirement | Why It's Hard Without Traffic |
|---|---|
| Real user queries | No users yet → no queries |
| Relevance labels | No queries → no way to know which listings match |
This is the cold-start problem: You need data to train the model, but you need the model running to collect data.
Using Kullback–Leibler (KL) Divergence:
KL divergence measures how much one probability distribution differs from a reference distribution. Lower = closer to real user behavior.
| Method | KL Divergence Score |
|---|---|
| InPars | ~26.2 |
| Promptagator | 9.33 |
| CASTLE | 1.01 |
Key insight: Prior methods treat query generation and relevance labeling as separate problems. CASTLE solves both simultaneously.
When a guest views multiple listings but books only one, that behavior implicitly encodes preference:
Guest views: Listing A, Listing B, Listing C
Guest books: Listing A
→ Listing A = POSITIVE (preferred)
→ Listing B or C = NEGATIVE (viewed but rejected)
This creates a (positive, negative) contrastive pair — grounded in real human behavior, not LLM assumptions.
The LLM is instructed:
"Generate a query satisfied by the POSITIVE listing but NOT the negative listing."
Because the distinction is defined before the LLM acts, the relevance label is correct by construction — no post-hoc human judgment needed.
Positive Listing: Cabin with fireplace, ski resort nearby
Negative Listing: Beach house, no fireplace
Generated Query: "cozy cabin near ski resort with fireplace"
Relevance Label: Positive listing ✓ (automatically correct)
No circularity: What counts as positive/negative comes from user booking data, not from the LLM itself.
Three prompt variants work together:
Without intervention, LLMs tend toward "query collapse" — converging on the same short phrase repeatedly.
CASTLE explicitly instructs the model to vary length and phrasing.
Result:
| Metric | Real Users | CASTLE | Baselines |
|---|---|---|---|
| Word-count std deviation (σ) | 2.49 | 2.48 | 0.99 |
CASTLE nearly perfectly matches real user query length variation. Baselines are far off.
No booking history → no contrastive pairs → CASTLE can't apply its core mechanism.
| Level | CASTLE Score | Best Baseline |
|---|---|---|
| Overall query distribution | 1.01 | 9.33 (9.2× worse) |
| Attribute-type distribution | 0.08 | 0.09 (even beats hand-curated seeds) |
Even after real traffic accumulates, CASTLE remains useful because:
Real traffic naturally underrepresents rare searches like:
CASTLE's generation is conditioned on listing characteristics, so it can deliberately oversample these rare but important intents.
Think of it as filling gaps that organic traffic will never fill adequately.
Authentic Booking Behavior + LLM Generation
↓ ↓
Contrastive pairs Query diversity &
(real preference signal) linguistic variety
+ Relevance labels ↓
by construction Realistic phrasing
↓ ↓
└──────────────┬───────────────┘
↓
Closes the gap between
synthetic and real queries
| Component | What It Contributes |
|---|---|
| Booking data | Ground truth preference signal |
| Contrastive pairs | Automatic relevance labels |
| Seed queries | Authentic language style |
| Three prompt variants | Query diversity |
| Anti-collapse mechanism | Realistic length distribution |
| Virtual Judge | Long-tail coverage |