Extracting structured data from Japanese invoices with LLMs
By Syed Mohd Haider Rizvi · Updated 18 July 2026
Reliable Japanese invoice extraction is three steps, not one: an LLM reads the document into a fixed field schema, deterministic rules validate and normalize each field, and anything uncertain is routed to a human before it is committed. The single most useful correctness check is free: the 10% consumption tax and the totals must agree, so the invoice validates its own arithmetic.
A field taxonomy for 請求書
Define the schema first, then extract into it. A workable core for a Japanese invoice:
{
"document_type": "請求書", // invoice / 見積書 / 納品書
"invoice_no": "INV-2024-0512", // 請求書番号
"issue_date": "2024-05-12", // 発行日 (和暦 normalized)
"supplier_name": "株式会社山田製作所", // 取引先 / 請求元
"subtotal": 482000, // 小計
"tax_rate": 0.10, // 消費税率 (10% or 8% reduced)
"tax": 48200, // 消費税
"total": 530200, // 合計金額
"due_date": "2024-06-30" // 支払期限
}
Typing matters: amounts are integers (yen has no minor unit in practice), dates are ISO strings, and the tax rate is explicit so a reduced-rate (軽減税率) line can be represented rather than assumed.
Why Japanese invoice layouts vary so much
There is no single invoice template in Japan. Labels differ (取引先 vs 請求先 vs お客様名), vertical and horizontal layouts both appear, company seals (印鑑) overlap text, and the same field can be a stamp, handwriting, or print. This is why pure template/positional OCR is brittle and why an LLM — which reads by meaning, not coordinates — is the right tool for the extraction step.
Confidence thresholds and human-in-the-loop routing
Every extracted field carries a confidence score. Set a threshold (say 0.80) and route anything below it — plus anything that fails a rule — to a review queue. The goal is not 100% automation; it is zero silent errors. A finance team will trust a system that says "I'm not sure about this handwritten note" far more than one that guesses.
for field in extracted:
if field.confidence < 0.80 or field.rule_failed:
queue_for_review(field) # held, with the source crop + reason
else:
commit(field) # written, with an audit-log entry
The consumption tax is a free correctness check
Unlike most extraction tasks, invoices contain their own answer key. Two cheap checks catch a large share of errors:
- →Tax rate: tax ≈ round(subtotal × rate). If the stated tax is 8% of the subtotal when you expected 10%, flag it — it may be a 軽減税率 item or an extraction error.
- →Totals: subtotal + tax = total. A mismatch means at least one number was read wrong.
These checks cost nothing at runtime and turn silent extraction mistakes into visible, reviewable flags.
Putting it together
Extraction (LLM) → normalization (和暦 dates, numbers) → validation (tax, totals) → routing (auto-commit or human review) → structured JSON/CSV with an audit log. That is exactly the Japanese invoice AI-OCR pipeline we build — and you can run it on sample invoices in the live demo.
Want this running on your own invoices, measured against an agreed accuracy target? Book a 15-minute introduction.
Related: Normalizing Japanese 和暦 (era) dates for invoice systems →