Data Nexus

Data · We run it ourselves

Document extraction

Reading the fields off a photographed document — passport, Emirates ID, driving licence, trade licence, vehicle registration, insurance, an odometer, an invoice — and filing them against a record.

A customer sends a photograph of a passport into a WhatsApp thread. Everything that happens next is either a data-entry job somebody does at a desk, or it is this. The interesting engineering is not the reading; it is what the system does about the parts it is unsure of.

ai.google.dev

01/Why this one

  1. 01

    Every extracted field carries a confidence score, and the threshold is a constant in the code rather than a habit. Anything below 0.9 is flagged for a person to check. A system that returns a name with no measure of how sure it is has moved the error from the model into the database, where nobody will find it until a contract carries the wrong passport number.


  2. 02

    The document is classified before it is read. A photograph arriving in a chat is not labelled, so the first question is what it is — passport, Emirates ID, driving licence, international permit, or none of them — and that answer decides both which fields to look for and what the customer's status implies. A tourist and a resident hire under different terms, and the document in the photograph is what distinguishes them.


  3. 03

    The provider sits behind an interface, so the model is replaceable. Extraction quality on Gulf documents is the fastest-moving thing in this stack, and a system that names its vendor in the application code has to be rewritten to take an improvement. A mock implementation sits behind the same interface, which is what allows the surrounding logic to be tested without spending on inference.


  4. 04

    Money is read in minor units and kept there. Line items on a service invoice come back in fils as integers, because a total assembled from floating-point currency is wrong by construction and the error only shows up in reconciliation, months later, as a number nobody can explain.


  5. 05

    The set of documents is the operational reality of the Gulf rather than a generic list. Emirates ID, Mulkiya registration and an international driving permit are not fields on an American form, and a vendor's out-of-the-box extraction has usually not seen them.


  6. 06

    The same capability transcribes a document verbatim for a retrieval knowledge base, which is the join between this and grounded answering: a contract that has been read can then be asked questions.

02/What you can check

An entry that cannot point at something you can open, run or read does not compile. That is a property of the type, not a promise in a paragraph.

In our code
carfleet/packages/integrations/src/interfaces/ocr.ts — A vendor-neutral extraction interface covering nine document types, with a CONFIDENCE_REVIEW_THRESHOLD of 0.9 that callers are required to enforce, per-field confidence, invoice line items in minor units, and a separate classifier for identifying an unlabelled chat photo.

In our code
carfleet/packages/integrations/src/impl/gemini-ocr.ts — The live implementation, alongside a mock behind the same interface so the surrounding logic is testable without inference cost.

Product we run
The operating system this runs inside, which we run ourselves — so a misread field is our support ticket, not somebody else's.Carfleet
03/Where it stops

Invariant

Extraction is a probability, never a fact. A worn Emirates ID photographed at an angle in bad light will return fields the model is not sure about, and the honest design consequence is that a human sees them — which means this reduces data entry rather than removing it, and any process costed as though it removes it will be wrong. Nor is it a document-verification system: reading what a passport says is not the same as establishing that the passport is genuine, and we do not claim the second.