Improving a marketplace classifier
I wanted to improve the prompt without tuning it to the test. I turned recurring failures into specific changes, kept 40 cases outside the editing loop, and ran the chosen prompt across all 200 cases.
What the classifier needs to get right
A listing title is not enough. The classifier has to identify the exact product and retain details that change its resale value: generation, storage, carrier, condition, included accessories, financing status, and whether the asking price is usable.
iPhone 15 Plus 256GB T-Mobile Balance Owed
Works now but has remaining device payments and may be blocked. T-Mobile only. Asking price: $280.
- Identity
- iPhone 15 Plus · 256GB
- Restriction
- T-Mobile · financed
- Asking price
- $280 is a full-item price
Dropping the balance restriction could match this phone with clean, unlocked sales.
MacBook Air 13 M2 A2681 LCD Screen Assembly
Used replacement display assembly only. Laptop and logic board not included. Asking price: $210.
- Identity
- MacBook Air M2 · A2681
- Package
- Display assembly only
- Asking price
- $210 prices the replacement part
A screen assembly cannot be valued against complete MacBook sales.
Nintendo Switch OLED Tablet Console Only HEG-001
Screen tablet only. No Joy-Con, dock, charger, or games. Asking price: $135.
- Identity
- Switch OLED · HEG-001
- Package
- Tablet only
- Missing
- Controllers · dock · charger
Bundle contents materially change which sold listings are comparable.
Leica Q3 43 Camera Reservation Deposit
Nonrefundable deposit to join the waitlist; remaining balance due at pickup. Displayed price: $500.
- Identity
- Leica Q3 43
- Listing type
- Reservation deposit
- Asking price
- $500 is not a usable sale price
Treating a deposit as the camera price would create a false bargain.
Remote iPhone Samsung Carrier Unlock Service
Digital IMEI submission service only. No physical phone is being sold. Displayed price: $35.
- Inventory
- No physical product
- Market
- Unsupported service listing
- Asking price
- $35 is not a product price
The classifier should stop before product search or pricing begins.
How I measured it
The suite contains 200 hand-authored, hand-labeled synthetic listings across 22 resale categories. A strict pass requires every check to pass. The semantic score averages six dimensions per case, so a narrow omission counts differently from a complete identity or safety failure.
- 200 reviewable cases
- The synthetic listing text and expected output live side by side in the repository. No independent second-annotator review is recorded.
- Six checks
- Category, identity, search terms, value-bearing attributes, market support, and asking-price usability. Identity, search, and attributes receive partial credit inside the semantic score.
- Two cohorts, one release gate
- The suite combines 100 frozen regression cases with 100 harder challenge cases. I used 60 challenge cases for development, kept 40 outside the editing loop, and ran the winning prompt across all 200 cases.
- Pricing safety
- The suite has 19 unusable-price cases and 8 unsupported-market cases. The retained v3 summary records one combined safety mismatch, but its original case-level checkpoint is no longer available to separate the two flags.
- Hard cases on purpose
- The set concentrates on incomplete packages, damage, financing, carrier locks, misleading prices, accessories, and ambiguous product identity.
- Text only
- Production can also receive listing photos, but every measurement in this report isolates text extraction. It does not validate image understanding.
How I improve the classifier
I treat the model, reasoning setting, and prompt as separate levers. I change one at a time, measure it against the same contract, and keep a holdout outside the editing loop.
Hold the baseline still
Every model starts with the same prompt, listing formatter, JSON schema, reasoning level, tools, and scorer. This reduces configuration differences and tests each model as a drop-in option under one contract.
Turn failures into prompt hypotheses
I group misses by package state, identity, restrictions, attributes, market support, and price usability. A prompt change must target a named failure rather than merely become longer.
Test on a small set
Candidates first run on 10 to 20 targeted cases with known passing controls, then on a fixed development cohort. Each run records the prompt fingerprint, tokens, dollars, and latency.
Keep the holdout out of editing
Only the strongest candidate reaches cases that prompt authors did not use while editing. The winner then faces the complete 200-case release gate.
I reject candidates that increase guardrail mismatches. Otherwise I prioritize strict correctness, use the semantic score to understand the severity of misses, check the locked holdout, and then compare cost and tail latency.
What changed with prompt v3
Prompt v3 makes package state, restrictions, identity, and price rules explicit. It passed 18 more listings on the full release gate and cut attribute misses from 70 to 50. The locked holdout also improved from 14/40 to 21/40.
| Prompt | Strict passes | Semantic score | Development | Locked holdout | Guardrail mismatches | Average | P95 | Observed / 1K | Cold / 1K |
|---|---|---|---|---|---|---|---|---|---|
| Baseline2ca71c9c3894 | 117/200 | 94.82% | 22/60 | 14/40 | 2 mismatches | 2.89s | 4.80s | $0.45 | $0.51 |
| Production v374c46c57d079 | 135/200 | 96.79% | 35/60 | 21/40 | 1 mismatch | 2.99s | 5.11s | $0.38 | $0.65 |
The current model check
I reran Luna and Gemini 3.7 Flash on the same 200 cases with prompt v3, low reasoning, no tools, and the same scorer. Gemini passed 47 fewer cases, cost 5.98 times more, and had 4.38 times higher P95 latency. Its run also encountered eight capacity errors.
| Model | Strict passes | Semantic score | Observed cost / 1K | Average | P95 | Guardrail mismatches | Availability |
|---|---|---|---|---|---|---|---|
| Lunagpt-5.6-luna · low reasoning | 136/200 | 96.84% | $0.3774 | 3.99s | 7.52s | 1 mismatch | No interruptions |
| Gemini 3.7 Flashgemini-3.7-flash · low thinking | 89/200 | 93.70% | $2.2562 | 7.47s | 32.92s | 5 mismatches | 8 capacity errors |
Run accounting
| Model | Input tokens | Cached input | Output tokens | Reasoning tokens | Run spend | Cost basis |
|---|---|---|---|---|---|---|
| Lunagpt-5.6-luna · low reasoning | 322,484 | 303,420 | 54,666 | 6,504 | $0.075480 | Published-rate estimate |
| Gemini 3.7 Flashgemini-3.7-flash · low thinking | 283,848 | 0 | 63,559 | 2,867 | $0.451232 | Published-rate estimate |
The production choice
I kept Luna with prompt v3 for the tested text path. A fresh repeat passed 136 cases and made no asking-price mistakes. Its one guardrail mismatch was conservative: it marked a deposit listing unsupported while still refusing the deposit as a usable price.
Measured result: 136/200 strict passes · 96.84% semantic score · $0.65 cold per 1,000 text classifications · 0/19 price traps missed.
Method and limits
This is a practical engineering benchmark for structured extraction from listing text, not an academic benchmark or a test of each provider's full platform.
- Prompt identity
- Current release runs use SHA-256 prompt fingerprints. Production v3 is 74c46c57d079; the baseline is 2ca71c9c3894.
- Evaluation identity
- The current Luna and Gemini comparison is bfa83589a1d3. The earlier prompt-development gate is c63ad64bf1c9. Both fingerprints cover the prompt, scorer, category resolver, schema, and fixtures.
- Interpretation
- The 135/200 score is a release-gate result, not a production-accuracy estimate. The locked holdout improved from 14/40 to 21/40, which is consistent with improvement beyond the 60 development cases, but the holdout is now known and cannot remain untouched for future prompt studies.
- Reasoning
- The current Luna run used low reasoning and Gemini used low thinking.
- Sampling
- Temperature and top-p were not set, so provider defaults applied.
- Output
- Every model returned the same strict structured JSON schema.
- Execution
- Luna used five concurrent cases and completed without interruption. Gemini used two, produced eight 503 capacity errors, and needed one manual restart after a stalled attempt. Successful cases were checkpointed by listing ID.
- Latency
- Average and P95 latency are operational measurements from one hosted run, not a maximum-throughput claim.
- Scope
- Photos, web search, grounding, and external tools were disabled. The results apply to these 200 text-only cases across 22 categories.
- Cost
- Successful-call tokens were priced at the providers' current Standard rates.