Invoice extraction
Pull the fields you need out of an invoice (text or a scanned image), typed and validated, with a calibrated check on each value. Only the uncertain fields go to a person.
from simoai import Client, Extract, Fill, Noul, image
c = Client()
FIELDS = {
"invoice_no": Extract("the invoice number, exactly as written", max_tokens=16),
"date": Extract("the invoice date, exactly as written", max_tokens=16),
"vendor": Extract("the name of the company that issued the invoice", max_tokens=24),
"total": Fill("the total amount due, in the invoice's currency", kind="number"),
"currency": Fill("the currency code, e.g. USD or EUR", pattern=r"[A-Z]{3}", max_tokens=4),
"items": Extract("every line item description", many=True, max_tokens=256),
"paid": Noul("The invoice is marked as paid"),
}
def read_invoice(path: str) -> dict:
r = c.ask({"invoice": "<image:1>"}, FIELDS, media=[image(path)], self_check=True)
out, review = {}, []
for name, a in r.answers.items():
out[name] = a.result
check = a.raw.get("check") # set on Fill / Extract with self_check
if (check is not None and check < 0.9) or a.raw.get("valid") is False:
review.append(name)
return {"fields": out, "review": review, "cost": r.cost_usd}
print(read_invoice("invoice-0193.png"))
# {'fields': {'invoice_no': 'INV-0193', 'date': '3 Oct 2026', 'total': 1240.5, 'currency': 'EUR',
# 'items': ['Design review (8h)', 'Hosting, October'], 'paid': False, ...},
# 'review': [], 'cost': 4.1e-05}{
"model": "simo-1-pro",
"state": {"invoice": "<image:1>"},
"media": [{"type": "image", "data": "data:image/png;base64,..."}],
"questions": {
"invoice_no": {"type": "extract", "instructions": "the invoice number, exactly as written", "kind": "text", "many": false, "max_tokens": 16},
"date": {"type": "extract", "instructions": "the invoice date, exactly as written", "kind": "text", "many": false, "max_tokens": 16},
"total": {"type": "fill", "instructions": "the total amount due, in the invoice's currency", "kind": "number", "max_tokens": 16},
"currency": {"type": "fill", "instructions": "the currency code, e.g. USD or EUR", "kind": "text", "pattern": "[A-Z]{3}", "max_tokens": 4},
"items": {"type": "extract", "instructions": "every line item description", "kind": "text", "many": true, "max_tokens": 256},
"paid": {"type": "noul", "instructions": "The invoice is marked as paid"}
},
"options": {"self_check": 1}
}Why it works
- Typed output.
kind="number"always parses to a number andpatternforces a three-letter code, so there is no cleanup step. - A calibrated check per field.
self_checkaddscheck, the probability the value is right. Unlikeconfidence, you can threshold it. - Text works too. For a text invoice, put the text in the state instead of
<image:1>and dropmedia.