File size: 6,734 Bytes
2a9e166
bb76929
 
2a9e166
bb76929
2a9e166
9b62d57
2a9e166
 
 
 
 
bb76929
2a9e166
bb76929
 
 
 
 
2a9e166
 
 
 
 
 
 
 
1d905fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a9e166
 
bb76929
 
 
 
 
 
 
 
 
 
 
 
a20dd9f
2a9e166
 
1d905fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a9e166
a20dd9f
 
bb76929
a20dd9f
 
 
bb76929
 
a20dd9f
7ce911a
 
 
 
 
 
 
 
a20dd9f
bb76929
 
 
a20dd9f
3a6d22d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a9e166
 
 
 
 
 
a20dd9f
2a9e166
 
 
 
 
 
 
1d905fa
 
 
a20dd9f
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
---
title: Document Intelligence - OCR Data Extractor
emoji: πŸ“„
colorFrom: blue
colorTo: gray
sdk: gradio
sdk_version: 6.19.0
app_file: app.py
pinned: false
license: mit
---

# Turn Documents Into Structured Business Data

The real value isn't converting images into text β€” it's turning
unstructured documents into reliable, actionable data. This tool takes
scanned PDFs or images, runs them through OCR, and uses an AI-assisted
extraction step (configured by describing what you need in plain
language) to produce clean, audit-ready structured data. Built for:

- **Construction / SAP data support** β€” change orders, delay notices,
  punch list items, RFIs, PO numbers, SAP document numbers, quantities.
- **Compliance** β€” non-conformances, violations, expirations, corrective
  actions, certification codes (ISO, OSHA, ASTM, ANSI).
- **Business finance** β€” past-due invoices, payment rejections, credit
  holds, invoice numbers, dollar amounts, due dates.

## Notifications vs. fields

The tool treats two kinds of requests differently, rather than running
one blanket extraction pass over every document:

- **Notifications** β€” keyword/phrase hits that flag an event (a boolean
  "this happened on this page"), e.g. "past due", "non-compliant",
  "change order". Each category (construction/compliance/finance/general)
  has its own built-in phrase list; you can add your own custom
  notification keywords too.
- **Fields** β€” labeled values extracted as data, not just flagged.
  Standard fields are *scoped to the categories you select* (see
  `CATEGORY_FIELD_MAP` in `extractors.py`) so a compliance document
  doesn't generate empty invoice-number columns: construction gets PO/SAP
  numbers, compliance gets certification codes, finance gets invoice
  numbers/percentages, and dates/amounts apply where relevant. On top of
  that, you can name your own **custom fields** β€” any label that appears
  in the document followed by a value (e.g. "reference number", "gross
  weight", "delivery date") β€” and the app finds the label and captures
  what follows it.

## How it works

The app is a single guided flow: describe what you need, upload your
documents, run and review.

1. **Step 1 - describe what you need** β€” in plain language (e.g. *"flag
   overdue invoices over $10k and non-compliance notices, and pull the
   reference number and gross weight"*), or tap one of the
   construction/compliance/finance starting-point buttons. A Hugging
   Face-hosted chat model turns that into extraction settings
   (categories, notification keywords, custom fields, export filter),
   shown live in the "Extraction plan" panel. You can also skip the chat
   and set everything by hand in the "Advanced" accordion in Step 2.
2. **Step 2 - upload your documents** β€” one or more PDFs or images.
3. Each page's text is pulled directly from the PDF when it has a text
   layer; scanned/image-only pages are rendered and run through
   Tesseract OCR.
4. The text is scanned for notification keywords and both standard and
   custom fields, per the scoping above.
5. Results are shown as two tidy (one-fact-per-row) tables β€” extracted
   fields and notification hits β€” and exported as three CSVs:
   - `ocr_fields_*.csv` β€” file, page, field_type (standard/custom),
     field_name, field_value, OCR source/confidence.
   - `ocr_notifications_*.csv` β€” file, page, category, keyword, context,
     OCR source/confidence.
   - `ocr_run_metadata_*.csv` β€” an audit record of exactly what produced
     the run: categories, notification keywords, custom fields, the
     match filter, the chat model used, and the full chat transcript.
     This is the lineage trail for anyone auditing why a given row was
     (or wasn't) extracted.

   Long/tidy tables were chosen over one wide fixed-schema table so that
   irrelevant fields never show up as blank columns, and so the output
   loads cleanly into a database, pivot table, or BI tool without
   reshaping β€” consistent with standard data-quality practice (e.g. DAMA
   DMBOK's completeness, validity, and lineage dimensions).

## Chat assistant setup

The Step 1 assistant calls the Hugging Face Inference API, so it needs a token:

- **On a Space:** add a repo secret named `HF_TOKEN` (Settings ->
  Variables and secrets) with a token that has Inference API access.
- **Locally / as a fallback:** paste a token into the "Use your own
  Hugging Face token" accordion in Step 1; it's only used for that session.

The token needs **Inference Providers** permission: use the simple
"Read" token type, or on a fine-grained token check "Make calls to
Inference Providers".

The assistant tries `Qwen/Qwen2.5-7B-Instruct` first, then falls back to
`mistralai/Mistral-7B-Instruct-v0.3` and `Qwen/Qwen2.5-72B-Instruct` if
a provider doesn't carry it. Set an `HF_CHAT_MODEL` env var/Space
variable to force a specific model instead.

If the chat call fails or no token is available, the rest of the app
still works fully via the "Advanced: edit settings manually" accordion
in Step 2 β€” the chat is a convenience layer on top, not a dependency.

## Sample documents

Three fictitious, clearly watermarked demo PDFs are generated on first
launch (by `sample_docs/generate_samples.py` β€” they aren't committed,
since the Hub requires LFS for binaries) and are loadable with one click
from Step 2 (each button also presets the matching extraction settings,
so Run works immediately):

- **Construction change order** β€” PO/SAP numbers, cost overrun amounts,
  a safety-violation field note, OSHA cert reference (native text layer).
- **Accounting / tax invoice** β€” invoice number, line items, tax rate,
  past-due/credit-hold language (native text layer).
- **Bill of lading** β€” saved as an image-only "scanned" page, so it
  exercises the full Tesseract OCR path with confidence scores; custom
  fields pull BOL/reference numbers, weights, and delivery date.

Every sample carries a "FICTITIOUS DATA - NOT REAL DATA" banner,
watermark, and footer. Regenerate them manually with
`python sample_docs/generate_samples.py`.

## Local development

```bash
pip install -r requirements.txt
# Tesseract must also be installed on the system, e.g.:
#   apt-get install tesseract-ocr
export HF_TOKEN=hf_...   # optional, enables the chat tab
python app.py
```

## Files

- `app.py` β€” Gradio UI and orchestration.
- `ocr_engine.py` β€” PDF/image loading and OCR (PyMuPDF + Tesseract).
- `extractors.py` β€” keyword notification scanning, category-scoped
  standard field extraction, and generic label->value custom field
  extraction.
- `chat_config.py` β€” chat assistant that turns natural-language
  instructions into extraction settings via a Hugging Face chat model.