Scanned receipts in, clean records out.
A pipeline that reads real, crumpled, low-resolution receipts: several OCR passes vote on each field, small learned models pick the company, date, address and total, and validation sends anything uncertain to a person instead of the database. Every number below is measured on receipts the models never saw.
s3:ObjectCreated
Lambda container
logistic regression
95% precision target
SQS, idempotent writes
Receipt
Works best on a flat, well-lit receipt, similar to the SROIE scans (Malaysian shops).
Results
Trained on 426 receipts, tested on 200 others. A field counts as right only if it matches the label exactly (amounts and dates by value; company and address as text after upper-casing and collapsing spaces).
How it works
The expensive part of document processing isn't reading text; it's knowing when the reading is wrong. So the pipeline is built around calibrated confidence and a review queue.
OCR voting
Each receipt is read four times (Tesseract's standard and "best" models, each with two page-layout modes). They make different mistakes, so every candidate carries how many passes agree with it.
Candidates, not guesses
Dates and amounts come from patterns; company and address from lines near the top. A logistic regression per field ranks candidates on position, keywords, font size, agreement and OCR confidence.
Calibrated review
Five-fold cross-validation on the training receipts sets each field's threshold: the lowest confidence at which accepted values were at least 95% right. Below it, or failing a schema rule, the field goes to a person.
Serverless on AWS
An AWS SAM template: an encrypted private S3 inbox triggers a container Lambda (Tesseract + the models). Results go to DynamoDB with conditional writes, uncertain ones to an SQS review queue.
Least privilege
The function can read only inbox/*, write one table and send to one queue. TLS-only bucket policy, KMS encryption, no public access, non-root container, dead-letter queue and CloudWatch alarms.
Reproducible
CI downloads the dataset, retrains, re-scores the test set and fails if the published numbers drift; the Lambda image is built and run on a real receipt; the handler is tested end to end against mocked S3, DynamoDB and SQS.
Data: the SROIE 2019 receipts (ICDAR competition, corrected labels). Images on this page load from that repository.