DOC OPS: turning an invoice into a verified table
A case study: OCR, JSON-schema extraction, deterministic validation, human-in-the-loop and a benchmark on 44 synthetic documents.
Contents
Why “chat with your PDF” does not solve the job
When people hear “AI document assistant”, they usually imagine a chat: upload a PDF, ask a question, get an answer. It looks impressive in a demo. In operations it is nearly useless.
A manager does not need the answer “the total due is 5,678.26”. They need rows in a table: SKU, quantity, price, line total, VAT. And they need confidence that the data can go into accounting without checking every number by hand.
That is why DOC OPS was built as document intake, not a chat: file → verified structured data → action.
Demo: docs.webdev07.tech
Case study: portfolio.webdev07.tech/en/cases/doc-ops
What happens to a document
The pipeline has five steps.
- Ingest. PDF, JPG/PNG, DOCX or XLSX. MIME and size checks, sha256, page previews.
- Text or OCR. Text-layer PDFs go through
pdftotext. Scans and photos go to a vision model. - Extraction. The model fills a strict JSON schema: supplier, number, dates, totals, every line item.
- Validation. Plain TypeScript checks arithmetic, VAT, duplicates, date range and required fields.
- Review and export. A human sees ambiguous fields, fixes them and exports XLSX/CSV/JSON.
The key decision: extraction and validation are separate. The model does not decide whether arithmetic adds up. If 12 × 245.00 does not equal 2,890.00, code catches it, not another LLM call.
Where the model fails
On a synthetic set of 44 documents the model is good, but not perfect. In one run a low-quality scan returned no JSON at all. In another run a date on a scan was read as 2026-10-05 instead of 2026-10-06.
That is not a reason to drop the model. It is a reason not to build the process as if the model is always right.
What helps:
- Retry with the validation error. If JSON fails Zod, the model gets the list of issues and tries again.
- Fallback to a stronger vision model for scans that fail the first pass.
- Per-field confidence. Low confidence is not hidden: the field is highlighted.
- Deterministic checks. Arithmetic, VAT and duplicates do not depend on model temperature.
- Human-in-the-loop. Below the threshold a document cannot move on without a human.
What the benchmark showed
44 synthetic documents: text PDFs, scans, DOCX, XLSX, invoices with a wrong line total, a duplicate number and a missing field.
| Metric | Value |
|---|---|
| Field accuracy | 99.6% |
| Line-item accuracy | 100% |
| Documents fully correct | 43 / 44 |
| Median per document | 5.8 s |
| Estimated cost | $0.0015 / document |
| Edge cases caught | 3 / 3 |
One run produced 44/44, the control run 43/44. The case study publishes the conservative number and a note about both runs. This is synthetic data, not client data: promising the same accuracy on someone else's scans would be dishonest.
Why XLSX is parsed without a model
A price list in XLSX is already structured data. Sending it to an LLM is strange: more expensive, slower and less predictable.
Code finds the header row, maps the “SKU”, “Description” and “Price” columns, reads the rows and normalises numbers. That document is processed in fractions of a second and costs $0.
The model is needed where structure is lost: PDFs, scans, photos and DOCX tables.
What builds trust
- Page citations. Click a field and see the source fragment.
- Checks tied to fields. An error leads to a specific line, not into the void.
- Edits are saved. After confirmation the document becomes
doneand checks are recalculated. - 24-hour TTL. Uploaded files are deleted automatically; the demo uses synthetic data only.
- No public URLs. File access is by ID and a session cookie.
What comes next
The next steps are not “add another model”, but strengthen the process:
- contract version comparison;
- 1C and inbox integrations;
- custom client schemas;
- a queue with retries and audit;
- more scans and languages in the benchmark.
But the base already works: a document arrives, data is extracted, errors are caught, a human confirms, and the table moves on. That is an AI assistant that saves time instead of creating another review interface.
Related
Traffic Arbitrage in 2026: More Expensive, More Honest, More Engineering
The state of traffic arbitrage in November 2026: rising CPMs, cookie limits, AI creatives, Telegram Ads, first-party data and unit economics. What to do next.
ReadA one-screen CRM: lead intake, filters and n8n delivery
How to build a simple single-user CRM: SQLite, intake API, dedupe, AI-powered Telegram sync every 20 minutes, smart routing by 15 parameters, tasks from a plan and an n8n outbox.
ReadNeed similar automation?
Message me on Telegram — let's discuss the task and the format.