I'm not a professional developer — I run a small business and I'm self-taught (HTML/CSS/JS, a bit of Python). Every month I had the same chore: a pile of PDF invoices and me copying supplier, date, concept and total into a spreadsheet by hand. Boring, and full of typos.
I automated it with n8n, but with two hard rules:
- Invoices never leave my computer. They're supplier and business data — I didn't want to push them to any cloud API.
- No monthly subscription per model call.
So I ran it on Ollama locally (qwen2.5-coder:7b) instead of a paid API. It works on a normal laptop — a Ryzen 7, 16 GB RAM, no pro GPU — at ~12 s per invoice and €0 cost per run.
The flow is 7 nodes: a trigger (Gmail label "Invoices" in production) → a Code node with 3 sample invoices embedded so anyone can test it with zero setup → an HTTP Request to Ollama asking for JSON (supplier, date, concept, total) → a classifier → a summary → a Telegram ping → a slot to dump into Google Sheets.
The part that actually mattered
At first the model invented data when an invoice was blurry or badly scanned — a disaster for accounting. The fix was to ask the prompt for an extra confidence field (0 to 1) and add one simple rule:
if confidence >= 0.8 AND supplier AND total -> OK
else -> REVIEW
Now dubious invoices don't slip through: they're flagged and I check them in 10 seconds. I'd rather that than a silent €300 error. The prompt uses temperature: 0 and format: json so it doesn't ramble.
A few gotchas that cost me time
- If n8n runs in Docker, the Ollama node must point to
http://host.docker.internal:11434, notlocalhost— that's the classic "connection refused". - The first invoice is much slower (~1 min on my laptop) because Ollama loads the model into memory the first time. From the second one it's ~8–10 s. First one is the toll, then it flies.
- If everything comes back "REVIEW", your confidence threshold is too high — drop it to 0.6.
- If the PDF is a scan with no text layer, the model gets nothing — you need an OCR step first.
Two questions for anyone who's done this
- How do you handle the "REVIEW" bucket — a second pass with another model, or straight to human review like me?
- For production: Gmail Trigger, a watched folder, or a webhook?
Happy to share the full workflow JSON if it's useful. Any critique welcome — I'm more bar-counter than code. 🙂
Top comments (0)