docgun 0.1.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.
- docgun-0.1.0/CHANGELOG.md +16 -0
- docgun-0.1.0/LICENSE +21 -0
- docgun-0.1.0/PKG-INFO +292 -0
- docgun-0.1.0/README.md +248 -0
- docgun-0.1.0/pyproject.toml +76 -0
- docgun-0.1.0/src/docgun/__init__.py +8 -0
- docgun-0.1.0/src/docgun/agents/__init__.py +1 -0
- docgun-0.1.0/src/docgun/agents/confidence.py +59 -0
- docgun-0.1.0/src/docgun/agents/enrichment.py +23 -0
- docgun-0.1.0/src/docgun/agents/inspection.py +123 -0
- docgun-0.1.0/src/docgun/agents/quality.py +81 -0
- docgun-0.1.0/src/docgun/agents/recovery.py +206 -0
- docgun-0.1.0/src/docgun/agents/router.py +32 -0
- docgun-0.1.0/src/docgun/agents/vision.py +79 -0
- docgun-0.1.0/src/docgun/api/__init__.py +1 -0
- docgun-0.1.0/src/docgun/api/routes.py +66 -0
- docgun-0.1.0/src/docgun/chunking/__init__.py +1 -0
- docgun-0.1.0/src/docgun/chunking/hierarchical.py +59 -0
- docgun-0.1.0/src/docgun/chunking/spreadsheet.py +11 -0
- docgun-0.1.0/src/docgun/cli.py +39 -0
- docgun-0.1.0/src/docgun/domain/__init__.py +1 -0
- docgun-0.1.0/src/docgun/domain/errors.py +34 -0
- docgun-0.1.0/src/docgun/domain/models.py +72 -0
- docgun-0.1.0/src/docgun/parsers/__init__.py +1 -0
- docgun-0.1.0/src/docgun/parsers/base.py +14 -0
- docgun-0.1.0/src/docgun/parsers/csv.py +57 -0
- docgun-0.1.0/src/docgun/parsers/docx.py +109 -0
- docgun-0.1.0/src/docgun/parsers/excel.py +87 -0
- docgun-0.1.0/src/docgun/parsers/pdf_docling.py +93 -0
- docgun-0.1.0/src/docgun/parsers/pdf_fast.py +101 -0
- docgun-0.1.0/src/docgun/pipeline/__init__.py +1 -0
- docgun-0.1.0/src/docgun/pipeline/graph.py +64 -0
- docgun-0.1.0/src/docgun/pipeline/policies.py +1 -0
- docgun-0.1.0/src/docgun/pipeline/state.py +25 -0
- docgun-0.1.0/src/docgun/py.typed +1 -0
- docgun-0.1.0/src/docgun/security/__init__.py +1 -0
- docgun-0.1.0/src/docgun/security/limits.py +11 -0
- docgun-0.1.0/src/docgun/security/validation.py +81 -0
- docgun-0.1.0/src/docgun/storage/__init__.py +1 -0
- docgun-0.1.0/src/docgun/storage/documents.py +12 -0
- docgun-0.1.0/src/docgun/storage/vectors.py +10 -0
- docgun-0.1.0/tests/test_chunking.py +22 -0
- docgun-0.1.0/tests/test_quality.py +62 -0
- docgun-0.1.0/tests/test_recovery.py +126 -0
- docgun-0.1.0/tests/test_router.py +29 -0
- docgun-0.1.0/tests/test_validation.py +26 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to DocGun are documented here.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-07-11
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Deterministic PDF, DOCX, Excel, and CSV ingestion.
|
|
10
|
+
- Unified typed document and provenance models.
|
|
11
|
+
- Quality scoring and structured recovery diagnostics.
|
|
12
|
+
- Page-level Docling and injectable vision/OCR recovery.
|
|
13
|
+
- FastAPI upload endpoint with bounded temporary-file handling.
|
|
14
|
+
- `docgun` command-line interface.
|
|
15
|
+
|
|
16
|
+
[0.1.0]: https://github.com/Arkay92/DocGun/releases/tag/v0.1.0
|
docgun-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JadeyGraham96
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
docgun-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docgun
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic document ingestion for PDF, DOCX, Excel, and CSV with quality-aware recovery.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Arkay92/DocGun
|
|
6
|
+
Project-URL: Repository, https://github.com/Arkay92/DocGun
|
|
7
|
+
Project-URL: Issues, https://github.com/Arkay92/DocGun/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Arkay92/DocGun/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Arkay92
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: csv,document-ingestion,docx,ocr,pdf,rag,xlsx
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: defusedxml
|
|
22
|
+
Requires-Dist: fastapi
|
|
23
|
+
Requires-Dist: openpyxl
|
|
24
|
+
Requires-Dist: opentelemetry-api
|
|
25
|
+
Requires-Dist: orjson
|
|
26
|
+
Requires-Dist: pandas
|
|
27
|
+
Requires-Dist: pyarrow
|
|
28
|
+
Requires-Dist: pydantic>=2
|
|
29
|
+
Requires-Dist: pymupdf
|
|
30
|
+
Requires-Dist: python-docx
|
|
31
|
+
Requires-Dist: structlog
|
|
32
|
+
Requires-Dist: tenacity
|
|
33
|
+
Requires-Dist: uvicorn[standard]
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
37
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
38
|
+
Provides-Extra: full
|
|
39
|
+
Requires-Dist: docling; extra == 'full'
|
|
40
|
+
Requires-Dist: polars; extra == 'full'
|
|
41
|
+
Requires-Dist: python-calamine; extra == 'full'
|
|
42
|
+
Requires-Dist: python-magic; extra == 'full'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# DocGun
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
Quality-aware document ingestion for Python and RAG pipelines.
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img width="256" height="256" alt="DocGun logo" src="https://raw.githubusercontent.com/Arkay92/DocGun/refs/heads/main/DocGun.png" />
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
<p align="center">
|
|
56
|
+
<a href="https://github.com/Arkay92/DocGun/actions/workflows/publish.yml"><img alt="Publish" src="https://github.com/Arkay92/DocGun/actions/workflows/publish.yml/badge.svg" /></a>
|
|
57
|
+
<a href="https://pypi.org/project/docgun/"><img alt="PyPI" src="https://img.shields.io/pypi/v/docgun.svg" /></a>
|
|
58
|
+
<img alt="Python" src="https://img.shields.io/pypi/pyversions/docgun.svg" />
|
|
59
|
+
<img alt="Downloads" src="https://img.shields.io/pypi/dm/docgun.svg" />
|
|
60
|
+
<img alt="License" src="https://img.shields.io/pypi/l/docgun.svg" />
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
> **Package name:** `docgun`
|
|
64
|
+
> **Project name:** DocGun
|
|
65
|
+
> **Install:** `pip install docgun`
|
|
66
|
+
> **Import:** `from docgun import ingest`
|
|
67
|
+
|
|
68
|
+
**DocGun** turns PDF, DOCX, Excel, and CSV files into a consistent typed document model. It combines deterministic parsing with extraction scoring, page-aware fallback, security limits, and explicit recovery states so incomplete scans do not silently look successful.
|
|
69
|
+
|
|
70
|
+
- Native PDF text, coordinates, tables, and page provenance with PyMuPDF.
|
|
71
|
+
- Ordered DOCX headings, paragraphs, lists, and tables.
|
|
72
|
+
- Bounded XLSX/XLSM and batched CSV extraction.
|
|
73
|
+
- Page-level Docling fallback with structured elements and provenance.
|
|
74
|
+
- Injectable OCR/VLM recovery for only the pages that need it.
|
|
75
|
+
- Measurable confidence reports and structured recovery attempts.
|
|
76
|
+
- ZIP/Open XML validation, encrypted-PDF detection, and ingestion limits.
|
|
77
|
+
- Python API, CLI, and FastAPI upload route.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Before / After
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from docgun import ingest
|
|
85
|
+
|
|
86
|
+
state = ingest("mixed-report.pdf")
|
|
87
|
+
|
|
88
|
+
print(state.status)
|
|
89
|
+
print(state.quality.confidence)
|
|
90
|
+
print(len(state.document.elements))
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Example output:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
completed
|
|
97
|
+
0.9142
|
|
98
|
+
47
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When a scan cannot be recovered, DocGun returns `recovery_required` with page-level markers and diagnostics instead of presenting an empty page as successfully ingested.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Why Quality-Aware Ingestion?
|
|
106
|
+
|
|
107
|
+
Document parsers can return technically valid but incomplete output: a scanned page may yield only a footer, a fallback may omit pages, or a table detector may consume nearby text. DocGun makes those failure modes visible:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
Input document
|
|
111
|
+
-> Validate size, signature, archive safety, and encryption
|
|
112
|
+
-> Inspect pages or workbook dimensions
|
|
113
|
+
-> Route to a deterministic native parser
|
|
114
|
+
-> Score content, structure, tables, and provenance
|
|
115
|
+
-> Compare page-level fallback candidates
|
|
116
|
+
-> Recover only weak pages with Docling or an OCR/VLM backend
|
|
117
|
+
-> Return typed elements, status, quality, warnings, and diagnostics
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Pipeline statuses are `completed`, `partially_completed`, `recovery_required`, and `failed`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Install
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
pip install docgun
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For Docling and the complete fallback toolset:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install "docgun[full]"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
For development:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install -e ".[dev,full]"
|
|
140
|
+
pytest -q
|
|
141
|
+
python -m build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Quick Start
|
|
147
|
+
|
|
148
|
+
### Ingest a Document
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from docgun import ingest
|
|
152
|
+
|
|
153
|
+
state = ingest("annual-report.pdf")
|
|
154
|
+
|
|
155
|
+
for element in state.document.elements:
|
|
156
|
+
print(element.type, element.text, element.location)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Inspect Recovery Diagnostics
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
for attempt in state.recovery_attempts:
|
|
163
|
+
print(attempt.action, attempt.status, attempt.error_message)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Configure Page-Level Vision Recovery
|
|
167
|
+
|
|
168
|
+
Implement `extract_batch(rendered_pages)` in your OCR or VLM adapter and inject it into the pipeline:
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from docgun.agents.recovery import RecoveryEngine
|
|
172
|
+
from docgun.agents.vision import VisionPageRecovery
|
|
173
|
+
from docgun.pipeline.graph import ingest
|
|
174
|
+
|
|
175
|
+
class MyVisionBackend:
|
|
176
|
+
def extract_batch(self, pages):
|
|
177
|
+
return vision_client.extract(pages)
|
|
178
|
+
|
|
179
|
+
engine = RecoveryEngine(VisionPageRecovery(MyVisionBackend()))
|
|
180
|
+
state = ingest("scan.pdf", recovery_engine=engine)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Each backend result may contain `text`, `type`, `table`, `bbox`, and `confidence` fields.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## CLI
|
|
188
|
+
|
|
189
|
+
Ingest a file and print the complete pipeline state as JSON:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
docgun report.pdf
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Print a compact summary:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
docgun report.pdf --summary
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Supported Formats
|
|
204
|
+
|
|
205
|
+
| Format | Native parser | Recovery |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| PDF | PyMuPDF | Docling, then configured page-level OCR/VLM |
|
|
208
|
+
| DOCX | python-docx | Explicit low-confidence status |
|
|
209
|
+
| XLSX/XLSM | openpyxl | Explicit low-confidence status |
|
|
210
|
+
| CSV | PyArrow | Explicit low-confidence status |
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Architecture
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
src/docgun/
|
|
218
|
+
__init__.py # Public API
|
|
219
|
+
cli.py # Command-line interface
|
|
220
|
+
agents/ # Inspection, routing, confidence, quality, recovery
|
|
221
|
+
api/ # FastAPI upload route
|
|
222
|
+
chunking/ # Hierarchical and spreadsheet chunk helpers
|
|
223
|
+
domain/ # Typed elements, inspections, and errors
|
|
224
|
+
parsers/ # PDF, Docling, DOCX, Excel, and CSV parsers
|
|
225
|
+
pipeline/ # Orchestration state and policies
|
|
226
|
+
security/ # File limits and format validation
|
|
227
|
+
storage/ # Document and vector storage interfaces
|
|
228
|
+
tests/ # Unit and regression tests
|
|
229
|
+
.github/workflows/ # CI and trusted PyPI publishing
|
|
230
|
+
CHANGELOG.md # Release history
|
|
231
|
+
pyproject.toml # Package metadata and dependencies
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## FastAPI
|
|
237
|
+
|
|
238
|
+
The bundled route streams uploads to a bounded temporary file, maps ingestion errors to appropriate HTTP responses, and removes the temporary file after success or failure.
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from fastapi import FastAPI
|
|
242
|
+
from docgun.api.routes import router
|
|
243
|
+
|
|
244
|
+
app = FastAPI()
|
|
245
|
+
app.include_router(router, prefix="/documents")
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Development
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
pip install -e ".[dev,full]"
|
|
254
|
+
python -m pytest
|
|
255
|
+
python -m build
|
|
256
|
+
python -m twine check dist/*
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
MIT
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Contributing
|
|
268
|
+
|
|
269
|
+
Contributions are welcome. Please include a representative document or minimal generated fixture, the expected elements, and a regression test for parser or recovery changes.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Citation
|
|
274
|
+
|
|
275
|
+
```bibtex
|
|
276
|
+
@software{DocGun2026,
|
|
277
|
+
title={DocGun: Quality-Aware Document Ingestion for Python},
|
|
278
|
+
author={Arkay92},
|
|
279
|
+
url={https://github.com/Arkay92/DocGun},
|
|
280
|
+
year={2026},
|
|
281
|
+
version={0.1.0},
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Acknowledgments
|
|
288
|
+
|
|
289
|
+
- [PyMuPDF](https://pymupdf.readthedocs.io/) for fast native PDF extraction and rendering.
|
|
290
|
+
- [Docling](https://github.com/docling-project/docling) for layout-aware document conversion.
|
|
291
|
+
- [python-docx](https://python-docx.readthedocs.io/) and [openpyxl](https://openpyxl.readthedocs.io/) for Office document parsing.
|
|
292
|
+
- [Apache Arrow](https://arrow.apache.org/) for batched CSV ingestion.
|
docgun-0.1.0/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# DocGun
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
Quality-aware document ingestion for Python and RAG pipelines.
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img width="256" height="256" alt="DocGun logo" src="https://raw.githubusercontent.com/Arkay92/DocGun/refs/heads/main/DocGun.png" />
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/Arkay92/DocGun/actions/workflows/publish.yml"><img alt="Publish" src="https://github.com/Arkay92/DocGun/actions/workflows/publish.yml/badge.svg" /></a>
|
|
13
|
+
<a href="https://pypi.org/project/docgun/"><img alt="PyPI" src="https://img.shields.io/pypi/v/docgun.svg" /></a>
|
|
14
|
+
<img alt="Python" src="https://img.shields.io/pypi/pyversions/docgun.svg" />
|
|
15
|
+
<img alt="Downloads" src="https://img.shields.io/pypi/dm/docgun.svg" />
|
|
16
|
+
<img alt="License" src="https://img.shields.io/pypi/l/docgun.svg" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
> **Package name:** `docgun`
|
|
20
|
+
> **Project name:** DocGun
|
|
21
|
+
> **Install:** `pip install docgun`
|
|
22
|
+
> **Import:** `from docgun import ingest`
|
|
23
|
+
|
|
24
|
+
**DocGun** turns PDF, DOCX, Excel, and CSV files into a consistent typed document model. It combines deterministic parsing with extraction scoring, page-aware fallback, security limits, and explicit recovery states so incomplete scans do not silently look successful.
|
|
25
|
+
|
|
26
|
+
- Native PDF text, coordinates, tables, and page provenance with PyMuPDF.
|
|
27
|
+
- Ordered DOCX headings, paragraphs, lists, and tables.
|
|
28
|
+
- Bounded XLSX/XLSM and batched CSV extraction.
|
|
29
|
+
- Page-level Docling fallback with structured elements and provenance.
|
|
30
|
+
- Injectable OCR/VLM recovery for only the pages that need it.
|
|
31
|
+
- Measurable confidence reports and structured recovery attempts.
|
|
32
|
+
- ZIP/Open XML validation, encrypted-PDF detection, and ingestion limits.
|
|
33
|
+
- Python API, CLI, and FastAPI upload route.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Before / After
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from docgun import ingest
|
|
41
|
+
|
|
42
|
+
state = ingest("mixed-report.pdf")
|
|
43
|
+
|
|
44
|
+
print(state.status)
|
|
45
|
+
print(state.quality.confidence)
|
|
46
|
+
print(len(state.document.elements))
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Example output:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
completed
|
|
53
|
+
0.9142
|
|
54
|
+
47
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
When a scan cannot be recovered, DocGun returns `recovery_required` with page-level markers and diagnostics instead of presenting an empty page as successfully ingested.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Why Quality-Aware Ingestion?
|
|
62
|
+
|
|
63
|
+
Document parsers can return technically valid but incomplete output: a scanned page may yield only a footer, a fallback may omit pages, or a table detector may consume nearby text. DocGun makes those failure modes visible:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Input document
|
|
67
|
+
-> Validate size, signature, archive safety, and encryption
|
|
68
|
+
-> Inspect pages or workbook dimensions
|
|
69
|
+
-> Route to a deterministic native parser
|
|
70
|
+
-> Score content, structure, tables, and provenance
|
|
71
|
+
-> Compare page-level fallback candidates
|
|
72
|
+
-> Recover only weak pages with Docling or an OCR/VLM backend
|
|
73
|
+
-> Return typed elements, status, quality, warnings, and diagnostics
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Pipeline statuses are `completed`, `partially_completed`, `recovery_required`, and `failed`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install docgun
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For Docling and the complete fallback toolset:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install "docgun[full]"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
For development:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install -e ".[dev,full]"
|
|
96
|
+
pytest -q
|
|
97
|
+
python -m build
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Quick Start
|
|
103
|
+
|
|
104
|
+
### Ingest a Document
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from docgun import ingest
|
|
108
|
+
|
|
109
|
+
state = ingest("annual-report.pdf")
|
|
110
|
+
|
|
111
|
+
for element in state.document.elements:
|
|
112
|
+
print(element.type, element.text, element.location)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Inspect Recovery Diagnostics
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
for attempt in state.recovery_attempts:
|
|
119
|
+
print(attempt.action, attempt.status, attempt.error_message)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Configure Page-Level Vision Recovery
|
|
123
|
+
|
|
124
|
+
Implement `extract_batch(rendered_pages)` in your OCR or VLM adapter and inject it into the pipeline:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from docgun.agents.recovery import RecoveryEngine
|
|
128
|
+
from docgun.agents.vision import VisionPageRecovery
|
|
129
|
+
from docgun.pipeline.graph import ingest
|
|
130
|
+
|
|
131
|
+
class MyVisionBackend:
|
|
132
|
+
def extract_batch(self, pages):
|
|
133
|
+
return vision_client.extract(pages)
|
|
134
|
+
|
|
135
|
+
engine = RecoveryEngine(VisionPageRecovery(MyVisionBackend()))
|
|
136
|
+
state = ingest("scan.pdf", recovery_engine=engine)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Each backend result may contain `text`, `type`, `table`, `bbox`, and `confidence` fields.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## CLI
|
|
144
|
+
|
|
145
|
+
Ingest a file and print the complete pipeline state as JSON:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
docgun report.pdf
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Print a compact summary:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
docgun report.pdf --summary
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Supported Formats
|
|
160
|
+
|
|
161
|
+
| Format | Native parser | Recovery |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| PDF | PyMuPDF | Docling, then configured page-level OCR/VLM |
|
|
164
|
+
| DOCX | python-docx | Explicit low-confidence status |
|
|
165
|
+
| XLSX/XLSM | openpyxl | Explicit low-confidence status |
|
|
166
|
+
| CSV | PyArrow | Explicit low-confidence status |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Architecture
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
src/docgun/
|
|
174
|
+
__init__.py # Public API
|
|
175
|
+
cli.py # Command-line interface
|
|
176
|
+
agents/ # Inspection, routing, confidence, quality, recovery
|
|
177
|
+
api/ # FastAPI upload route
|
|
178
|
+
chunking/ # Hierarchical and spreadsheet chunk helpers
|
|
179
|
+
domain/ # Typed elements, inspections, and errors
|
|
180
|
+
parsers/ # PDF, Docling, DOCX, Excel, and CSV parsers
|
|
181
|
+
pipeline/ # Orchestration state and policies
|
|
182
|
+
security/ # File limits and format validation
|
|
183
|
+
storage/ # Document and vector storage interfaces
|
|
184
|
+
tests/ # Unit and regression tests
|
|
185
|
+
.github/workflows/ # CI and trusted PyPI publishing
|
|
186
|
+
CHANGELOG.md # Release history
|
|
187
|
+
pyproject.toml # Package metadata and dependencies
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## FastAPI
|
|
193
|
+
|
|
194
|
+
The bundled route streams uploads to a bounded temporary file, maps ingestion errors to appropriate HTTP responses, and removes the temporary file after success or failure.
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from fastapi import FastAPI
|
|
198
|
+
from docgun.api.routes import router
|
|
199
|
+
|
|
200
|
+
app = FastAPI()
|
|
201
|
+
app.include_router(router, prefix="/documents")
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Development
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
pip install -e ".[dev,full]"
|
|
210
|
+
python -m pytest
|
|
211
|
+
python -m build
|
|
212
|
+
python -m twine check dist/*
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Contributing
|
|
224
|
+
|
|
225
|
+
Contributions are welcome. Please include a representative document or minimal generated fixture, the expected elements, and a regression test for parser or recovery changes.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Citation
|
|
230
|
+
|
|
231
|
+
```bibtex
|
|
232
|
+
@software{DocGun2026,
|
|
233
|
+
title={DocGun: Quality-Aware Document Ingestion for Python},
|
|
234
|
+
author={Arkay92},
|
|
235
|
+
url={https://github.com/Arkay92/DocGun},
|
|
236
|
+
year={2026},
|
|
237
|
+
version={0.1.0},
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Acknowledgments
|
|
244
|
+
|
|
245
|
+
- [PyMuPDF](https://pymupdf.readthedocs.io/) for fast native PDF extraction and rendering.
|
|
246
|
+
- [Docling](https://github.com/docling-project/docling) for layout-aware document conversion.
|
|
247
|
+
- [python-docx](https://python-docx.readthedocs.io/) and [openpyxl](https://openpyxl.readthedocs.io/) for Office document parsing.
|
|
248
|
+
- [Apache Arrow](https://arrow.apache.org/) for batched CSV ingestion.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "docgun"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Deterministic document ingestion for PDF, DOCX, Excel, and CSV with quality-aware recovery."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [{ name = "Arkay92" }]
|
|
9
|
+
keywords = ["document-ingestion", "pdf", "docx", "xlsx", "csv", "ocr", "rag"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3.11",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Programming Language :: Python :: 3.13",
|
|
17
|
+
"Typing :: Typed",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"fastapi",
|
|
21
|
+
"uvicorn[standard]",
|
|
22
|
+
"pydantic>=2",
|
|
23
|
+
"pymupdf",
|
|
24
|
+
"python-docx",
|
|
25
|
+
"openpyxl",
|
|
26
|
+
"pandas",
|
|
27
|
+
"pyarrow",
|
|
28
|
+
"defusedxml",
|
|
29
|
+
"orjson",
|
|
30
|
+
"tenacity",
|
|
31
|
+
"structlog",
|
|
32
|
+
"opentelemetry-api",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
full = [
|
|
37
|
+
"docling",
|
|
38
|
+
"python-calamine",
|
|
39
|
+
"polars",
|
|
40
|
+
"python-magic",
|
|
41
|
+
]
|
|
42
|
+
dev = [
|
|
43
|
+
"build>=1.0",
|
|
44
|
+
"pytest",
|
|
45
|
+
"twine>=5.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/Arkay92/DocGun"
|
|
50
|
+
Repository = "https://github.com/Arkay92/DocGun"
|
|
51
|
+
Issues = "https://github.com/Arkay92/DocGun/issues"
|
|
52
|
+
Changelog = "https://github.com/Arkay92/DocGun/blob/main/CHANGELOG.md"
|
|
53
|
+
|
|
54
|
+
[project.scripts]
|
|
55
|
+
docgun = "docgun.cli:main"
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["hatchling"]
|
|
59
|
+
build-backend = "hatchling.build"
|
|
60
|
+
|
|
61
|
+
[tool.hatch.build.targets.wheel]
|
|
62
|
+
packages = ["src/docgun"]
|
|
63
|
+
|
|
64
|
+
[tool.hatch.build.targets.sdist]
|
|
65
|
+
include = [
|
|
66
|
+
"/src",
|
|
67
|
+
"/tests",
|
|
68
|
+
"/README.md",
|
|
69
|
+
"/CHANGELOG.md",
|
|
70
|
+
"/LICENSE",
|
|
71
|
+
"/pyproject.toml",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[tool.pytest.ini_options]
|
|
75
|
+
pythonpath = ["src"]
|
|
76
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Agent-supervised deterministic pipeline helpers."""
|