verifydoc 0.2.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. verifydoc-0.4.0/.github/ISSUE_TEMPLATE/bug_report.md +25 -0
  2. verifydoc-0.4.0/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  3. verifydoc-0.4.0/.github/pull_request_template.md +11 -0
  4. {verifydoc-0.2.0 → verifydoc-0.4.0}/.gitignore +8 -0
  5. {verifydoc-0.2.0 → verifydoc-0.4.0}/CHANGELOG.md +40 -0
  6. verifydoc-0.4.0/CITATION.cff +17 -0
  7. verifydoc-0.4.0/CODE_OF_CONDUCT.md +32 -0
  8. verifydoc-0.4.0/CONTRIBUTING.md +55 -0
  9. {verifydoc-0.2.0 → verifydoc-0.4.0}/Makefile +7 -1
  10. {verifydoc-0.2.0 → verifydoc-0.4.0}/PKG-INFO +59 -18
  11. {verifydoc-0.2.0 → verifydoc-0.4.0}/PROJECT.md +3 -10
  12. {verifydoc-0.2.0 → verifydoc-0.4.0}/README.md +52 -17
  13. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/datasets/cord.py +57 -11
  14. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/datasets/funsd.py +1 -0
  15. verifydoc-0.4.0/configs/cord-apivlm.yaml +13 -0
  16. verifydoc-0.4.0/configs/cord-paddleocr.yaml +15 -0
  17. verifydoc-0.4.0/configs/cord-rapidocr.yaml +11 -0
  18. verifydoc-0.4.0/configs/funsd-paddleocr.yaml +9 -0
  19. verifydoc-0.4.0/configs/funsd-rapidocr.yaml +9 -0
  20. verifydoc-0.4.0/docs/REAL_MODELS.md +77 -0
  21. verifydoc-0.4.0/docs/how-it-works.md +57 -0
  22. verifydoc-0.4.0/examples/README.md +25 -0
  23. verifydoc-0.4.0/examples/invoice.txt +8 -0
  24. verifydoc-0.4.0/examples/invoice_schema.json +12 -0
  25. verifydoc-0.4.0/paper/generated/REAL_MODELS_RESULTS.md +60 -0
  26. verifydoc-0.4.0/paper/generated/calibration.tex +37 -0
  27. verifydoc-0.4.0/paper/generated/conformal.tex +19 -0
  28. verifydoc-0.4.0/paper/generated/cord/calibration.tex +37 -0
  29. verifydoc-0.4.0/paper/generated/cord/conformal.tex +19 -0
  30. verifydoc-0.4.0/paper/generated/cord/extraction.tex +8 -0
  31. verifydoc-0.4.0/paper/generated/cord/grounding.tex +8 -0
  32. verifydoc-0.4.0/paper/generated/cord/selective.tex +13 -0
  33. verifydoc-0.4.0/paper/generated/cord-paddleocr/calibration.md +34 -0
  34. verifydoc-0.4.0/paper/generated/cord-paddleocr/calibration.tex +37 -0
  35. verifydoc-0.4.0/paper/generated/cord-paddleocr/conformal.md +16 -0
  36. verifydoc-0.4.0/paper/generated/cord-paddleocr/conformal.tex +19 -0
  37. verifydoc-0.4.0/paper/generated/cord-paddleocr/extraction.md +5 -0
  38. verifydoc-0.4.0/paper/generated/cord-paddleocr/extraction.tex +8 -0
  39. verifydoc-0.4.0/paper/generated/cord-paddleocr/grounding.md +5 -0
  40. verifydoc-0.4.0/paper/generated/cord-paddleocr/grounding.tex +8 -0
  41. verifydoc-0.4.0/paper/generated/cord-paddleocr/selective.md +10 -0
  42. verifydoc-0.4.0/paper/generated/cord-paddleocr/selective.tex +13 -0
  43. verifydoc-0.4.0/paper/generated/cord-rapidocr/calibration.md +34 -0
  44. verifydoc-0.4.0/paper/generated/cord-rapidocr/calibration.tex +37 -0
  45. verifydoc-0.4.0/paper/generated/cord-rapidocr/conformal.md +16 -0
  46. verifydoc-0.4.0/paper/generated/cord-rapidocr/conformal.tex +19 -0
  47. verifydoc-0.4.0/paper/generated/cord-rapidocr/extraction.md +5 -0
  48. verifydoc-0.4.0/paper/generated/cord-rapidocr/extraction.tex +8 -0
  49. verifydoc-0.4.0/paper/generated/cord-rapidocr/grounding.md +5 -0
  50. verifydoc-0.4.0/paper/generated/cord-rapidocr/grounding.tex +8 -0
  51. verifydoc-0.4.0/paper/generated/cord-rapidocr/selective.md +10 -0
  52. verifydoc-0.4.0/paper/generated/cord-rapidocr/selective.tex +13 -0
  53. verifydoc-0.4.0/paper/generated/extraction.tex +8 -0
  54. verifydoc-0.4.0/paper/generated/funsd/calibration.tex +37 -0
  55. verifydoc-0.4.0/paper/generated/funsd/conformal.tex +19 -0
  56. verifydoc-0.4.0/paper/generated/funsd/extraction.tex +8 -0
  57. verifydoc-0.4.0/paper/generated/funsd/grounding.tex +8 -0
  58. verifydoc-0.4.0/paper/generated/funsd/selective.tex +13 -0
  59. verifydoc-0.4.0/paper/generated/funsd-paddleocr/calibration.md +34 -0
  60. verifydoc-0.4.0/paper/generated/funsd-paddleocr/calibration.tex +37 -0
  61. verifydoc-0.4.0/paper/generated/funsd-paddleocr/conformal.md +16 -0
  62. verifydoc-0.4.0/paper/generated/funsd-paddleocr/conformal.tex +19 -0
  63. verifydoc-0.4.0/paper/generated/funsd-paddleocr/extraction.md +5 -0
  64. verifydoc-0.4.0/paper/generated/funsd-paddleocr/extraction.tex +8 -0
  65. verifydoc-0.4.0/paper/generated/funsd-paddleocr/grounding.md +5 -0
  66. verifydoc-0.4.0/paper/generated/funsd-paddleocr/grounding.tex +8 -0
  67. verifydoc-0.4.0/paper/generated/funsd-paddleocr/selective.md +10 -0
  68. verifydoc-0.4.0/paper/generated/funsd-paddleocr/selective.tex +13 -0
  69. verifydoc-0.4.0/paper/generated/funsd-rapidocr/calibration.md +34 -0
  70. verifydoc-0.4.0/paper/generated/funsd-rapidocr/calibration.tex +37 -0
  71. verifydoc-0.4.0/paper/generated/funsd-rapidocr/conformal.md +16 -0
  72. verifydoc-0.4.0/paper/generated/funsd-rapidocr/conformal.tex +19 -0
  73. verifydoc-0.4.0/paper/generated/funsd-rapidocr/extraction.md +5 -0
  74. verifydoc-0.4.0/paper/generated/funsd-rapidocr/extraction.tex +8 -0
  75. verifydoc-0.4.0/paper/generated/funsd-rapidocr/grounding.md +5 -0
  76. verifydoc-0.4.0/paper/generated/funsd-rapidocr/grounding.tex +8 -0
  77. verifydoc-0.4.0/paper/generated/funsd-rapidocr/selective.md +10 -0
  78. verifydoc-0.4.0/paper/generated/funsd-rapidocr/selective.tex +13 -0
  79. verifydoc-0.4.0/paper/generated/grounding.tex +8 -0
  80. verifydoc-0.4.0/paper/generated/selective.tex +13 -0
  81. verifydoc-0.4.0/paper/main.tex +167 -0
  82. verifydoc-0.4.0/paper/refs.bib +35 -0
  83. {verifydoc-0.2.0 → verifydoc-0.4.0}/pyproject.toml +3 -1
  84. verifydoc-0.4.0/scripts/tables_to_latex.py +87 -0
  85. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_pipeline.py +106 -3
  86. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_types.py +13 -0
  87. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/__init__.py +1 -1
  88. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/__init__.py +1 -0
  89. verifydoc-0.4.0/verifydoc/adapters/api_vlm.py +172 -0
  90. verifydoc-0.4.0/verifydoc/adapters/paddleocr_vl.py +99 -0
  91. verifydoc-0.4.0/verifydoc/adapters/rapidocr.py +94 -0
  92. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/text_search.py +6 -2
  93. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/harness.py +6 -2
  94. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/types.py +2 -0
  95. verifydoc-0.2.0/CLAUDE.md +0 -51
  96. verifydoc-0.2.0/configs/cord-paddleocr.yaml +0 -14
  97. verifydoc-0.2.0/docs/REAL_MODELS.md +0 -61
  98. verifydoc-0.2.0/paper/main.tex +0 -90
  99. verifydoc-0.2.0/verifydoc/adapters/api_vlm.py +0 -97
  100. verifydoc-0.2.0/verifydoc/adapters/paddleocr_vl.py +0 -50
  101. {verifydoc-0.2.0 → verifydoc-0.4.0}/.github/workflows/ci.yml +0 -0
  102. {verifydoc-0.2.0 → verifydoc-0.4.0}/.github/workflows/release.yml +0 -0
  103. {verifydoc-0.2.0 → verifydoc-0.4.0}/.pre-commit-config.yaml +0 -0
  104. {verifydoc-0.2.0 → verifydoc-0.4.0}/LICENSE +0 -0
  105. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/__init__.py +0 -0
  106. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/card.md +0 -0
  107. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/datasets/__init__.py +0 -0
  108. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/datasets/synthetic.py +0 -0
  109. {verifydoc-0.2.0 → verifydoc-0.4.0}/benchmark/labeling/guide.md +0 -0
  110. {verifydoc-0.2.0 → verifydoc-0.4.0}/configs/cord.yaml +0 -0
  111. {verifydoc-0.2.0 → verifydoc-0.4.0}/configs/demo.yaml +0 -0
  112. {verifydoc-0.2.0 → verifydoc-0.4.0}/configs/funsd.yaml +0 -0
  113. {verifydoc-0.2.0 → verifydoc-0.4.0}/docs/USP.md +0 -0
  114. {verifydoc-0.2.0 → verifydoc-0.4.0}/docs/demo.gif +0 -0
  115. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/calibration.md +0 -0
  116. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/conformal.md +0 -0
  117. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/calibration.md +0 -0
  118. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/conformal.md +0 -0
  119. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/extraction.md +0 -0
  120. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/grounding.md +0 -0
  121. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/rc_curves.png +0 -0
  122. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/reliability.png +0 -0
  123. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/selective.md +0 -0
  124. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/cord/summary.json +0 -0
  125. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/extraction.md +0 -0
  126. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/calibration.md +0 -0
  127. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/conformal.md +0 -0
  128. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/extraction.md +0 -0
  129. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/grounding.md +0 -0
  130. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/rc_curves.png +0 -0
  131. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/reliability.png +0 -0
  132. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/selective.md +0 -0
  133. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/funsd/summary.json +0 -0
  134. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/grounding.md +0 -0
  135. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/rc_curves.png +0 -0
  136. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/reliability.png +0 -0
  137. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/selective.md +0 -0
  138. {verifydoc-0.2.0 → verifydoc-0.4.0}/paper/generated/summary.json +0 -0
  139. {verifydoc-0.2.0 → verifydoc-0.4.0}/scripts/make_demo_gif.py +0 -0
  140. {verifydoc-0.2.0 → verifydoc-0.4.0}/scripts/run_benchmark.py +0 -0
  141. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/__init__.py +0 -0
  142. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_calibration.py +0 -0
  143. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_calibrators.py +0 -0
  144. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_confidence.py +0 -0
  145. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_cord_loader.py +0 -0
  146. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_extraction.py +0 -0
  147. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_funsd_loader.py +0 -0
  148. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_grounding.py +0 -0
  149. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_harness.py +0 -0
  150. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_harness_extractors.py +0 -0
  151. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_learned_combiner.py +0 -0
  152. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_selective.py +0 -0
  153. {verifydoc-0.2.0 → verifydoc-0.4.0}/tests/test_stats.py +0 -0
  154. {verifydoc-0.2.0 → verifydoc-0.4.0}/ui/streamlit_app.py +0 -0
  155. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/_ocr_common.py +0 -0
  156. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/base.py +0 -0
  157. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/docling.py +0 -0
  158. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/dots_ocr.py +0 -0
  159. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/adapters/mock.py +0 -0
  160. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/__init__.py +0 -0
  161. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/base.py +0 -0
  162. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/conformal.py +0 -0
  163. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/histogram.py +0 -0
  164. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/isotonic.py +0 -0
  165. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/platt.py +0 -0
  166. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/splits.py +0 -0
  167. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/calibration/temperature.py +0 -0
  168. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/cli.py +0 -0
  169. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/__init__.py +0 -0
  170. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/combined.py +0 -0
  171. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/consensus.py +0 -0
  172. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/grounding_based.py +0 -0
  173. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/learned.py +0 -0
  174. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/token_prob.py +0 -0
  175. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/confidence/verbalized.py +0 -0
  176. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/__init__.py +0 -0
  177. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/calibration.py +0 -0
  178. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/extraction.py +0 -0
  179. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/grounding.py +0 -0
  180. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/selective.py +0 -0
  181. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/eval/stats.py +0 -0
  182. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/grounding/__init__.py +0 -0
  183. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/grounding/attach.py +0 -0
  184. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/ingest/__init__.py +0 -0
  185. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/ingest/loader.py +0 -0
  186. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/pipeline.py +0 -0
  187. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/policy/__init__.py +0 -0
  188. {verifydoc-0.2.0 → verifydoc-0.4.0}/verifydoc/policy/abstention.py +0 -0
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something isn't working as documented
4
+ labels: bug
5
+ ---
6
+
7
+ **What happened**
8
+ A clear description of the bug.
9
+
10
+ **Minimal repro**
11
+ Ideally a tiny document + schema and the `verify(...)` call or CLI command.
12
+
13
+ ```python
14
+ # your repro here
15
+ ```
16
+
17
+ **Expected vs actual**
18
+ - Expected:
19
+ - Actual:
20
+
21
+ **Environment**
22
+ - verifydoc version (`verifydoc version`):
23
+ - Python version:
24
+ - OS:
25
+ - Extractor/adapter (if relevant):
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: Feature request / new adapter or dataset
3
+ about: Propose an extractor adapter, dataset slice, signal, calibrator, or feature
4
+ labels: enhancement
5
+ ---
6
+
7
+ **What and why**
8
+ What should VerifyDoc do, and what does it enable?
9
+
10
+ **Which layer**
11
+ - [ ] Adapter (new extractor) — recall: one file in `verifydoc/adapters/`
12
+ - [ ] Dataset slice (`benchmark/datasets/`)
13
+ - [ ] Confidence signal / calibrator
14
+ - [ ] Eval metric
15
+ - [ ] Other
16
+
17
+ **Sketch (optional)**
18
+ Interface or output shape you have in mind. For metrics, include a
19
+ hand-computed expected value so it becomes a regression test.
@@ -0,0 +1,11 @@
1
+ ## What this does
2
+
3
+ Brief description. Link any issue it closes (`Closes #N`).
4
+
5
+ ## Checklist
6
+
7
+ - [ ] `make test lint typecheck` all green locally
8
+ - [ ] New/changed code has tests; metric code has a numeric regression test
9
+ - [ ] Docs updated if the public API changed (`README.md` / `PROJECT.md`)
10
+ - [ ] Conventional Commit title (`feat:` / `fix:` / `docs:` / `test:` / `bench:` …)
11
+ - [ ] If this adds a model adapter: all SDK code stays inside `verifydoc/adapters/`
@@ -37,3 +37,11 @@ outputs/
37
37
  .DS_Store
38
38
  .idea/
39
39
  .vscode/
40
+
41
+ # LaTeX build artifacts
42
+ paper/*.aux
43
+ paper/*.log
44
+ paper/*.out
45
+ paper/*.bbl
46
+ paper/*.blg
47
+ paper/main.pdf
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.4.0 — 2026-07-21
4
+
5
+ Paper-ready: fair API-VLM comparison + a compilable paper.
6
+
7
+ - **Vendor-neutral API-VLM extractor** (`verifydoc/adapters/api_vlm.py`):
8
+ OpenAI + Anthropic clients behind one `CompletionClient` protocol, with
9
+ **temperature-based k-sample sampling** so self-consistency consensus and
10
+ verbalized confidence are non-degenerate (the fair comparison the paper
11
+ needs). Harness `adapter_kwargs` passthrough; `configs/cord-apivlm.yaml`;
12
+ `ocr` and `api` install extras.
13
+ - **Compilable paper** (`paper/main.tex`) with real RapidOCR/PaddleOCR/
14
+ synthetic numbers, auto-generated LaTeX result tables
15
+ (`scripts/tables_to_latex.py`, booktabs) and `refs.bib`; `make paper`.
16
+ - **Docs**: `docs/how-it-works.md`; README documentation index; runnable
17
+ `examples/`.
18
+ - Repo hygiene: removed internal build-tooling notes; tidied PROJECT.md.
19
+
20
+ ## v0.3.0 — 2026-07-21
21
+
22
+ First **real-model** results (issue #3).
23
+
24
+ - **RapidOCR adapter** (PP-OCRv6 via ONNX Runtime) — architecture-independent,
25
+ the robust real-OCR default; runs where paddle's GPU wheels don't.
26
+ - **PaddleOCR adapter** validated end-to-end (PP-OCRv5 pipeline) on a real GPU.
27
+ - **Real results on CORD + FUNSD** for both extractors, committed under
28
+ `paper/generated/` with an honest reading (`REAL_MODELS_RESULTS.md`):
29
+ grounding/learned signals rank errors (AUROC 0.74–0.89) while
30
+ verbalized/consensus don't; grounding-conditioned gap +0.83/+0.84. The
31
+ floor field-finder's low recall forces conformal abstention at 2–5% — the
32
+ documented motivation for the selective framing.
33
+ - **Harness**: `extractor:` dispatch via the adapter registry; CORD/FUNSD
34
+ image export (`with_images`); schema `x-aliases` for on-page label variants.
35
+ - **Learned combiner** (`verifydoc/confidence/learned.py`) as a harness row.
36
+ - **Grounder ~1000× faster** (exact-match fast path, token-anchored fuzzy
37
+ scan, token-overlap for paragraph values) — FUNSD grounding hours → seconds.
38
+ - **GPU runbook** (`docs/REAL_MODELS.md`) with the hard-won version pins
39
+ (`paddlex==3.1.0`, `langchain<0.2`, Blackwell caveat, dots.ocr→vllm).
40
+ - dots.ocr: adapter stub validated to load/generate with `transformers==4.51.3`;
41
+ full run deferred to its vllm serving path (issue #3).
42
+
3
43
  ## v0.2.0 — 2026-07-21
4
44
 
5
45
  Real data, faster grounding, learned fusion.
@@ -0,0 +1,17 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use VerifyDoc or VerifyDocBench, please cite it."
3
+ title: "VerifyDoc: Calibrated, Abstaining, Grounded Document Extraction"
4
+ authors:
5
+ - family-names: Gurram
6
+ given-names: Bhaskar
7
+ repository-code: "https://github.com/bhaskargurram-ai/verifydoc"
8
+ license: Apache-2.0
9
+ version: 0.4.0
10
+ date-released: 2026-07-21
11
+ keywords:
12
+ - document-extraction
13
+ - calibration
14
+ - selective-prediction
15
+ - conformal-prediction
16
+ - grounding
17
+ - hallucination-detection
@@ -0,0 +1,32 @@
1
+ # Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We as members, contributors, and maintainers pledge to make participation in
6
+ VerifyDoc a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic
9
+ status, nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ ## Our standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ - Being respectful of differing opinions, viewpoints, and experiences
17
+ - Giving and gracefully accepting constructive feedback
18
+ - Focusing on what is best for the community and the project
19
+
20
+ Unacceptable behavior includes harassment, insulting or derogatory comments,
21
+ personal or political attacks, publishing others' private information, and
22
+ other conduct that could reasonably be considered inappropriate.
23
+
24
+ ## Enforcement
25
+
26
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
27
+ reported to the project maintainers via a GitHub issue or direct contact.
28
+ Maintainers will review and respond, and will respect the privacy and
29
+ security of the reporter.
30
+
31
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/),
32
+ version 2.1.
@@ -0,0 +1,55 @@
1
+ # Contributing to VerifyDoc
2
+
3
+ Thanks for helping build the open trust layer for document extraction. This
4
+ project is designed so contributions are small and self-contained.
5
+
6
+ ## Ground rules (the architecture makes these easy)
7
+
8
+ 1. **Adapters are isolated.** All model-specific code lives behind the
9
+ `ExtractorAdapter` interface in `verifydoc/adapters/`. **Adding a new
10
+ extractor = one new file** — nothing outside `adapters/` imports a model SDK.
11
+ 2. **Stages are independent:** ingest → adapter → confidence → calibration →
12
+ grounding → policy → report. Each has typed inputs/outputs
13
+ (`verifydoc/types.py`) and its own tests. No stage reaches into another.
14
+ 3. **The eval harness is decoupled.** It scores anything that emits
15
+ `FieldPrediction`. Never couple a metric to a specific model.
16
+ 4. **Never tune on test.** Calibration/abstention thresholds are fit only on
17
+ the dedicated calibration split (enforced by `assert_disjoint`).
18
+ 5. **No network in unit tests.** Mock adapters. Every metric gets a numeric
19
+ regression test against a hand-computed fixture.
20
+
21
+ ## Good first issues
22
+
23
+ Look for the [`good first issue`](https://github.com/bhaskargurram-ai/verifydoc/labels/good%20first%20issue)
24
+ label. Great starting points:
25
+
26
+ - **Add an extractor adapter** (Surya, GOT-OCR2.0, an API VLM) — one file in
27
+ `adapters/`, plus a normalization test (see `tests/test_pipeline.py`).
28
+ - **Add a dataset slice** (SROIE, DocILE, XFUND) — a loader in
29
+ `benchmark/datasets/` returning `BenchDocument`s, following `funsd.py`.
30
+ - **A new confidence signal or calibrator** behind the existing interfaces.
31
+
32
+ ## Dev setup
33
+
34
+ ```bash
35
+ git clone https://github.com/bhaskargurram-ai/verifydoc && cd verifydoc
36
+ uv venv .venv && uv pip install -e ".[dev]"
37
+ make test lint typecheck # all must be green
38
+ ```
39
+
40
+ ## Before you open a PR
41
+
42
+ - `ruff`, `black`, `mypy`, and `pytest` all pass (CI enforces; no PR merges red).
43
+ - New/changed code has tests; metric code has a numeric regression test.
44
+ - Public-API changes update `README.md` / `PROJECT.md`.
45
+ - Use [Conventional Commits](https://www.conventionalcommits.org/):
46
+ `feat:` `fix:` `docs:` `test:` `refactor:` `chore:` `perf:` `bench:`.
47
+ - Branch off `main`, open a PR, we squash-merge.
48
+
49
+ ## Reporting bugs / ideas
50
+
51
+ Open an issue with a minimal repro (a tiny document + schema is ideal). For
52
+ metric bugs, include the expected hand-computed value — that becomes the
53
+ regression test.
54
+
55
+ By contributing you agree your work is licensed under Apache-2.0.
@@ -1,4 +1,4 @@
1
- .PHONY: install lint format typecheck test cov results demo clean
1
+ .PHONY: install lint format typecheck test cov results paper demo clean
2
2
 
3
3
  PY ?= python
4
4
 
@@ -28,6 +28,12 @@ results:
28
28
  $(PY) scripts/run_benchmark.py --config configs/demo.yaml --out paper/generated
29
29
  $(PY) scripts/run_benchmark.py --config configs/cord.yaml --out paper/generated/cord
30
30
  $(PY) scripts/run_benchmark.py --config configs/funsd.yaml --out paper/generated/funsd
31
+ $(PY) scripts/tables_to_latex.py paper/generated
32
+
33
+ # Compile the paper (needs a LaTeX toolchain); tables come from `make results`.
34
+ paper:
35
+ $(PY) scripts/tables_to_latex.py paper/generated
36
+ cd paper && pdflatex -interaction=nonstopmode main.tex && bibtex main && pdflatex -interaction=nonstopmode main.tex && pdflatex -interaction=nonstopmode main.tex
31
37
 
32
38
  demo:
33
39
  streamlit run ui/streamlit_app.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: verifydoc
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: A trust layer for document -> structured-JSON extraction: calibrated per-field confidence, source grounding, and abstention on top of any extractor.
5
5
  Project-URL: Homepage, https://github.com/bhaskargurram-ai/verifydoc
6
6
  Project-URL: Repository, https://github.com/bhaskargurram-ai/verifydoc
@@ -226,6 +226,9 @@ Requires-Dist: pyyaml>=6.0
226
226
  Requires-Dist: scikit-learn>=1.3
227
227
  Requires-Dist: scipy>=1.11
228
228
  Requires-Dist: typer>=0.9
229
+ Provides-Extra: api
230
+ Requires-Dist: anthropic>=0.39; extra == 'api'
231
+ Requires-Dist: openai>=1.40; extra == 'api'
229
232
  Provides-Extra: data
230
233
  Requires-Dist: datasets>=2.16; extra == 'data'
231
234
  Provides-Extra: dev
@@ -235,6 +238,9 @@ Requires-Dist: pre-commit>=3.6; extra == 'dev'
235
238
  Requires-Dist: pytest-cov>=4.1; extra == 'dev'
236
239
  Requires-Dist: pytest>=7.4; extra == 'dev'
237
240
  Requires-Dist: ruff>=0.4; extra == 'dev'
241
+ Provides-Extra: ocr
242
+ Requires-Dist: onnxruntime>=1.17; extra == 'ocr'
243
+ Requires-Dist: rapidocr>=1.3; extra == 'ocr'
238
244
  Provides-Extra: pdf
239
245
  Requires-Dist: pdfplumber>=0.10; extra == 'pdf'
240
246
  Requires-Dist: pillow>=10.0; extra == 'pdf'
@@ -282,7 +288,8 @@ pip install 'verifydoc[pdf]' # + PDF/image ingestion
282
288
  ```python
283
289
  from verifydoc import verify
284
290
 
285
- result = verify("invoice.txt", schema="invoice_schema.json", k=3)
291
+ # ready-to-run sample lives in examples/
292
+ result = verify("examples/invoice.txt", schema="examples/invoice_schema.json")
286
293
  for f in result.fields:
287
294
  print(f"{f.path:12} = {f.value!r:24} conf={f.confidence:.2f} {f.decision}")
288
295
  if f.grounding:
@@ -290,10 +297,12 @@ for f in result.fields:
290
297
  ```
291
298
 
292
299
  ```bash
293
- verifydoc extract invoice.txt --schema invoice_schema.json --k 3 --threshold 0.8
300
+ verifydoc extract examples/invoice.txt --schema examples/invoice_schema.json --threshold 0.8
294
301
  streamlit run ui/streamlit_app.py # review UI: green/red fields + click-through to source
295
302
  ```
296
303
 
304
+ See [`examples/`](examples/) for the full runnable walk-through.
305
+
297
306
  Schemas are plain JSON Schema, with each leaf optionally declaring **how it is scored** (the executable-schema pattern):
298
307
 
299
308
  ```json
@@ -311,14 +320,37 @@ Schemas are plain JSON Schema, with each leaf optionally declaring **how it is s
311
320
 
312
321
  | Layer | Modules | Status |
313
322
  |---|---|---|
314
- | **Adapters** (all model code isolated here) | mock · text-search · PaddleOCR-VL · dots.ocr · Docling/MinerU output · API-VLM | ✅ |
323
+ | **Adapters** (all model code isolated here) | mock · text-search · RapidOCR · PaddleOCR · dots.ocr · Docling/MinerU output · API-VLM (OpenAI/Anthropic) | ✅ |
315
324
  | **Confidence signals** | token-prob · verbalized · consensus (k-sample voting) · grounding-based · combined | ✅ |
316
325
  | **Calibrators** (fit on a dedicated split, never test) | temperature · Platt · isotonic · histogram · **split conformal** with finite-sample risk guarantee | ✅ |
317
326
  | **Grounding** | value → page/bbox/char-span attachment with support scores | ✅ |
318
327
  | **Policy** | empirical & conformal accept thresholds for a target selective risk | ✅ |
319
328
  | **Eval harness / VerifyDocBench scorer** | Field-F1 · exact · CER/WER · ANLS · TEDS/TEDS-Struct · GriTS · omission vs hallucination · ECE/Adaptive-ECE/MCE/Brier/NLL/TCE · RC/AURC/E-AURC/Coverage@Risk/AUROC/AUPR/FPR@95 · box IoU/span-F1/grounding-conditioned correctness · bootstrap CIs + paired tests | ✅ |
320
329
 
321
- Every metric implements the exact definition in [PROJECT.md §5](PROJECT.md) with a hand-computed numeric regression test (200 tests, `eval/` coverage 98%).
330
+ Every metric implements the exact definition in [PROJECT.md §5](PROJECT.md) with a hand-computed numeric regression test (201 tests, `eval/` coverage 98%).
331
+
332
+ ## Results on real documents
333
+
334
+ Two independent real OCR extractors (**RapidOCR** and **PaddleOCR**) on real
335
+ **CORD** receipts and **FUNSD** forms, scored by the harness
336
+ ([full tables + reading](paper/generated/REAL_MODELS_RESULTS.md)):
337
+
338
+ | Confidence signal | ranks errors? | CORD AUROC (RapidOCR / PaddleOCR) |
339
+ |---|---|---|
340
+ | **learned combiner** | ✅ best | **0.89 / 0.84** |
341
+ | **grounding** | ✅ strong | 0.82 / 0.74 |
342
+ | token-probability | ~ moderate | 0.69 / 0.68 |
343
+ | verbalized / consensus | ✗ uninformative | 0.50 / 0.50 |
344
+
345
+ - **Grounding is a real trust signal:** grounded fields are **84–85% correct
346
+ vs ~1%** for ungrounded (gap ≈ +0.84; box accuracy @IoU 0.5 = 0.75–0.78).
347
+ - **The abstention layer is honest:** with a weak field-extractor the base
348
+ error rate is high, so conformal abstention at a 2–5% budget correctly
349
+ refuses to auto-accept — you report *selective risk*, not headline accuracy.
350
+ - The synthetic slice (strong extractor) shows the other end: Coverage@2% ≈ 1.0.
351
+
352
+ The thesis holds on real data: **grounding + a learned fusion rank errors;
353
+ self-reported and single-sample-consensus confidence do not.**
322
354
 
323
355
  ## The benchmark
324
356
 
@@ -328,16 +360,13 @@ make results # regenerates every table/figure in paper/generated from config
328
360
 
329
361
  The harness runs **signals × calibrators × the full metric suite** with a
330
362
  document-level calibration split (disjointness asserted in code), bootstrap
331
- CIs, and a conformal-guarantee row. The repo ships a deterministic synthetic
332
- slice that runs in CI; loaders for CORD (and next: FUNSD, SROIE, DocILE,
333
- XFUND) extend it. Sample findings on the shipped slice
334
- ([tables](paper/generated)):
335
-
336
- - **Verbalized self-confidence is badly miscalibrated** (the extractor says ~0.9 regardless of correctness) exactly the failure mode reported for RLHF'd models.
337
- - **Consensus and grounding signals rank errors near-perfectly** (AUROC ≈ 0.98): corrupted values can't be traced back to the page, so grounding support collapses.
338
- - **The conformal row holds its guarantee** on every tested α, and reports the abstention it forces.
339
-
340
- These self-checks run as unit tests — the repo's core claims are CI-enforced, not just stated.
363
+ CIs, and a conformal-guarantee row. It ships a deterministic **synthetic**
364
+ slice (runs in CI) plus **CORD** and **FUNSD** loaders with gold source boxes;
365
+ `extractor:` dispatches to any adapter (`rapidocr`, `paddleocr-vl`, …) and
366
+ `dataset:` to any slice. See the [GPU runbook](docs/REAL_MODELS.md) to
367
+ reproduce the real-model rows. Core claims (grounding beats verbalized;
368
+ conformal holds its guarantee) are also **CI-enforced as unit tests**, not
369
+ just stated.
341
370
 
342
371
  ## Why not just use the parser's own score?
343
372
 
@@ -350,9 +379,19 @@ buys you.
350
379
  ## Roadmap
351
380
 
352
381
  - [x] v0.1 — library + CLI + harness + synthetic benchmark slice + UI
353
- - [ ] CORD/FUNSD/SROIE slices with gold source boxes (VerifyDocBench v1)
354
- - [ ] Learned signal combiner + per-field-type calibration
355
- - [ ] Paper: first systematic study of confidence signals × calibration × abstention for document extraction
382
+ - [x] v0.2 — CORD + FUNSD real slices with gold boxes; learned combiner; 1000× faster grounder
383
+ - [x] v0.3 real-model results (RapidOCR + PaddleOCR on CORD/FUNSD)
384
+ - [x] v0.4 vendor-neutral API-VLM extractor (OpenAI/Anthropic) with k-sample consensus; compilable paper with auto-generated tables
385
+ - [ ] Run the API-VLM row at scale (fair verbalized + consensus comparison; needs an API key)
386
+ - [ ] dots.ocr via vllm; SROIE / DocILE / XFUND slices; human-labeled correctness + IAA
387
+ - [ ] Paper submission ([contributions welcome](CONTRIBUTING.md))
388
+
389
+ ## Documentation
390
+
391
+ - [How it works](docs/how-it-works.md) — the pipeline, the abstention idea, why grounding is a trust signal
392
+ - [Real-model results](paper/generated/REAL_MODELS_RESULTS.md) — RapidOCR + PaddleOCR numbers and reading
393
+ - [GPU runbook](docs/REAL_MODELS.md) — reproduce the real-extractor rows
394
+ - [USP audit](docs/USP.md) · [Paper draft](paper/main.tex) · [Full spec](PROJECT.md)
356
395
 
357
396
  ## Development
358
397
 
@@ -360,6 +399,8 @@ buys you.
360
399
  git clone https://github.com/bhaskargurram-ai/verifydoc && cd verifydoc
361
400
  uv venv .venv && uv pip install -e ".[dev]"
362
401
  make test lint typecheck # all green before any PR (CI enforces)
402
+ make results # regenerate benchmark tables + LaTeX
403
+ make paper # compile the paper (needs a LaTeX toolchain)
363
404
  ```
364
405
 
365
406
  Contributions welcome — see the issues tagged `good-first-issue`. All model-specific code goes in `verifydoc/adapters/`; a new extractor is one file.
@@ -1,6 +1,6 @@
1
1
  # VerifyDoc — A Trust Layer for Document → Structured-JSON Extraction
2
2
 
3
- **Project document / build spec (v1.0).** This is the single source of truth for building VerifyDoc with Claude Code. It contains the motivation, the precise problem definition, the literature-grounded evaluation methodology (the core of the paper), the system architecture, the repository layout, a six-week implementation plan, the git workflow, and the paper plan. Hand this file (plus `CLAUDE.md`) to Claude Code and build module by module against the "Definition of Done" in each section.
3
+ **Project document / design spec (v1.0).** This is the single source of truth for VerifyDoc's design. It contains the motivation, the precise problem definition, the literature-grounded evaluation methodology (the core of the paper), the system architecture, the repository layout, a six-week implementation plan, the git workflow, and the paper plan. Build module by module against the "Definition of Done" in each section.
4
4
 
5
5
  One-liner: *VerifyDoc wraps any document-extraction model and returns, for every field, a calibrated confidence score, a source-grounding box/span, and an abstain-or-accept decision — so a human reviews the 5% of fields that are actually wrong instead of eyeballing all of them.*
6
6
 
@@ -12,7 +12,7 @@ Document → structured-JSON extraction is one of the highest-volume uses of LLM
12
12
 
13
13
  That is the wedge. VerifyDoc does not compete with the parsers — it *layers on top of any of them* and adds the missing reliability contract: field-level confidence + provenance + abstention. Commercial APIs already prove the demand (Box shipped field-level confidence in Jan 2026; Azure Document Intelligence, AWS Textract, and Extend all expose per-field confidence), but no popular open-source parser leads with it. Practitioner leaderboards name exactly this unmet need: whether a reviewer can trace an uncertain value back to the page before it enters a downstream system. VerifyDoc is the open-source answer.
14
14
 
15
- Why this is a good solo project: the tool is model-agnostic and thin (it wraps existing extractors), the paper contribution is the reliable "benchmark + released dataset + strong open baseline" type rather than a risky "beat-SOTA architecture" play, and the demo (highlight-the-hallucinated-field on the rendered page) is instantly shareable.
15
+ Why the scope works: the tool is model-agnostic and thin (it wraps existing extractors), the paper contribution is the reliable "benchmark + released dataset + strong open baseline" type rather than a risky "beat-SOTA architecture" play, and the demo (highlight-the-hallucinated-field on the rendered page) is instantly shareable.
16
16
 
17
17
  ---
18
18
 
@@ -216,7 +216,6 @@ Design rules: adapters isolate all model-specific code behind one interface (`ex
216
216
  ```
217
217
  verifydoc/
218
218
  ├── README.md # quickstart + the killer demo GIF
219
- ├── CLAUDE.md # Claude Code working context (see separate file)
220
219
  ├── PROJECT.md # this document
221
220
  ├── LICENSE # Apache-2.0 (permissive → adoption)
222
221
  ├── pyproject.toml # packaging (pip install verifydoc)
@@ -269,7 +268,7 @@ verifydoc/
269
268
 
270
269
  ---
271
270
 
272
- ## 9. Implementation plan (6 weeks, solo)
271
+ ## 9. Implementation plan (6 weeks)
273
272
 
274
273
  **Week 1 — skeleton + types + one adapter + eval stubs.** Repo, packaging, CI, pre-commit. Define `types.py` (`FieldPrediction`, `Grounding`). Implement ingest (PDF→images + text layer). Ship the **PaddleOCR-VL adapter** end-to-end on a handful of CORD receipts. Stub `eval/extraction.py` with Field-F1 + exact-match. *DoD: `verifydoc extract sample.pdf --schema cord.json` returns JSON with placeholder confidences; CI green.*
275
274
 
@@ -320,12 +319,6 @@ verifydoc/
320
319
 
321
320
  ---
322
321
 
323
- ## 13. EB1-A mapping (brief, honest)
324
-
325
- This project can contribute to (a) **authorship of scholarly articles** (arXiv + workshop/TMLR paper); (b) **original contributions of major significance** — best evidenced by demonstrable open-source adoption (stars, PyPI downloads, dependents, external citations of VerifyDocBench); and (c) **judging the work of others** if you also serve as a reviewer for the workshop you submit to. Be realistic: USCIS requires meeting **at least three** criteria plus a holistic final-merits determination, and strong petitions usually document more, with independent corroboration (sustained citations, media, memberships, and recommendation letters). VerifyDoc is engineered to *generate* that downstream evidence (adoption → citations → letters), but **two projects alone are not a sufficient petition** — pair it with the second project and the complementary criteria.
326
-
327
- ---
328
-
329
322
  ## References (select; verify at write-up)
330
323
 
331
324
  - ExtractBench — arXiv:2602.12247 (SIGKDD 2026); code github.com/ContextualAI/extract-bench.
@@ -36,7 +36,8 @@ pip install 'verifydoc[pdf]' # + PDF/image ingestion
36
36
  ```python
37
37
  from verifydoc import verify
38
38
 
39
- result = verify("invoice.txt", schema="invoice_schema.json", k=3)
39
+ # ready-to-run sample lives in examples/
40
+ result = verify("examples/invoice.txt", schema="examples/invoice_schema.json")
40
41
  for f in result.fields:
41
42
  print(f"{f.path:12} = {f.value!r:24} conf={f.confidence:.2f} {f.decision}")
42
43
  if f.grounding:
@@ -44,10 +45,12 @@ for f in result.fields:
44
45
  ```
45
46
 
46
47
  ```bash
47
- verifydoc extract invoice.txt --schema invoice_schema.json --k 3 --threshold 0.8
48
+ verifydoc extract examples/invoice.txt --schema examples/invoice_schema.json --threshold 0.8
48
49
  streamlit run ui/streamlit_app.py # review UI: green/red fields + click-through to source
49
50
  ```
50
51
 
52
+ See [`examples/`](examples/) for the full runnable walk-through.
53
+
51
54
  Schemas are plain JSON Schema, with each leaf optionally declaring **how it is scored** (the executable-schema pattern):
52
55
 
53
56
  ```json
@@ -65,14 +68,37 @@ Schemas are plain JSON Schema, with each leaf optionally declaring **how it is s
65
68
 
66
69
  | Layer | Modules | Status |
67
70
  |---|---|---|
68
- | **Adapters** (all model code isolated here) | mock · text-search · PaddleOCR-VL · dots.ocr · Docling/MinerU output · API-VLM | ✅ |
71
+ | **Adapters** (all model code isolated here) | mock · text-search · RapidOCR · PaddleOCR · dots.ocr · Docling/MinerU output · API-VLM (OpenAI/Anthropic) | ✅ |
69
72
  | **Confidence signals** | token-prob · verbalized · consensus (k-sample voting) · grounding-based · combined | ✅ |
70
73
  | **Calibrators** (fit on a dedicated split, never test) | temperature · Platt · isotonic · histogram · **split conformal** with finite-sample risk guarantee | ✅ |
71
74
  | **Grounding** | value → page/bbox/char-span attachment with support scores | ✅ |
72
75
  | **Policy** | empirical & conformal accept thresholds for a target selective risk | ✅ |
73
76
  | **Eval harness / VerifyDocBench scorer** | Field-F1 · exact · CER/WER · ANLS · TEDS/TEDS-Struct · GriTS · omission vs hallucination · ECE/Adaptive-ECE/MCE/Brier/NLL/TCE · RC/AURC/E-AURC/Coverage@Risk/AUROC/AUPR/FPR@95 · box IoU/span-F1/grounding-conditioned correctness · bootstrap CIs + paired tests | ✅ |
74
77
 
75
- Every metric implements the exact definition in [PROJECT.md §5](PROJECT.md) with a hand-computed numeric regression test (200 tests, `eval/` coverage 98%).
78
+ Every metric implements the exact definition in [PROJECT.md §5](PROJECT.md) with a hand-computed numeric regression test (201 tests, `eval/` coverage 98%).
79
+
80
+ ## Results on real documents
81
+
82
+ Two independent real OCR extractors (**RapidOCR** and **PaddleOCR**) on real
83
+ **CORD** receipts and **FUNSD** forms, scored by the harness
84
+ ([full tables + reading](paper/generated/REAL_MODELS_RESULTS.md)):
85
+
86
+ | Confidence signal | ranks errors? | CORD AUROC (RapidOCR / PaddleOCR) |
87
+ |---|---|---|
88
+ | **learned combiner** | ✅ best | **0.89 / 0.84** |
89
+ | **grounding** | ✅ strong | 0.82 / 0.74 |
90
+ | token-probability | ~ moderate | 0.69 / 0.68 |
91
+ | verbalized / consensus | ✗ uninformative | 0.50 / 0.50 |
92
+
93
+ - **Grounding is a real trust signal:** grounded fields are **84–85% correct
94
+ vs ~1%** for ungrounded (gap ≈ +0.84; box accuracy @IoU 0.5 = 0.75–0.78).
95
+ - **The abstention layer is honest:** with a weak field-extractor the base
96
+ error rate is high, so conformal abstention at a 2–5% budget correctly
97
+ refuses to auto-accept — you report *selective risk*, not headline accuracy.
98
+ - The synthetic slice (strong extractor) shows the other end: Coverage@2% ≈ 1.0.
99
+
100
+ The thesis holds on real data: **grounding + a learned fusion rank errors;
101
+ self-reported and single-sample-consensus confidence do not.**
76
102
 
77
103
  ## The benchmark
78
104
 
@@ -82,16 +108,13 @@ make results # regenerates every table/figure in paper/generated from config
82
108
 
83
109
  The harness runs **signals × calibrators × the full metric suite** with a
84
110
  document-level calibration split (disjointness asserted in code), bootstrap
85
- CIs, and a conformal-guarantee row. The repo ships a deterministic synthetic
86
- slice that runs in CI; loaders for CORD (and next: FUNSD, SROIE, DocILE,
87
- XFUND) extend it. Sample findings on the shipped slice
88
- ([tables](paper/generated)):
89
-
90
- - **Verbalized self-confidence is badly miscalibrated** (the extractor says ~0.9 regardless of correctness) exactly the failure mode reported for RLHF'd models.
91
- - **Consensus and grounding signals rank errors near-perfectly** (AUROC ≈ 0.98): corrupted values can't be traced back to the page, so grounding support collapses.
92
- - **The conformal row holds its guarantee** on every tested α, and reports the abstention it forces.
93
-
94
- These self-checks run as unit tests — the repo's core claims are CI-enforced, not just stated.
111
+ CIs, and a conformal-guarantee row. It ships a deterministic **synthetic**
112
+ slice (runs in CI) plus **CORD** and **FUNSD** loaders with gold source boxes;
113
+ `extractor:` dispatches to any adapter (`rapidocr`, `paddleocr-vl`, …) and
114
+ `dataset:` to any slice. See the [GPU runbook](docs/REAL_MODELS.md) to
115
+ reproduce the real-model rows. Core claims (grounding beats verbalized;
116
+ conformal holds its guarantee) are also **CI-enforced as unit tests**, not
117
+ just stated.
95
118
 
96
119
  ## Why not just use the parser's own score?
97
120
 
@@ -104,9 +127,19 @@ buys you.
104
127
  ## Roadmap
105
128
 
106
129
  - [x] v0.1 — library + CLI + harness + synthetic benchmark slice + UI
107
- - [ ] CORD/FUNSD/SROIE slices with gold source boxes (VerifyDocBench v1)
108
- - [ ] Learned signal combiner + per-field-type calibration
109
- - [ ] Paper: first systematic study of confidence signals × calibration × abstention for document extraction
130
+ - [x] v0.2 — CORD + FUNSD real slices with gold boxes; learned combiner; 1000× faster grounder
131
+ - [x] v0.3 real-model results (RapidOCR + PaddleOCR on CORD/FUNSD)
132
+ - [x] v0.4 vendor-neutral API-VLM extractor (OpenAI/Anthropic) with k-sample consensus; compilable paper with auto-generated tables
133
+ - [ ] Run the API-VLM row at scale (fair verbalized + consensus comparison; needs an API key)
134
+ - [ ] dots.ocr via vllm; SROIE / DocILE / XFUND slices; human-labeled correctness + IAA
135
+ - [ ] Paper submission ([contributions welcome](CONTRIBUTING.md))
136
+
137
+ ## Documentation
138
+
139
+ - [How it works](docs/how-it-works.md) — the pipeline, the abstention idea, why grounding is a trust signal
140
+ - [Real-model results](paper/generated/REAL_MODELS_RESULTS.md) — RapidOCR + PaddleOCR numbers and reading
141
+ - [GPU runbook](docs/REAL_MODELS.md) — reproduce the real-extractor rows
142
+ - [USP audit](docs/USP.md) · [Paper draft](paper/main.tex) · [Full spec](PROJECT.md)
110
143
 
111
144
  ## Development
112
145
 
@@ -114,6 +147,8 @@ buys you.
114
147
  git clone https://github.com/bhaskargurram-ai/verifydoc && cd verifydoc
115
148
  uv venv .venv && uv pip install -e ".[dev]"
116
149
  make test lint typecheck # all green before any PR (CI enforces)
150
+ make results # regenerate benchmark tables + LaTeX
151
+ make paper # compile the paper (needs a LaTeX toolchain)
117
152
  ```
118
153
 
119
154
  Contributions welcome — see the issues tagged `good-first-issue`. All model-specific code goes in `verifydoc/adapters/`; a new extractor is one file.