Read the full writeup →

Cellar Scanner

By Jeremy Lee, WSET Level 3

27.7%

Top-1 on 40 grapes, from a tasting note with the grape name masked

A wine label scanner, and a laptop-tuned model that guesses the grape blind

Photograph a label and Cellar Scanner reads it with local OCR and Claude, retrieves similar wines from 30,000 Wine Enthusiast reviews, and writes a profile and pairings that cite only those reviews. Blind Taste Mode runs a Qwen2.5-1.5B model, LoRA fine-tuned with MLX, that names the grape from the note alone.

Blind Taste Mode, benchmarked

Held-out notes the models never saw in training. Base and LoRA were scored on a seeded 300-row subsample, Claude on the first 200 of those rows.

SystemTop-1Top-3Macro-F1Latency
Base Qwen2.5-1.5B8.7%14.3%0.0214.3 s
+ LoRA fine-tune27.7%27.7%0.25310.6 s
Claude, zero-shot23.0%30.5%0.11969.6 s

Fine-tuning tripled Top-1 over the base model. The LoRA model leads Claude on Top-1 and macro-F1 and trails it on Top-3, because it was trained to give a single answer. Its 4.7-point Top-1 lead is within sampling noise for samples this size. Grape names were masked in the 20.1% of notes that mentioned them, so the model cannot just read the answer.

Two modes

Scan
tesseract reads the label; one claude -p call rejects non-wine photos and extracts producer, grape, vintage and region; a Chroma index of 30,000 reviews returns similar wines; a second call writes a profile and pairings. Sentences that do not match a retrieved review are dropped, and a weak OCR read asks for a retake.
Blind Taste
Paste or speak a tasting note. The LoRA model guesses the grape locally, with no network call, before the reveal.
Pipeline diagram: label photo, local OCR, claude -p extraction, wine card, a 30,000-review Chroma index, a grounded recommendation and a cited profile; a separate branch sends a blind tasting note to the LoRA model, 27.7% top-1 against 8.7% for the base model.
The scan pipeline and the Blind Taste branch.

Running it

It is a local Gradio app (python app.py) with no hosted demo. Everything runs on the machine except the claude -p calls, which use a Claude subscription. Setup, training commands and the full benchmark are in the repository and the technical writeup.