All work
Dukaan Dost · Engineering case study

Packing lists

Handwritten textile packing lists in, structured rows out — with two models checking each other, because one was never going to be trusted.

Role
Acting CTO — architecture, build, rollout
Timeline
2024 – ongoing
Stage
In production · every dispatch, every day
Outcome
~90% of manual data entry removed
The OCR review queue showing extracted rows against the source document
Extraction beside the original, so a reviewer checks rather than retypes
The problem

The data existed. It was on paper, in someone's handwriting.

Every dispatch produced a handwritten packing list. Someone then retyped it into the ERP — roll numbers, colours, quantities, buyer — line by line, every day. It was the single largest manual cost in the operation and the single largest source of bad inventory data, because a typo at that step propagated into stock, orders and invoicing.

The obvious answer was OCR. The obvious answer did not work. Mixed Hindi and English handwriting on creased carbon-copy paper defeated every single-model pipeline we tried — not by failing loudly, which would have been fine, but by returning confident, plausible, wrong numbers.

Every
dispatch produced a sheet that was retyped by hand
1 typo
propagated into stock, orders and invoicing
Silent
failures — wrong numbers returned with high confidence
What shipped

Before, and after

01
Entry
Photograph the sheet, review the diffs
Retype every line by hand
02
Manual effort
~90% removed
Full transcription, every dispatch
03
Trust
Two models must agree, or a human is asked
One pair of eyes, late in the day
04
Failure mode
Disagreement surfaces as a review item
A confident wrong number, found weeks later
05
Throughput
Async on BullMQ — the operator does not wait
Blocking, at the speed of typing
The decisions

What got chosen, and what got refused

The direction I killed — one model, half the price

A single vision model was cheaper and simpler, and it was good enough that the demo looked finished. It was not good enough that anyone would stop checking its output. A tool people double-check has saved nobody any time — it has just moved the work from typing to proofreading. I killed it, because the whole value of the module was people trusting it enough to walk away.

Single-model extraction output with no cross-check
KilledThe cheaper pipeline, abandoned — plausible and wrong

Two models, cross-checked

GPT-4 Vision and Claude read the same document independently and their structured output is compared field by field. Agreement is accepted. Disagreement becomes a review item with both readings shown. This does not make either model better; it makes their failures visible, which is the only property that mattered.

Field-level comparison of two model outputs
Where the two readings differ, a human decides

Asynchronous, so nobody waits

Extraction runs as a BullMQ job rather than in the request. The operator photographs the sheet and carries on; results land in a review queue. Making it synchronous would have tied the warehouse's pace to inference latency and to whether an upstream API was having a good afternoon.

Where it got hard

The parts that fought back

Confidence is not accuracy

Both models return high confidence on text they have hallucinated. Per-field confidence scores were useless as a trust signal on their own — cross-model agreement turned out to be the only reliable one.

The paper is the adversary

Carbon copies, folds, smudges, and sheets photographed at an angle in bad warehouse light. A meaningful share of the engineering was normalising the input before any model saw it.

Trust had to be earned once

The first month ran with full human review on every document even where the models agreed, purely to build the evidence that agreement meant correct. Skipping that would have saved a month and cost the rollout.

What I learned
  1. 01

    The cheapest model that people do not trust costs more than the expensive one they do.

  2. 02

    Design for the failure you can see. Two models disagreeing is a workflow; one model being wrong is a silent liability.

  3. 03

    Automation that removes 90% of a task and leaves the rest visible beats automation that claims 100% and hides its mistakes.

More work

Still scrolling? Let's talk.

hiteshpal.8097@gmail.com