Receipt OCR options — issue #694
Research date: 21 October 2026. Related issue:
#694.
Repository reviewed: 9a25a01.
PDF follow-up
PDFs now use bounded PDFium rendering and the same PP-OCRv6/Ministral path; the serving Textract adapter and IAM permissions are removed. Local offline checks passed for synthetic three-page digital/scanned invoices, page ordering, printed amount presence and encrypted/corrupt/over-limit PDF rejection. This is not a measured PDF financial-extraction or Lambda benchmark. See the PDF implementation evidence. No additional paid calls ran; reservations remain $0.077.
Implemented follow-up
The implementation follow-up now uses PP-OCRv6 small for images and Ministral 3 8B with improved prompting, schema and deterministic validation; PDFs retain Textract. Four new model calls against saved OCR produced 4/4 exact totals and complete item-cost lists, no truncation, and 1.384 s median model-stage latency. These are development fixtures, not held-out production accuracy. Container packaging was checked locally; no Lambda was deployed. Broader validation and real Lambda measurements remain before rollout.
The same ledger now retains $0.077 after four additional $0.0055 reservations. Historical entries are unchanged; cumulative standard-rate service estimates are $0.00500723 before cache discounts. No completed calls were repeated, reservations released or ledger reset.
Original comparison recommendation and evidence
The bounded live performance comparison is complete. Neither tested alternative is ready to replace the deployed route. On the attempted receipts, both OCR→Gemma 3 configurations omitted required fields and then truncated; direct Gemma 4 got 3/4 totals and 1/4 complete item-cost lists right, with a 16.137-second median. The baseline also exposed a deterministic SDN BHD/currency bug. Retaining its deployment is not an endorsement of its measured quality.
Ten paid service calls ran in the original comparison. Reported usage at standard rates is $0.00415208 before cache discounts, not a settled bill. At that point the cumulative ledger retained $0.055, including ancillary allowance, below the existing $0.08 cap and the user's $0.10 limit. No request was repeated and no production change deployed. Local OCR benchmarks were recovered without repeating the benchmark; missing OCR text was regenerated from the original pinned weights and images. See the performance report for recovery provenance, raw results, and pricing scenarios.
PP-OCRv6 small remains a promising CPU OCR component, while direct Gemma 4 avoids native OCR packaging. Fix the shared extraction/validation weaknesses and assess a successor structurer before choosing between them. Published results below remain separate from the measured results and do not establish a production winner.
Gemma-only option
AWS's Gemma 3 4B model card
lists image/text inputs, in-region availability in us-east-1, and InvokeModel
support. It also lists the model as legacy, with EOL on 30 March 2027.
The existing adapter sends text only; that does not establish a model-level
image limitation. Image input combined with the exact response_format
request used here still needs a live compatibility check.
Include Gemma 4 E2B in the shortlist for a successor: AWS lists it as active with image input. Published us-east-1 prices are the same for Gemma 3 4B and Gemma 4 E2B: $0.04 per million input tokens and $0.08 per million output tokens. API/request compatibility must be checked separately; changing the model ID alone is insufficient evidence of compatibility.
There are several integration requirements beyond deleting a Textract call:
- The structurer uses OCR text for quantity repair, currency detection, and a deterministic fallback. Direct-image output needs its own evidence/failure handling. A schema-valid JSON response or the current minimal fallback is not a successful receipt extraction. Preserve decimal-string → minor-unit conversion, translations, discounts, and quantity expansion.
- Storage validation accepts JPEG/PNG and PDFs up to three pages and 10 MiB. A PDF needs bounded page rasterisation or an explicitly retained PDF route. Start the eval with images; retain Textract for PDFs initially. Do not remove its IAM grant while that route remains.
- The model needs image bytes in a supported request representation. Reuse bounded S3 access; cap decoded pixels, crops, and request size. Tall receipts may lose small digits when resized. Google's model card describes 896×896 image normalisation; test long receipts explicitly.
- The pipeline checkpoints a draft and
rawTextHash. Define how direct-image extraction supplies evidence and provenance without pretending an image hash is an OCR-text hash. Preserve content deduplication, leases, quota checks, and recovery behaviour.
Self-hosting Gemma in ordinary Lambda is a lower-priority option. Fitting quantised weights into memory does not establish acceptable CPU generation latency, peak memory, or cold-start cost. Bedrock already removes the need to load and serve these weights ourselves.
OCR models that could run in Lambda
These OCR alternatives still need the structurer to create an expense draft. Lambda suitability is an engineering assessment, pending an actual package and benchmark on the selected architecture.
| Candidate | Evidence and likely deployment fit | Assessment |
|---|---|---|
| PP-OCRv6 small / tiny + RapidOCR / ONNX Runtime | Paddle's CPU/ONNX results include Intel and Apple Silicon. Small favours recognition quality; tiny favours latency. RapidOCR lists v6 model routes. | First CPU candidate. Pin the detector, recogniser, dictionary, runtime, and language selection. Verify Linux ARM64 packaging; Apple Silicon results do not establish Graviton latency. |
| PP-OCRv5 mobile + RapidOCR / ONNX Runtime | Pinned Paddle documentation lists a 4.7 MB detector and 16 MB recogniser. Those are model-file sizes, excluding runtime, image processing, and working memory. | Useful pinned alternative. Choose mobile explicitly; avoid silently inheriting larger server-model defaults. |
| Tesseract 5 + tessdata_fast | CPU-native executable and language files; usable from Node through a subprocess. Official guidance covers deskewing, thresholding, segmentation, and table limitations; fast/best benchmarks show the speed trade-off. | Simple low-dependency baseline. Test receipt columns, faint thermal print, perspective, and language packs. Do not assume clean-document performance transfers to phone photos. |
| EasyOCR | Official CPU mode uses gpu=False; PyTorch and detector/recogniser weights add packaging and initialisation work. |
Plausible container-based Lambda option, lower priority than compact PP-OCR for this use case. |
| PaddleOCR-VL 0.9B family | Current upstream instructions include x64 CPU inference. Older documentation saying CPU is unsupported is insufficient for the current version. | Technically worth revisiting if simpler OCR fails; larger autoregressive inference and layout machinery require measured memory/latency. Linux ARM64 support is not established here. |
| SmolDocling 256M / Granite-Docling 258M | Docling's model catalogue lists compact document VLMs with DocTags output. | Secondary CPU experiments; converting document markup into reliable receipt amounts adds work. Model size alone is not a latency result. |
| DeepSeek-OCR / OCR-2 | Upstream OCR-2 examples use CUDA, bfloat16, and FlashAttention. | Poor fit for the existing CPU Lambda worker. A port or external GPU endpoint would need its own cost case; do not provision one for this evaluation. |
The current worker has 1,024 MB; ServiceLambda selects ARM64 and Node.js. Native OCR therefore requires packaging work, not an npm-only model swap. Prefer a small CPU container with pinned local weights, no runtime model downloads, and a model session reused across warm invocations. Consider a native subprocess or a separate OCR worker; account for both Lambdas if splitting work.
Ordinary Lambda limits include 10,240 MB memory, proportional CPU, a 15-minute timeout, 250 MB unzipped ZIP/layers, and 10 GB uncompressed container images. Use a CPU build; a container does not supply a GPU. Measure initialisation, image decoding, PDF rendering, inference, peak RSS, and total billed duration. Cap threads to allocated CPU. Check each selected weight file's licence as well as the wrapper's licence.
Published accuracy and runtime evidence
Retrieved 21 October 2026. These results have different datasets, scoring rules, and runtimes. Recognition accuracy, character error rate (CER), document QA, and exact financial-field extraction are different measurements. None is a measured success rate for TailSpend's complete expense-draft pipeline.
Receipt-specific evidence
The independent Fraunhofer/Lamarr invoice-processing preprint, Table I
directly tests gemma-3-4b-it on SROIE scanned receipts. It reports 53.79%
exact field accuracy for direct image input, versus 36.69% through its
Docling/SmolDocling text path. Gemma 3 12B achieves 66.91% with images.
The receipt fields are company, address, date, and total; this does not measure
line-item prices or quantities. It uses zero-shot prompts and minimal
normalisation, and is not a comparison with Textract → Gemma. Public-dataset
training contamination is possible. This is directly relevant negative
evidence against assuming Gemma 3 4B alone will preserve receipt quality.
ImageToTable's published metrics CSV provides a separate commercial-vendor-run comparison on 361 SROIE receipts:
| OCR runner | Character error rate ↓ | Word error rate ↓ |
|---|---|---|
| PaddleOCR | 20.45% | 32.56% |
| EasyOCR | 28.33% | 61.58% |
| Tesseract | 33.47% | 55.91% |
These are full-text edit errors, sensitive to reading order and normalisation; they are not percentages of incorrect totals. The Paddle runner uses framework defaults, without explicitly pinning small/tiny/mobile weights. Its GPU results therefore do not validate the exact Lambda candidate. The publisher's article and current CSV disagree on latency; use the CSV for the figures above and do not transfer its GPU costs to Lambda. Its field-score comparisons also depend on a regex or a different downstream LLM, not Gemma.
The independent KORIE receipt benchmark reports CER of 15.84% PaddleOCR, 17.36% EasyOCR, and 25.43% Tesseract on Korean receipt text crops. The paper describes fine-tuning the Paddle/EasyOCR baselines. This supports the importance of language/domain adaptation, rather than establishing those numbers for off-the-shelf English receipt images.
CPU trade-off within PP-OCR
Paddle's own PP-OCRv6 evaluation provides a useful comparison within one evaluation:
| Model | Recognition accuracy ↑ | Intel Xeon ONNX s/image ↓ |
|---|---|---|
| PP-OCRv6 small | 81.3% | 0.61 |
| PP-OCRv6 tiny | 73.5% | 0.22 |
| PP-OCRv5 mobile | 73.7% | 0.61 |
Accuracy is on its in-house multi-scenario recognition set. Timing is end-to-end on 200 general/document images on Xeon 8350C, including image I/O and pre/post-processing. These are vendor measurements, not Lambda cold starts. They favour small as the initial quality/cost candidate and tiny when latency matters more.
One practitioner's Lambda deployment reports Tesseract 1.9 s/page and RapidOCR 5.1 s/page on loan documents, with 103/108 and 101/108 checked values recovered respectively; Textract recovered 104/108. It uses only 11 documents, has private code, and does not adequately specify the Lambda memory/architecture for transferring the timings. It is deployment evidence, not a receipt accuracy leaderboard or a reason to assume RapidOCR will take five seconds here.
Other document models
| Candidate | Published result | Meaning and limitation |
|---|---|---|
| Gemma 4 E2B | 0.290 average edit distance on OmniDocBench 1.5 in Google's model card | Lower is better; vendor-reported general document parsing, not receipt totals. No directly comparable receipt result found for E2B. |
| PaddleOCR-VL-1.6 | 96.34 overall, text edit distance 0.0326 on OmniDocBench v1.6_full | Benchmark-maintainer results; overall combines text, tables, and formula scores. It is not 96.34% receipt accuracy or a CPU latency measurement. |
| DeepSeek-OCR 2 | 90.25 overall, text edit distance 0.050, on the same v1.6_full leaderboard | Stronger deployment requirements remain; upstream examples use CUDA. Not directly comparable with Google's v1.5 average edit distance. |
| Granite-Docling 258M / SmolDocling 256M | Full-page OCR F1 0.84 / 0.80 and OCRBench 500 / 338, respectively, in IBM's model card | Author-reported document tasks. Supports choosing Granite over the older SmolDocling for an experiment, but establishes neither receipt amounts nor Lambda speed. |
The most decision-useful gap remains a paired comparison of Textract + our structurer, PP-OCRv6 small + our structurer, and direct Gemma 4 E2B on the same receipts. Published results justify narrowing to these paths without spending money testing every model.
Cost comparison
Estimates, excluding free tiers, discounts, taxes, S3, logs, DynamoDB, retries, and baseline worker overhead. Textract's $0.0015/page first-tier rate was verified for us-east-1 in the saved regional price list. For illustration, assume 1,000 billed input and 1,000 output tokens for either model route, including image tokens where relevant:
| Route, one image page | Illustrative cost per scan | Per 1,000 scans |
|---|---|---|
| Textract + Gemma | $0.001620 | $1.62 |
| Gemma directly | $0.000120 | $0.12 |
| CPU OCR at 2 GB × 2 seconds ARM + Gemma | ~$0.000174 | ~$0.174 |
These figures are scenarios, not measurements. Image resolution/cropping can change the billed token count. The direct route saves about 93% of the first row in this scenario; CPU OCR saves about 89%.
Using Lambda's published ARM compute rate of $0.0000133334/GB-second, replacing $0.0015 of OCR breaks even at roughly 112.5 incremental GB-seconds/page: 56 seconds at 2 GB or 28 seconds at 4 GB, before request/storage overhead. Use incremental total pipeline cost: allocating more memory while waiting for Bedrock can consume some OCR savings. Cold starts and fallback calls must be included. Ten percent Textract fallback adds at least $0.00015/page on average, plus any repeated structuring.
At the issue's illustrative $10 eCPM, one rewarded view yields $0.01. Five single-page scans at $0.00162 consume $0.0081 before other costs, about 1.23× revenue/cost coverage. Five three-page scans consume $0.0231 with the same model assumption. The one-credit-per-attempt price and three-page allowance therefore matter to margins even with existing page quotas. These are revenue scenarios, not measured AdMob yields.
Completed bounded evaluation and remaining work
The runner executed the four-image, three-route plan with fail-stop rules. Both Gemma 3 routes stopped after receipt 001 truncated, so receipts 002–003 were not attempted for those routes. Gemma 4 completed all four API calls; completion did not imply correct amounts.
The canonical cumulative ledger retains two Textract reservations at $0.0015, eight model reservations at $0.0055, and $0.008 ancillary allowance, totalling $0.055. Its cap remains $0.08; no reservation was released. Keep this ledger and the saved results in every continuation. Do not repeat completed requests or increase token limits to work around truncation. The comparison is finished within its original scope.
The performance report records exact errors, observed latency/memory, rate-derived costs, Step Functions scenarios, and the recommendation. Further work should address the currency/tender and incomplete-output failures, model lifecycle, representative private receipt/PDF evidence, actual ARM64 runtime, and service integration for orchestration. Keep issue #694 open until those requirements support a replacement.