Receipt Auditor
A 1.5B model fine-tuned on a laptop sorts receipt line items into 12 categories at 90.5%
Receipt Auditor reads receipt photos, checks each total in code, strips personal data, and categorizes every line item with Qwen2.5-1.5B plus a LoRA adapter. Spending questions are answered by pandas; the language model only writes the sentence.
Top-1 accuracy, 12 categories
- Base Qwen2.5-1.5B27.7%
- Claude, zero-shot80.0%
- Qwen2.5-1.5B + LoRA90.5%
220 held-out line items from 158 merchants not seen in training, all three systems on every row. Macro-F1 0.893 against 0.770. Synthetic data only. Claude was given the 12 allowed labels in its prompt and scored by exact match. Most of its misses are rows with debatable labels, such as hardware labeled other. Rerun 2026-10-28 from a scratch directory with tools off; the first run's 56.0% ran inside the repo and was parsed from prose. The write-up has the details.
From the test set
| Item | Label | LoRA | Claude |
|---|---|---|---|
| CHEVRON #7843UNLEADED 87 10.5 GAL | fuel | fuel | fuel |
| CVS #2156FIRST AID KIT | other | other | health |
| SHELL*GAS STATIONUNLEADED 87 12.5 GAL | transport | fuel | fuel |
The labels came from the synthetic generator and are not always consistent. The fine-tune learned them, quirks included.
How it works
tesseractreads each photo; oneclaude -pcall turns the text into a validated receipt or refuses a photo that isn't one.- Line items plus tax are compared with the printed total, allowing the larger of 2 cents or 0.5%. A mismatch is flagged for review, never adjusted.
- The schema has no fields for card numbers, names or addresses; raw OCR text is discarded; a regex sweep redacts anything that slips through.
- Each line item goes to the LoRA classifier.
- A spending question is answered by a pandas query. The LLM phrases the result, and a guard checks every number survived, or falls back to a template sentence.