Skip to content

About

Indic document harness + AutoOpt mer/compile/solve loop (CPU). Golden-set eval and labelled scans.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

IndicQuant

India's paperwork and class-board LPs are small, local, and checkable. IndicQuant is a CPU harness for that: Indic document extractors with tests, plus AutoOpt (arXiv:2510.21436) as a checked loop — image → mathematical understanding → latex → optimization IR → validation → code generation → solver selection → optimize → independent verification. Not image-to-answer. A tiny CNN+CTC is trained here and shipped as ONNX int8. This machine does not train or serve a 30B VLM, AutoOpt-M1 (393M), or DeepSeek-Coder 1.3B.

Identity numbers in evals/ are SAMPLE / fake.

Walkthrough

Results (measured here)

CLI, CPU — uv run indicquant autoopt --sample opt_lp2 then uv run indicquant eval --suite autoopt:

CLI AutoOpt + eval

opt_lp2 vertex-lp, (x=2, y=3), objective 18.0, sub-ms
documents golden set field accuracy 1.0 on the labelled rows (hi/ta/te/kn/bn)
autoopt golden set 10/10, including incomplete + infeasible checkpoints
tiny MER 56,021 params, int8 65 KB, ~8 ms/page; 31.1% CER on 64 held-out lines (256 train lines, zero overlap)
photos 11 phone shots of the SAMPLE sheet on a laptop screen (evals/photos/real/); 2 synthetic JPEGs stay labelled as such
pytest uv run pytest -q

Live Compose (http://127.0.0.1:7861) is postgres + redis; uv run indicquant serve is the single-process UI.

Per-field tables, CER, and confusion: uv run indicquant eval, uv run indicquant eval --suite scans, uv run indicquant eval --suite mer, uv run indicquant eval --suite photos. Paper protocol: docs/comparison.md. On-device envelope: docs/BENCHMARKS.md. Architecture: ARCHITECTURE.md.

Snapshots

UI and job JSON live under results/demo/.

File What
walkthrough.gif skim: PAN → Aadhaar → GST → AutoOpt → CLI
00_testing_report.png pytest + evals
02_pan_extract.png PAN hi → JSON
06_aadhaar.png Aadhaar hi
03_autoopt_lp2.png mer checkpoint + obj 18

Data

Golden sets are the test distribution. Adding rows raises coverage without a GPU.

Set Path Notes
Documents evals/documents.json hi, ta, te, kn, bn, native digits, IGST, two-page GST, DL
AutoOpt evals/autoopt.json LP, LaTeX, BOBD, equality, compile fail, infeasible
Scans evals/scans.json + evals/scans/* labelled pages, ocr_noise, camera-style JPEGs; grammar compile-solve
MER split evals/mer_split.json 256 train / 64 held-out synthetic lines + 12 scan-instance strings, zero overlap
Photos evals/photos/ 11 phone photos of the SAMPLE sheet on a laptop screen + 2 JPEG-degraded renders. Not printed paper. IDs are fake.

A scanned AutoOpt-11k dump would be the next data step. It needs their 11k pages, not this laptop.

Tiny MER (trained here)

Same loop: understand → latex → IR → validate → codegen → select solver → optimize → verify. Grammar repair still sits in front of the IR. CTC is an extra, measured path. There is no image-to-answer shortcut.

Split (auditable in evals/mer_split.json): trained on 256 unique synthetic LP lines (seed 7). Evaluated on 64 held-out synthetic lines (seed 123) plus 12 scan-instance strings from evals/scans.json. Zero string overlap. Shared boilerplate (subject to, x >= 0, y >= 0, p >= 0, q >= 0) is train-only and may still appear on eval pages.

Piece What shipped What it is not
Pages evals/scans/* + gold in scans.json AutoOpt-11k
Grammar MER mer.recognise — sense + ≤ / s.t. a net
Tiny CTC CNN+CTC → ONNX fp32/int8 ResNet+Swin+Nougat 393.3M
Metric CER + compile-solve paper BLEU on 11k
uv sync --extra mer --extra train
uv run python scripts/train_mer_ctc.py --steps 1200
uv run python scripts/eval_mer_cer.py
uv run python scripts/bench_mer.py
uv run indicquant eval --suite scans
uv run indicquant eval --suite mer

Held-out CTC: 31.1% CER (0.3114 micro) on 64 lines; 37.0% CER on the 12 scan-instance strings. Grammar MER on stored ocr_noise still compile-solves 8/8. Full-page CTC is not AutoOpt-M1. Source: results/mer/cer.json.

Pipelines

document  ingest → split → preprocess → infer → validate → assemble
autoopt   ingest → preprocess → understand → latex → ir → validate
          → codegen → select_solver → optimize → verify
flowchart LR
  img["image"] --> understand["mathematical understanding"]
  understand --> latex["latex"]
  latex --> ir["optimization IR"]
  ir --> val["validation"]
  val -->|incomplete| stop["stop"]
  val --> codegen["code generation"]
  codegen --> pick["solver selection"]
  pick --> opt["optimize"]
  opt --> verify["independent verification"]
Loading

GST validate: taxable + cgst + sgst + igst ≈ total. The AutoOpt IR fails closed-loop if min/max or constraints are missing. Solver selection is vertex-lp (≤2 linear vars) or bobd-grid (quadratic / extra vars). Verify re-evaluates the IR at (x) and rejects a lying objective.

Run

uv venv --python 3.11 && uv pip install -e '.[dev,mer]'
uv run indicquant extract --sample pan_hi
uv run indicquant autoopt --sample opt_lp2
uv run indicquant eval
uv run indicquant eval --suite autoopt
uv run indicquant eval --suite scans
uv run indicquant eval --suite mer
uv run indicquant eval --suite photos
uv run pytest -q

UI: uv run indicquant serve → http://127.0.0.1:7860
Compose: docker compose up --build → http://127.0.0.1:7861.

curl -s http://127.0.0.1:7861/api/jobs -H 'content-type: application/json' -d '{"sample_id":"opt_lp2"}'

What still improves this

  1. Printed paper (or more phone shots). We now have 11 phone photos of the SAMPLE sheet on a laptop screen (evals/photos/real/). That is not a field dump and not printed paper. More angles of paper would still help.
  2. A better line CTC — more synthetic data, still CPU, still ONNX. Keep compile as the checkpoint. Held-out CER is 31.1%; that is the number to beat.
  3. Optional HiGHS/CBC behind M2; vertex/BOBD stays the no-dep path.

What we will not do on this laptop: train 393M Nougat or fine-tune 1.3B DeepSeek-Coder.

Kaggle

uv run python scripts/push_kaggle.py

Layout

evals/documents.json          document golden set
evals/autoopt.json            AutoOpt golden set
evals/scans.json              labelled pages + grammar CER
evals/mer_split.json          256/64 CTC split, zero overlap
evals/photos.json             11 phone-of-screen + 2 synthetic JPEGs
src/indicquant/harness/       ingest → assemble
src/indicquant/autoopt/       mer, ctc, m1–m3, ONNX weights
src/indicquant/eval/          scoring
docs/comparison.md            vs arXiv:2510.21436
docs/BENCHMARKS.md            size / CPU ms / held-out CER
results/demo/                 screenshots + walkthrough.gif
results/mer/cer.json          held-out CTC CER

About

Indic document harness + AutoOpt mer/compile/solve loop (CPU). Golden-set eval and labelled scans.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages