← Selected work / 01
AuctionWire
Reading the certificate on every graded card, from whatever photo the auction house happened to post.
85% → 98%
cert-number accuracy after fine-tuning a Qwen vision model with QLoRA
95%+
accuracy on rotated cards
71
listing sources registered: auction houses, marketplaces and eBay
0
third-party OCR providers. The service replaced the paid one
The problem
A graded card is only worth what its slab says. To trust a listing, AuctionWire needs the grader, the certificate number and the grade, and they have to belong to this card.
AuctionWire gathers graded trading-card listings from dozens of auction houses and eBay into one place. The photos are whatever each house posted: small, rotated, glare on the plastic, sometimes the back of the slab first. Every grader prints its label differently, and the certificate formats differ too. PSA uses 8 to 10 digits, BGS 10 to 11 with leading zeros, and SGC 7 to 10 with an optional dash.
The failure that matters isn't a card we can't read. It's a card we read confidently and wrongly: a plausible cert that belongs to some other card silently attaches the wrong population, sales history and value. So the system had to be built around verification, not just recognition.
How a card is read
Six steps, in order, stopping at the first one that settles the card.
-
1
Fetch the image
Download the listing photo, retrying through a proxy or a headless browser for hosts that block plain clients. Downscale to the model's image budget. If the first image shows no slab, try the next.
-
2
Read the label
A fine-tuned Qwen vision model returns grader, cert, grade, year, brand, player and card number as JSON, with a confidence. It is told to read the grader's name, not guess from label colour.
-
3
Guard the cert
Reject certs that can't belong to this card before spending a registry call: placeholder values, wrong formats, and “attractor” certs the model tends to write onto unrelated cards.
-
4
Verify with Gemrate
Look the cert up in the Gemrate registry and compare its grade with the label's. For PSA and SGC a contradiction fails the read; dual-graded slabs count either grade.
-
5
Escalate
If the read fails, is unsure, or the cert isn't found, a larger 30B vision model re-reads it. Then comes a registry search by the card's title. What's still unresolved goes to a person.
-
6
Store one record
Write one verified record per listing: the label's reading plus Gemrate's full record of the cert, including set, parallel, subgrades and population.
Guarding against confident mistakes
Vision models don't just fail to read. Some numbers they love to write, and those numbers turn up on cards they don't belong to.
- Attractor certs. Any cert seen on 25 or more distinct cards is treated as suspect. The list is relearned from the corpus every 12 hours and cached, so startup never waits for it.
- Placeholders and formats. Values like 1000000000 or 8888888888 are rejected outright, and each grader's cert shape is enforced.
- Grade agreement. A cert that exists but disagrees with the label's grade is usually another card. Enforcing this for PSA showed that 64.7% of the PSA certs that still disagreed were exactly that.
- One outcome per read. Every read ends in exactly one named state: verified, verified by title, not found, grade mismatch, consensus, low confidence, no slab, or queued for review. Nothing is silently “probably fine”.
Evaluated like code
Any change to the prompt, model, adapter or image budget runs against a frozen eval set and is compared with the production baseline. The gate fails the change if cert accuracy on real slabs drops more than a point overall, or more than three for any grader with 30 or more cards. It also fails if more real slabs get answered “no slab”.
The set is 615 production images, with Gemrate's record as ground truth for every slab. It over-weights the hard cases on purpose: 165 of them are cards that only the fallback model, a retry or a person got right.
The larger 30B model is faster, but it fails the gate. Its BGS cert accuracy is 7.7 points lower and it misses 2.6% of slabs, so it stays the fallback and the fine-tuned model reads first.
| Metric | Fine-tuned (prod) | 30B fallback |
|---|---|---|
| Cert exact, real slabs | 95.4% | 95.0% |
| Grade | 93.3% | 92.9% |
| Real slabs missed | 0.0% | 2.6% |
| No-slab images correct | 100% | 100% |
| Median latency | 4.5 s | 3.0 s |
Live first, backlog ahead
Ahead of time
A background worker reads the backlog across every source, so most cards are already verified before anyone opens them.
Live comes first
When a user opens a card, the live request pauses the backlog's next model call. Concurrent requests for the same listing merge into one, and stored results answer instantly. Load tested at p95 5.8 s with four calls running at once.
People close the loop
Cards neither model can settle land in a review console: approve, correct, mark “no slab” or reject. Every review is stored as a training sample for the next fine-tune.
What's still hard
- Accuracy depends on the source. Label fields are 89–96% right on eBay but far lower on some auction houses, mostly because of tiny photos and autograph slabs.
- Autograph slabs carry their own cert series, so a correct-looking read can land on a real but different cert. Grade enforcement now catches the PSA share of these.
- Some fields never come from the label at all. Set name, parallel and subgrades are taken from the registry once a cert is verified.