Technical Architecture · LDI v5.1

Lost Demand Intelligence:
Seeing what analytics miss

LDI is a real-time classification engine that identifies purchase intent in e-commerce search queries — before the user presses Enter. This document explains the architecture that reached 91% accuracy on a new product domain by rebuilding only the domain knowledge layer — not by retraining the underlying model.

Author: Łukasz Piskorski / Adept AI Version: 5.1 (Surgery Fixed) Status: Production · Live Demo
91%
Automotive accuracy
91/100 test scenarios
92.3%
Electronics accuracy
169/183 — new domain knowledge layer
1.0 / 0.8
Platinum / Gold
reward labels

Standard e-commerce analytics track what users bought. They cannot track what users wanted to buy but couldn't find. LDI captures this signal in real-time — and identifies the highest-value training data automatically.

I.

The Gold Signal: Reward what matters, penalize what doesn't

The core insight

Most search analytics reward clicks. Problem: a click after a perfect match (query = product) is low-value — the user already knew what they wanted. The system learned nothing.

The highest-value signal is the inverse: clicked_despite_no_match. User searched for "iPhone 14 Pro case leather", I didn't have it, but they clicked on "iPhone 14 silicone case" anyway. This tells me:

Gold Signal: NO_MATCH → user clicked an alternative product. Exported reward score 0.8 — high weight in training.

Platinum Signal: when discovery converts to purchase

Gold Signal captures intent (user clicked the alternative). When that click leads to a purchase, the record is upgraded to Platinum Signal — the strongest training label in the system.

Platinum Signal: NO_MATCH → clicked alternative → purchased. Exported reward score 1.0 (ceiling of the normalized range).

The reward formula

LDI uses a weighted ensemble of behavioral signals with anti-bait penalties. Three signal categories drive the score:

Exact weights are tuned hyperparameters refined against the test suite. All scores normalize to [-1.0, +1.0] — directly consumable by reward-modeled fine-tuning pipelines.

Bounce detection runs as a batch sweep at JSONL export time, not on the hot path. Records older than 5 minutes with no click, cart-add, or purchase are flagged bounce: true in a single UPDATE. This keeps query classification free of background bookkeeping, at the cost of bounce labels being eventually consistent (not real-time).


II.

Semantic Validation: Filtering noise before it reaches the model

The problem with raw query logs

E-commerce search logs are 60-70% noise: keyboard mashing (asdfgh), incomplete prefixes (ip), food queries on an auto parts store (pizza), and hallucinated products (iPhone 30).

If you train on this data, you train on garbage. LDI implements a SemanticValidator that rejects low-quality queries before they enter the reward pipeline.

The 5-layer rejection pipeline

Every query passes through five sequential filters before it touches the reward engine:

  1. Format checks — minimum length, keyboard mashing patterns, nonsense word lists
  2. Domain heuristics — wrong-domain detection (e.g. food queries on an auto parts store)
  3. Realism check — model number sanity catches hallucinations like iPhone 30 or Galaxy S99
  4. Lost-demand qualification — NO_MATCH queries must carry both domain context (recognized brand or category) and at least one extractable feature; otherwise they are uninformative noise
  5. Feature extraction — a per-domain attribute extractor (color, capacity, chassis code, fuel type, body type, etc.) populates missing_features for downstream training labels

Records that fail any layer are persisted with ai_ready: false and excluded from training exports by default.

Why NO_MATCH with features is valid

If a user searches "BMW E46 klocki Brembo" and I get NO_MATCH, that's not noise — that's genuine lost demand. The query has domain context (car brand + part term) and the feature extractor pulls out gen:e46. These records are flagged VALID_LOST_DEMAND and routed to the Gold/Platinum Signal pipeline.


III.

Universal Automotive Knowledge: ~980 entities, zero hallucinations

The domain knowledge layer

LDI was built first for automotive e-commerce. The UNIVERSAL_AUTOMOTIVE_KNOWLEDGE dictionary ships with:

Total: ~980 domain entities across 8 categories, all hot-loaded into memory at boot. The electronics adaptation swaps this dictionary for an equivalent UNIVERSAL_ELECTRONICS_KNOWLEDGE structure — same shape, different content.

Why this matters

When a user types "Brembo klocki E46", the system knows:

This context enables fuzzy matching: even if I don't have "Brembo brake pads for E46" in the product database, I can suggest "ATE brake pads for E46" — and if the user clicks, that's a Gold Signal.


IV.

Real-time classification pipeline

Architecture flow

User query ("BMW E46 klocki Brembo")
    ↓
[1] source dispatcher (moto vs elektro)
    ↓
[2] per-domain MissingFeatureExtractor
       moto   → MotoFeatureExtractor    (chassis, engine, fuel, body, color)
       elektro → ElektroFeatureExtractor (capacity, ram, screen, variant, gen)
    ↓
    extracts: ["gen:e46"]
    ↓
[3] SemanticValidator (5-layer pipeline)
    rejects: keyboard | wrong-domain | unrealistic | NO_MATCH-without-features
    ↓
[4] Fuzzy matcher against in-memory product catalog → confidence_level
    ↓
    ┌──────────────────────────────┬──────────────────────────────┐
    │ HIGH / MEDIUM                │ NO_MATCH                     │
    │ standard product results     │ alternative suggestions      │
    └──────────────────────────────┴───────────────┬──────────────┘
                                                   │
                                                   ↓
                                       User clicks "Add to cart"?
                                                   │
                                       ┌───────────┴───────────┐
                                      YES                     NO
                                       │                       │
                                       ↓                       ↓
                              GOLD SIGNAL (0.8)        Lost-demand log
                                       │                (inventory team)
                            purchase webhook fires?
                                       │
                                       ↓ YES
                              PLATINUM SIGNAL (1.0)

Hot-path design

Classification runs on the keystroke debounce — there are no external API calls in the request path. Three things make this work:


V.

Training data export: JSONL for fine-tuning

AI-ready data pipeline

Every validated session is logged to JSONL with a normalized reward score [-1.0, +1.0]. This format is directly consumable by reinforcement learning pipelines.

{
  "query": "BMW E46 klocki Brembo",
  "intent_label": "hamulce",
  "confidence": "NO_MATCH",
  "source": "moto",
  "reward_signal": {
    "score": 0.8,
    "clicked_alternative": true,
    "purchased": false,
    "bounce": false
  },
  "missing_features": ["gen:e46"],
  "matched_product_id": null,
  "alternative_clicked_id": "ate-klocki-e46-przod",
  "ai_ready": true,
  "query_refinement_count": 0,
  "timestamp": "2026-06-17 10:30:00"
}

Data quality guarantees

Field Meaning Export behavior
ai_ready: true Passed all 5 validator layers, has extractable features Default export (clean training data)
ai_ready: false Keyboard pattern, wrong domain, unrealistic model, NO_MATCH without features Excluded unless ?ai_ready=0
source Bot domain (moto / elektro) Use for per-domain partitioning
missing_features Per-domain attribute extraction (color, capacity, gen, fuel, ...) The "what was the user looking for" training label
score: 0.8 Gold Signal — NO_MATCH + clicked alternative (no purchase yet) Prioritize in training
score: 1.0 Platinum Signal — NO_MATCH + click + purchase Highest training weight

VI.

Privacy by design: GDPR-compliant from the first byte

LDI is deployed in the EU. Privacy is enforced at the data layer, not bolted on later.

What is scrubbed before logging

What the JSONL training export contains — and what it doesn't

The export ships query text, classification metadata, behavioral flags, and the reward score. It does not ship session IDs, IP hashes, organization names, or any user identifier. Two records from the same session are linked only by the surrounding behavioral signal, never by an identifier.

Right to erasure

All visitor data is keyed by salted session hash in a single relational store. Deletion requests resolve to a single DB query, not a multi-system reconciliation. No analytics warehouse, no third-party CDN cookies, no off-platform reporting.


VII.

Test results & cross-domain generalization

Cross-domain generalization

The same architecture was retargeted from automotive to consumer electronics (smartphones, laptops, audio) without retraining the underlying model or touching its hyperparameters. What did change was the domain knowledge layer — brands, categories, and the attribute extractor — which had to be rebuilt for the new vertical. This is not a zero-effort transfer: the validator, reward engine, and session consolidation are domain-agnostic by design, but each new vertical still needs its own domain knowledge layer built out.

Electronics test suite: 169/183 scenarios passed (92.3%) — marginally higher than the automotive benchmark, on a domain the system had never seen before. Evidence that the validator, reward engine, session consolidation, and feature-extraction core are genuinely domain-agnostic.

Automotive test methodology

The test suite covers edge cases that break naive matchers:

Results breakdown

Category Scenarios Passed Accuracy
Basic queries + product codes 30 30 100%
Typo handling (basic + hard) 20 20 100%
Context & mixed language 20 18 90%
Mechanic slang + tech specs 20 15 75%
Noise rejection + edge cases 10 8 80%
TOTAL 100 91 91%

The 9 failures are documented. Most are edge cases in mechanic slang variants, rare technical specifications, and Polish morphology edge cases. They're on the roadmap — not blockers. → Full test methodology (91/100 scenarios)


VIII.

Where LDI fits next to standard analytics

What standard analytics already do

GA4, Mixpanel, and most internal warehouses can log search terms, no-result events, and custom "lost demand" dimensions. The question is what comes out the other end — and what shape the data is in by the time an ML engineer or merchandiser sees it.

Where LDI is structurally different

None of this replaces GA4 — they solve different problems. LDI is a specialized layer that produces something general analytics cannot: training-ready labels for the queries that didn't convert.


Epilogue: Why this matters for e-commerce

Every e-commerce store has a "lost demand" problem. Users search for products that don't exist in the catalog. The search returns "no results" or irrelevant suggestions. The user leaves.

Standard analytics cannot capture this. They see a bounce. They don't see the intent.

LDI captures the intent. It logs what users wanted, not just what they bought. It identifies which "no results" queries are genuine demand signals (Gold Signal) vs. noise (keyboard mashing, wrong domain).

This data is the highest-value signal for inventory decisions and AI training. It tells you what to stock. It tells you what associations to learn. It's the signal that standard analytics miss.

I don't track what users bought. I track what they wanted.