doc-ai-runtime 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.
- doc_ai_runtime-0.1.0/LICENSE +22 -0
- doc_ai_runtime-0.1.0/PKG-INFO +106 -0
- doc_ai_runtime-0.1.0/README.md +88 -0
- doc_ai_runtime-0.1.0/doc_ai_runtime.egg-info/PKG-INFO +106 -0
- doc_ai_runtime-0.1.0/doc_ai_runtime.egg-info/SOURCES.txt +23 -0
- doc_ai_runtime-0.1.0/doc_ai_runtime.egg-info/dependency_links.txt +1 -0
- doc_ai_runtime-0.1.0/doc_ai_runtime.egg-info/requires.txt +8 -0
- doc_ai_runtime-0.1.0/doc_ai_runtime.egg-info/top_level.txt +1 -0
- doc_ai_runtime-0.1.0/pyproject.toml +25 -0
- doc_ai_runtime-0.1.0/setup.cfg +4 -0
- doc_ai_runtime-0.1.0/src/core/config.py +0 -0
- doc_ai_runtime-0.1.0/src/core/dom/models.py +127 -0
- doc_ai_runtime-0.1.0/src/core/interfaces.py +41 -0
- doc_ai_runtime-0.1.0/src/core/pipeline/runner.py +83 -0
- doc_ai_runtime-0.1.0/src/exporters/markdown.py +56 -0
- doc_ai_runtime-0.1.0/src/exporters/rag.py +78 -0
- doc_ai_runtime-0.1.0/src/plugins/layout/surya_layout.py +76 -0
- doc_ai_runtime-0.1.0/src/plugins/loaders/docx_loader.py +89 -0
- doc_ai_runtime-0.1.0/src/plugins/loaders/image_loader.py +41 -0
- doc_ai_runtime-0.1.0/src/plugins/loaders/pdf_loader.py +93 -0
- doc_ai_runtime-0.1.0/src/plugins/loaders/pptx_loader.py +60 -0
- doc_ai_runtime-0.1.0/src/plugins/loaders/xlsx_loader.py +48 -0
- doc_ai_runtime-0.1.0/src/plugins/ocr/qwen_ocr.py +74 -0
- doc_ai_runtime-0.1.0/src/plugins/ocr/tesseract_ocr.py +75 -0
- doc_ai_runtime-0.1.0/src/plugins/reading_order/reading_order_engine.py +99 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 alain2022kalo
|
|
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.
|
|
22
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: doc-ai-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Modular Document AI Runtime for RAG and Markdown exports.
|
|
5
|
+
Author-email: Alain Kalombo <alain.kalombo@anztech.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: python-docx
|
|
10
|
+
Requires-Dist: python-pptx
|
|
11
|
+
Requires-Dist: openpyxl
|
|
12
|
+
Requires-Dist: pytesseract
|
|
13
|
+
Requires-Dist: Pillow
|
|
14
|
+
Requires-Dist: PyMuPDF
|
|
15
|
+
Requires-Dist: surya-ocr
|
|
16
|
+
Requires-Dist: ollama
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# 📄 Document AI Runtime
|
|
20
|
+
|
|
21
|
+
Un pipeline modulaire et extensible pour l'extraction de documents (OCR et Bureautique), conçu pour transformer des PDF, images et Word en formats structurés (Markdown et RAG).
|
|
22
|
+
|
|
23
|
+
Inspiré des capacités de solutions comme ABBYY, ce runtime repose sur une architecture de plugins indépendants manipulant un modèle de données canonique (DOM).
|
|
24
|
+
|
|
25
|
+
## 🚀 Fonctionnalités
|
|
26
|
+
|
|
27
|
+
* **Multi-Formats natifs et OCR :**
|
|
28
|
+
* **Bureautique (Path B)** : DOCX, XLSX (Excel), PPTX (PowerPoint) extraits nativement.
|
|
29
|
+
* **PDF Hybride** : Extrait le calque texte natif, et bascule automatiquement sur l'OCR (Surya + Tesseract) pour les pages scannées.
|
|
30
|
+
* **Images (Path A)** : JPG, PNG traités via IA (Surya Layout + Tesseract OCR).
|
|
31
|
+
* **Moteur XY-Cut** : Algorithme récursif de coupe verticale/horizontale pour reconstruire l'ordre de lecture des documents multi-colonnes complexes.
|
|
32
|
+
* **Exports spécialisés :** Markdown (structuré) et RAG (JSON chunké avec métadonnées).
|
|
33
|
+
|
|
34
|
+
## 📦 Installation
|
|
35
|
+
|
|
36
|
+
Installer la bibliothèque et ses dépendances :
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install -e .
|
|
40
|
+
|
|
41
|
+
## 🛠 Architecture
|
|
42
|
+
|
|
43
|
+
Le projet est construit autour de 4 piliers :
|
|
44
|
+
1. **Le DOM (Document Object Model) :** Des classes Python (`Document`, `Page`, `Region`, `Block`, `Table`, `Cell`) qui modélisent le document de bout en bout.
|
|
45
|
+
2. **Les Interfaces :** `IDocumentLoader` et `IDocumentPlugin` garantissent que tous les modules (Surya, Tesseract, python-docx) communiquent avec le même langage.
|
|
46
|
+
3. **Les Plugins :** Chaque étape (chargement, layout, OCR) est un module interchangeable dans `src/plugins/`. *Remplacer Surya par un autre moteur de layout n'impacte pas le reste du code.*
|
|
47
|
+
4. **Le Pipeline Runner :** L'orchestrateur qui détecte le type de fichier et exécute le bon chemin (A ou B) automatiquement.
|
|
48
|
+
|
|
49
|
+
## 📦 Installation
|
|
50
|
+
|
|
51
|
+
### 1. Prérequis Python
|
|
52
|
+
Clonez le dépôt et installez les dépendances Python :
|
|
53
|
+
```bash
|
|
54
|
+
pip install python-docx pytesseract Pillow PyMuPDF surya-ocr
|
|
55
|
+
|
|
56
|
+
### 2. Dépendances Système
|
|
57
|
+
Tesseract OCR :
|
|
58
|
+
Windows : Téléchargez l'installeur sur UB-Mannheim et ajoutez-le au PATH.
|
|
59
|
+
Linux : sudo apt install tesseract-ocr
|
|
60
|
+
Surya OCR (Optionnel) : Nécessite llama.cpp pour fonctionner. Le runner peut fonctionner avec Tesseract seul si Surya n'est pas configuré.
|
|
61
|
+
|
|
62
|
+
🏃 Utilisation
|
|
63
|
+
|
|
64
|
+
Le runtime s'utilise via le script test_runtime.py (ou votre propre script) qui appelle le PipelineRunner.
|
|
65
|
+
|
|
66
|
+
from src.core.pipeline.runner import PipelineRunner
|
|
67
|
+
|
|
68
|
+
runner = PipelineRunner()
|
|
69
|
+
|
|
70
|
+
# Pour un PDF ou une Image -> Export Markdown
|
|
71
|
+
|
|
72
|
+
result_md = runner.process("mon_document.pdf", export_mode="markdown")
|
|
73
|
+
print(result_md)
|
|
74
|
+
|
|
75
|
+
# Pour un Word -> Export RAG
|
|
76
|
+
|
|
77
|
+
result_rag = runner.process("mon_document.docx", export_mode="rag")
|
|
78
|
+
print(result_rag)
|
|
79
|
+
|
|
80
|
+
🏃 Utilisation (CLI)
|
|
81
|
+
|
|
82
|
+
python main.py --file mon_document.pdf --export markdown
|
|
83
|
+
|
|
84
|
+
🗂 Structure du dépôt
|
|
85
|
+
|
|
86
|
+
doc-ai-runtime/
|
|
87
|
+
├── src/
|
|
88
|
+
│ ├── core/ # Le cœur (DOM, Interfaces, Runner)
|
|
89
|
+
│ │ ├── dom/ # Modèles de données (Document, Page, Block...)
|
|
90
|
+
│ │ └── pipeline/ # Orchestrateur (runner.py)
|
|
91
|
+
│ ├── plugins/ # Les briques interchangeables
|
|
92
|
+
│ │ ├── loaders/ # ImageLoader, PdfLoader, DocxLoader
|
|
93
|
+
│ │ ├── layout/ # SuryaLayoutPlugin
|
|
94
|
+
│ │ └── ocr/ # TesseractOCRPlugin
|
|
95
|
+
│ └── exporters/ # MarkdownExporter, RagExporter
|
|
96
|
+
├── test_runtime.py # Script de démonstration
|
|
97
|
+
└── README.md
|
|
98
|
+
|
|
99
|
+
🗺 Feuille de route (Roadmap)
|
|
100
|
+
|
|
101
|
+
Document Object Model (DOM)
|
|
102
|
+
Loaders (DOCX, Images, PDF)
|
|
103
|
+
Layout Analysis (Surya) & OCR (Tesseract)
|
|
104
|
+
Exporters Markdown et RAG
|
|
105
|
+
Image Quality Analyzer (pré-traitement des scans)
|
|
106
|
+
Amélioration du moteur d'ordre de lecture (Reading Order Engine)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 📄 Document AI Runtime
|
|
2
|
+
|
|
3
|
+
Un pipeline modulaire et extensible pour l'extraction de documents (OCR et Bureautique), conçu pour transformer des PDF, images et Word en formats structurés (Markdown et RAG).
|
|
4
|
+
|
|
5
|
+
Inspiré des capacités de solutions comme ABBYY, ce runtime repose sur une architecture de plugins indépendants manipulant un modèle de données canonique (DOM).
|
|
6
|
+
|
|
7
|
+
## 🚀 Fonctionnalités
|
|
8
|
+
|
|
9
|
+
* **Multi-Formats natifs et OCR :**
|
|
10
|
+
* **Bureautique (Path B)** : DOCX, XLSX (Excel), PPTX (PowerPoint) extraits nativement.
|
|
11
|
+
* **PDF Hybride** : Extrait le calque texte natif, et bascule automatiquement sur l'OCR (Surya + Tesseract) pour les pages scannées.
|
|
12
|
+
* **Images (Path A)** : JPG, PNG traités via IA (Surya Layout + Tesseract OCR).
|
|
13
|
+
* **Moteur XY-Cut** : Algorithme récursif de coupe verticale/horizontale pour reconstruire l'ordre de lecture des documents multi-colonnes complexes.
|
|
14
|
+
* **Exports spécialisés :** Markdown (structuré) et RAG (JSON chunké avec métadonnées).
|
|
15
|
+
|
|
16
|
+
## 📦 Installation
|
|
17
|
+
|
|
18
|
+
Installer la bibliothèque et ses dépendances :
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install -e .
|
|
22
|
+
|
|
23
|
+
## 🛠 Architecture
|
|
24
|
+
|
|
25
|
+
Le projet est construit autour de 4 piliers :
|
|
26
|
+
1. **Le DOM (Document Object Model) :** Des classes Python (`Document`, `Page`, `Region`, `Block`, `Table`, `Cell`) qui modélisent le document de bout en bout.
|
|
27
|
+
2. **Les Interfaces :** `IDocumentLoader` et `IDocumentPlugin` garantissent que tous les modules (Surya, Tesseract, python-docx) communiquent avec le même langage.
|
|
28
|
+
3. **Les Plugins :** Chaque étape (chargement, layout, OCR) est un module interchangeable dans `src/plugins/`. *Remplacer Surya par un autre moteur de layout n'impacte pas le reste du code.*
|
|
29
|
+
4. **Le Pipeline Runner :** L'orchestrateur qui détecte le type de fichier et exécute le bon chemin (A ou B) automatiquement.
|
|
30
|
+
|
|
31
|
+
## 📦 Installation
|
|
32
|
+
|
|
33
|
+
### 1. Prérequis Python
|
|
34
|
+
Clonez le dépôt et installez les dépendances Python :
|
|
35
|
+
```bash
|
|
36
|
+
pip install python-docx pytesseract Pillow PyMuPDF surya-ocr
|
|
37
|
+
|
|
38
|
+
### 2. Dépendances Système
|
|
39
|
+
Tesseract OCR :
|
|
40
|
+
Windows : Téléchargez l'installeur sur UB-Mannheim et ajoutez-le au PATH.
|
|
41
|
+
Linux : sudo apt install tesseract-ocr
|
|
42
|
+
Surya OCR (Optionnel) : Nécessite llama.cpp pour fonctionner. Le runner peut fonctionner avec Tesseract seul si Surya n'est pas configuré.
|
|
43
|
+
|
|
44
|
+
🏃 Utilisation
|
|
45
|
+
|
|
46
|
+
Le runtime s'utilise via le script test_runtime.py (ou votre propre script) qui appelle le PipelineRunner.
|
|
47
|
+
|
|
48
|
+
from src.core.pipeline.runner import PipelineRunner
|
|
49
|
+
|
|
50
|
+
runner = PipelineRunner()
|
|
51
|
+
|
|
52
|
+
# Pour un PDF ou une Image -> Export Markdown
|
|
53
|
+
|
|
54
|
+
result_md = runner.process("mon_document.pdf", export_mode="markdown")
|
|
55
|
+
print(result_md)
|
|
56
|
+
|
|
57
|
+
# Pour un Word -> Export RAG
|
|
58
|
+
|
|
59
|
+
result_rag = runner.process("mon_document.docx", export_mode="rag")
|
|
60
|
+
print(result_rag)
|
|
61
|
+
|
|
62
|
+
🏃 Utilisation (CLI)
|
|
63
|
+
|
|
64
|
+
python main.py --file mon_document.pdf --export markdown
|
|
65
|
+
|
|
66
|
+
🗂 Structure du dépôt
|
|
67
|
+
|
|
68
|
+
doc-ai-runtime/
|
|
69
|
+
├── src/
|
|
70
|
+
│ ├── core/ # Le cœur (DOM, Interfaces, Runner)
|
|
71
|
+
│ │ ├── dom/ # Modèles de données (Document, Page, Block...)
|
|
72
|
+
│ │ └── pipeline/ # Orchestrateur (runner.py)
|
|
73
|
+
│ ├── plugins/ # Les briques interchangeables
|
|
74
|
+
│ │ ├── loaders/ # ImageLoader, PdfLoader, DocxLoader
|
|
75
|
+
│ │ ├── layout/ # SuryaLayoutPlugin
|
|
76
|
+
│ │ └── ocr/ # TesseractOCRPlugin
|
|
77
|
+
│ └── exporters/ # MarkdownExporter, RagExporter
|
|
78
|
+
├── test_runtime.py # Script de démonstration
|
|
79
|
+
└── README.md
|
|
80
|
+
|
|
81
|
+
🗺 Feuille de route (Roadmap)
|
|
82
|
+
|
|
83
|
+
Document Object Model (DOM)
|
|
84
|
+
Loaders (DOCX, Images, PDF)
|
|
85
|
+
Layout Analysis (Surya) & OCR (Tesseract)
|
|
86
|
+
Exporters Markdown et RAG
|
|
87
|
+
Image Quality Analyzer (pré-traitement des scans)
|
|
88
|
+
Amélioration du moteur d'ordre de lecture (Reading Order Engine)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: doc-ai-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Modular Document AI Runtime for RAG and Markdown exports.
|
|
5
|
+
Author-email: Alain Kalombo <alain.kalombo@anztech.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: python-docx
|
|
10
|
+
Requires-Dist: python-pptx
|
|
11
|
+
Requires-Dist: openpyxl
|
|
12
|
+
Requires-Dist: pytesseract
|
|
13
|
+
Requires-Dist: Pillow
|
|
14
|
+
Requires-Dist: PyMuPDF
|
|
15
|
+
Requires-Dist: surya-ocr
|
|
16
|
+
Requires-Dist: ollama
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# 📄 Document AI Runtime
|
|
20
|
+
|
|
21
|
+
Un pipeline modulaire et extensible pour l'extraction de documents (OCR et Bureautique), conçu pour transformer des PDF, images et Word en formats structurés (Markdown et RAG).
|
|
22
|
+
|
|
23
|
+
Inspiré des capacités de solutions comme ABBYY, ce runtime repose sur une architecture de plugins indépendants manipulant un modèle de données canonique (DOM).
|
|
24
|
+
|
|
25
|
+
## 🚀 Fonctionnalités
|
|
26
|
+
|
|
27
|
+
* **Multi-Formats natifs et OCR :**
|
|
28
|
+
* **Bureautique (Path B)** : DOCX, XLSX (Excel), PPTX (PowerPoint) extraits nativement.
|
|
29
|
+
* **PDF Hybride** : Extrait le calque texte natif, et bascule automatiquement sur l'OCR (Surya + Tesseract) pour les pages scannées.
|
|
30
|
+
* **Images (Path A)** : JPG, PNG traités via IA (Surya Layout + Tesseract OCR).
|
|
31
|
+
* **Moteur XY-Cut** : Algorithme récursif de coupe verticale/horizontale pour reconstruire l'ordre de lecture des documents multi-colonnes complexes.
|
|
32
|
+
* **Exports spécialisés :** Markdown (structuré) et RAG (JSON chunké avec métadonnées).
|
|
33
|
+
|
|
34
|
+
## 📦 Installation
|
|
35
|
+
|
|
36
|
+
Installer la bibliothèque et ses dépendances :
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install -e .
|
|
40
|
+
|
|
41
|
+
## 🛠 Architecture
|
|
42
|
+
|
|
43
|
+
Le projet est construit autour de 4 piliers :
|
|
44
|
+
1. **Le DOM (Document Object Model) :** Des classes Python (`Document`, `Page`, `Region`, `Block`, `Table`, `Cell`) qui modélisent le document de bout en bout.
|
|
45
|
+
2. **Les Interfaces :** `IDocumentLoader` et `IDocumentPlugin` garantissent que tous les modules (Surya, Tesseract, python-docx) communiquent avec le même langage.
|
|
46
|
+
3. **Les Plugins :** Chaque étape (chargement, layout, OCR) est un module interchangeable dans `src/plugins/`. *Remplacer Surya par un autre moteur de layout n'impacte pas le reste du code.*
|
|
47
|
+
4. **Le Pipeline Runner :** L'orchestrateur qui détecte le type de fichier et exécute le bon chemin (A ou B) automatiquement.
|
|
48
|
+
|
|
49
|
+
## 📦 Installation
|
|
50
|
+
|
|
51
|
+
### 1. Prérequis Python
|
|
52
|
+
Clonez le dépôt et installez les dépendances Python :
|
|
53
|
+
```bash
|
|
54
|
+
pip install python-docx pytesseract Pillow PyMuPDF surya-ocr
|
|
55
|
+
|
|
56
|
+
### 2. Dépendances Système
|
|
57
|
+
Tesseract OCR :
|
|
58
|
+
Windows : Téléchargez l'installeur sur UB-Mannheim et ajoutez-le au PATH.
|
|
59
|
+
Linux : sudo apt install tesseract-ocr
|
|
60
|
+
Surya OCR (Optionnel) : Nécessite llama.cpp pour fonctionner. Le runner peut fonctionner avec Tesseract seul si Surya n'est pas configuré.
|
|
61
|
+
|
|
62
|
+
🏃 Utilisation
|
|
63
|
+
|
|
64
|
+
Le runtime s'utilise via le script test_runtime.py (ou votre propre script) qui appelle le PipelineRunner.
|
|
65
|
+
|
|
66
|
+
from src.core.pipeline.runner import PipelineRunner
|
|
67
|
+
|
|
68
|
+
runner = PipelineRunner()
|
|
69
|
+
|
|
70
|
+
# Pour un PDF ou une Image -> Export Markdown
|
|
71
|
+
|
|
72
|
+
result_md = runner.process("mon_document.pdf", export_mode="markdown")
|
|
73
|
+
print(result_md)
|
|
74
|
+
|
|
75
|
+
# Pour un Word -> Export RAG
|
|
76
|
+
|
|
77
|
+
result_rag = runner.process("mon_document.docx", export_mode="rag")
|
|
78
|
+
print(result_rag)
|
|
79
|
+
|
|
80
|
+
🏃 Utilisation (CLI)
|
|
81
|
+
|
|
82
|
+
python main.py --file mon_document.pdf --export markdown
|
|
83
|
+
|
|
84
|
+
🗂 Structure du dépôt
|
|
85
|
+
|
|
86
|
+
doc-ai-runtime/
|
|
87
|
+
├── src/
|
|
88
|
+
│ ├── core/ # Le cœur (DOM, Interfaces, Runner)
|
|
89
|
+
│ │ ├── dom/ # Modèles de données (Document, Page, Block...)
|
|
90
|
+
│ │ └── pipeline/ # Orchestrateur (runner.py)
|
|
91
|
+
│ ├── plugins/ # Les briques interchangeables
|
|
92
|
+
│ │ ├── loaders/ # ImageLoader, PdfLoader, DocxLoader
|
|
93
|
+
│ │ ├── layout/ # SuryaLayoutPlugin
|
|
94
|
+
│ │ └── ocr/ # TesseractOCRPlugin
|
|
95
|
+
│ └── exporters/ # MarkdownExporter, RagExporter
|
|
96
|
+
├── test_runtime.py # Script de démonstration
|
|
97
|
+
└── README.md
|
|
98
|
+
|
|
99
|
+
🗺 Feuille de route (Roadmap)
|
|
100
|
+
|
|
101
|
+
Document Object Model (DOM)
|
|
102
|
+
Loaders (DOCX, Images, PDF)
|
|
103
|
+
Layout Analysis (Surya) & OCR (Tesseract)
|
|
104
|
+
Exporters Markdown et RAG
|
|
105
|
+
Image Quality Analyzer (pré-traitement des scans)
|
|
106
|
+
Amélioration du moteur d'ordre de lecture (Reading Order Engine)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
doc_ai_runtime.egg-info/PKG-INFO
|
|
5
|
+
doc_ai_runtime.egg-info/SOURCES.txt
|
|
6
|
+
doc_ai_runtime.egg-info/dependency_links.txt
|
|
7
|
+
doc_ai_runtime.egg-info/requires.txt
|
|
8
|
+
doc_ai_runtime.egg-info/top_level.txt
|
|
9
|
+
src/core/config.py
|
|
10
|
+
src/core/interfaces.py
|
|
11
|
+
src/core/dom/models.py
|
|
12
|
+
src/core/pipeline/runner.py
|
|
13
|
+
src/exporters/markdown.py
|
|
14
|
+
src/exporters/rag.py
|
|
15
|
+
src/plugins/layout/surya_layout.py
|
|
16
|
+
src/plugins/loaders/docx_loader.py
|
|
17
|
+
src/plugins/loaders/image_loader.py
|
|
18
|
+
src/plugins/loaders/pdf_loader.py
|
|
19
|
+
src/plugins/loaders/pptx_loader.py
|
|
20
|
+
src/plugins/loaders/xlsx_loader.py
|
|
21
|
+
src/plugins/ocr/qwen_ocr.py
|
|
22
|
+
src/plugins/ocr/tesseract_ocr.py
|
|
23
|
+
src/plugins/reading_order/reading_order_engine.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
src
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "doc-ai-runtime"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Modular Document AI Runtime for RAG and Markdown exports."
|
|
9
|
+
authors = [{ name = "Alain Kalombo", email = "alain.kalombo@anztech.dev" }]
|
|
10
|
+
readme = "README.md" # Indique à PyPI d'afficher ton README sur sa page web
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
dependencies = [
|
|
13
|
+
"python-docx",
|
|
14
|
+
"python-pptx",
|
|
15
|
+
"openpyxl",
|
|
16
|
+
"pytesseract",
|
|
17
|
+
"Pillow",
|
|
18
|
+
"PyMuPDF",
|
|
19
|
+
"surya-ocr",
|
|
20
|
+
"ollama"
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["."]
|
|
25
|
+
include = ["src*"]
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import List, Optional, Dict, Any
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
class RegionType(Enum):
|
|
7
|
+
TITLE = "title"
|
|
8
|
+
TEXT = "text"
|
|
9
|
+
TABLE = "table"
|
|
10
|
+
IMAGE = "image"
|
|
11
|
+
LIST = "list"
|
|
12
|
+
CAPTION = "caption"
|
|
13
|
+
HEADER = "header"
|
|
14
|
+
FOOTER = "footer"
|
|
15
|
+
|
|
16
|
+
class BlockType(Enum):
|
|
17
|
+
TEXT = "text"
|
|
18
|
+
TABLE_CELL = "table_cell"
|
|
19
|
+
IMAGE = "image"
|
|
20
|
+
EMPTY = "empty"
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class BoundingBox:
|
|
24
|
+
"""Représente les coordonnées spatiales d'un élément sur la page."""
|
|
25
|
+
x: float
|
|
26
|
+
y: float
|
|
27
|
+
width: float
|
|
28
|
+
height: float
|
|
29
|
+
confidence: float = 1.0
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class Style:
|
|
33
|
+
"""Définit le style typographique d'un bloc de texte."""
|
|
34
|
+
font_name: Optional[str] = None
|
|
35
|
+
font_size: Optional[float] = None
|
|
36
|
+
bold: bool = False
|
|
37
|
+
italic: bool = False
|
|
38
|
+
underline: bool = False
|
|
39
|
+
color: Optional[str] = None # Format hexadécimal, ex: '#000000'
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class Cell:
|
|
43
|
+
"""Représente une cellule d'un tableau."""
|
|
44
|
+
bbox: BoundingBox
|
|
45
|
+
text: str = ""
|
|
46
|
+
row_span: int = 1
|
|
47
|
+
col_span: int = 1
|
|
48
|
+
is_header: bool = False
|
|
49
|
+
confidence: float = 1.0
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class Table:
|
|
53
|
+
"""Représente un tableau structuré."""
|
|
54
|
+
bbox: BoundingBox
|
|
55
|
+
rows: int = 0
|
|
56
|
+
cols: int = 0
|
|
57
|
+
cells: List[Cell] = field(default_factory=list)
|
|
58
|
+
reading_order: int = 0
|
|
59
|
+
|
|
60
|
+
def get_markdown(self) -> str:
|
|
61
|
+
"""Méthode utilitaire pour un export Markdown rapide (utile plus tard)."""
|
|
62
|
+
if not self.cells:
|
|
63
|
+
return ""
|
|
64
|
+
# Logique de génération Markdown basique à implémenter
|
|
65
|
+
return "[Tableau Markdown]"
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class Image:
|
|
69
|
+
"""Représente une image détectée dans le document."""
|
|
70
|
+
bbox: BoundingBox
|
|
71
|
+
image_data: Optional[bytes] = None # Stockage binaire ou base64
|
|
72
|
+
image_path: Optional[str] = None # Chemin si sauvegardée sur disque
|
|
73
|
+
caption: Optional[str] = None
|
|
74
|
+
reading_order: int = 0
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class Block:
|
|
78
|
+
"""L'unité de base de contenu (texte, image, etc.)."""
|
|
79
|
+
bbox: BoundingBox
|
|
80
|
+
block_type: BlockType = BlockType.TEXT
|
|
81
|
+
text: str = ""
|
|
82
|
+
style: Style = field(default_factory=Style)
|
|
83
|
+
reading_order: int = 0 # Indispensable pour le RAG et le Markdown
|
|
84
|
+
confidence: float = 1.0
|
|
85
|
+
heading_level: Optional[int] = None # <-- AJOUT : None si ce n'est pas un titre, 1 pour H1, 2 pour H2, etc.
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class Region:
|
|
89
|
+
"""Une zone logique de la page regroupant des blocs."""
|
|
90
|
+
bbox: BoundingBox
|
|
91
|
+
region_type: RegionType = RegionType.TEXT
|
|
92
|
+
blocks: List[Block] = field(default_factory=list)
|
|
93
|
+
tables: List[Table] = field(default_factory=list)
|
|
94
|
+
images: List[Image] = field(default_factory=list)
|
|
95
|
+
reading_order: int = 0
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class Page:
|
|
99
|
+
"""Représente une page physique du document."""
|
|
100
|
+
page_number: int
|
|
101
|
+
width: float
|
|
102
|
+
height: float
|
|
103
|
+
regions: List[Region] = field(default_factory=list)
|
|
104
|
+
image_path: Optional[str] = None
|
|
105
|
+
|
|
106
|
+
def get_all_blocks_in_reading_order(self) -> List[Block]:
|
|
107
|
+
"""Retourne tous les blocs de la page triés par ordre de lecture."""
|
|
108
|
+
blocks = []
|
|
109
|
+
for region in sorted(self.regions, key=lambda r: r.reading_order):
|
|
110
|
+
blocks.extend(sorted(region.blocks, key=lambda b: b.reading_order))
|
|
111
|
+
return blocks
|
|
112
|
+
|
|
113
|
+
@dataclass
|
|
114
|
+
class Document:
|
|
115
|
+
"""Le modèle racine représentant le document complet."""
|
|
116
|
+
source_file: str
|
|
117
|
+
pages: List[Page] = field(default_factory=list)
|
|
118
|
+
metadata: Dict[str, Any] = field(default_factory=dict) # Auteur, date, titre, etc.
|
|
119
|
+
|
|
120
|
+
def get_text(self) -> str:
|
|
121
|
+
"""Extrait tout le texte du document dans l'ordre de lecture (base pour le RAG)."""
|
|
122
|
+
full_text = []
|
|
123
|
+
for page in self.pages:
|
|
124
|
+
for block in page.get_all_blocks_in_reading_order():
|
|
125
|
+
if block.text:
|
|
126
|
+
full_text.append(block.text)
|
|
127
|
+
return "\n\n".join(full_text)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any
|
|
3
|
+
from src.core.dom.models import Document
|
|
4
|
+
|
|
5
|
+
class IDocumentLoader(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Interface pour les plugins de chargement (Étape 1 du pipeline).
|
|
8
|
+
Prend un fichier brut en entrée et génère l'objet Document initial.
|
|
9
|
+
"""
|
|
10
|
+
@property
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def name(self) -> str:
|
|
13
|
+
"""Retourne le nom du chargeur (ex: 'PdfLoader', 'DocxLoader')."""
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def load(self, file_path: str) -> Document:
|
|
18
|
+
"""
|
|
19
|
+
Charge un fichier et retourne un objet Document partiellement ou
|
|
20
|
+
totalement rempli (selon si c'est une image ou un doc natif).
|
|
21
|
+
"""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
class IDocumentPlugin(ABC):
|
|
25
|
+
"""
|
|
26
|
+
Interface de base pour toutes les autres étapes du pipeline
|
|
27
|
+
(Layout, OCR, Reconstruction, Exporters).
|
|
28
|
+
"""
|
|
29
|
+
@property
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def name(self) -> str:
|
|
32
|
+
"""Retourne le nom du plugin (ex: 'SuryaLayoutAnalyzer')."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def run(self, document: Document) -> Document:
|
|
37
|
+
"""
|
|
38
|
+
Reçoit l'objet Document, effectue un traitement (ajout de blocs,
|
|
39
|
+
extraction de texte, etc.) et retourne l'objet Document mis à jour.
|
|
40
|
+
"""
|
|
41
|
+
pass
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
|
|
4
|
+
if platform.system() == "Windows":
|
|
5
|
+
# Chemin pour ta machine Windows
|
|
6
|
+
os.environ["LLAMA_CPP_BINARY"] = r"c:\llama.cpp\llama-server.exe"
|
|
7
|
+
else:
|
|
8
|
+
# Chemin pour ton serveur Ubuntu (Linux)
|
|
9
|
+
os.environ["LLAMA_CPP_BINARY"] = "/home/linuxbrew/.linuxbrew/bin/llama-server"
|
|
10
|
+
|
|
11
|
+
os.environ["SURYA_INFERENCE_BACKEND"] = "llamacpp"
|
|
12
|
+
os.environ["SURYA_GUIDED_LAYOUT"] = "False"
|
|
13
|
+
|
|
14
|
+
from src.plugins.loaders.image_loader import ImageLoader
|
|
15
|
+
from src.plugins.loaders.docx_loader import DocxLoader
|
|
16
|
+
from src.plugins.loaders.pdf_loader import PdfLoader
|
|
17
|
+
from src.plugins.reading_order.reading_order_engine import ReadingOrderPlugin
|
|
18
|
+
|
|
19
|
+
from src.plugins.loaders.xlsx_loader import XlsxLoader
|
|
20
|
+
from src.plugins.loaders.pptx_loader import PptxLoader
|
|
21
|
+
from src.plugins.ocr.qwen_ocr import QwenOCRPlugin
|
|
22
|
+
|
|
23
|
+
from src.plugins.layout.surya_layout import SuryaLayoutPlugin
|
|
24
|
+
from src.plugins.ocr.tesseract_ocr import TesseractOCRPlugin
|
|
25
|
+
from src.exporters.markdown import MarkdownExporter
|
|
26
|
+
from src.exporters.rag import RagExporter
|
|
27
|
+
|
|
28
|
+
class PipelineRunner:
|
|
29
|
+
def __init__(self):
|
|
30
|
+
self.markdown_exporter = MarkdownExporter()
|
|
31
|
+
self.rag_exporter = RagExporter()
|
|
32
|
+
|
|
33
|
+
def process(self, file_path: str, export_mode: str = "markdown") -> str:
|
|
34
|
+
_, ext = os.path.splitext(file_path)
|
|
35
|
+
ext = ext.lower()
|
|
36
|
+
document = None
|
|
37
|
+
|
|
38
|
+
# --- PATH B : PDF (Hybride Natif + OCR) ---
|
|
39
|
+
if ext == ".pdf":
|
|
40
|
+
print("-> Fichier PDF détecté. Analyse (Hybride)...")
|
|
41
|
+
loader = PdfLoader()
|
|
42
|
+
document = loader.load(file_path)
|
|
43
|
+
|
|
44
|
+
elif ext == ".docx":
|
|
45
|
+
print("-> Fichier DOCX détecté. Extraction native.")
|
|
46
|
+
loader = DocxLoader()
|
|
47
|
+
document = loader.load(file_path)
|
|
48
|
+
|
|
49
|
+
elif ext == ".xlsx":
|
|
50
|
+
print("-> Fichier XLSX détecté. Extraction native (Tableaux).")
|
|
51
|
+
loader = XlsxLoader()
|
|
52
|
+
document = loader.load(file_path)
|
|
53
|
+
|
|
54
|
+
elif ext == ".pptx":
|
|
55
|
+
print("-> Fichier PPTX détecté. Extraction native (Slides).")
|
|
56
|
+
loader = PptxLoader()
|
|
57
|
+
document = loader.load(file_path)
|
|
58
|
+
|
|
59
|
+
# --- PATH A : Images pures (OCR) ---
|
|
60
|
+
elif ext in [".jpg", ".jpeg", ".png", ".tiff", ".bmp"]:
|
|
61
|
+
print("-> Fichier Image détecté. Utilisation OCR.")
|
|
62
|
+
loader = ImageLoader()
|
|
63
|
+
document = loader.load(file_path)
|
|
64
|
+
|
|
65
|
+
print(" ... Calcul de l'ordre de lecture")
|
|
66
|
+
reading_order_plugin = ReadingOrderPlugin()
|
|
67
|
+
document = reading_order_plugin.run(document)
|
|
68
|
+
|
|
69
|
+
# 4. OCR (Qwen2.5-VL lit dans les boîtes de Surya)
|
|
70
|
+
print(" ... Extraction du texte (Qwen2.5-VL via Ollama)")
|
|
71
|
+
# ocr_plugin = TesseractOCRPlugin() <-- On commente Tesseract
|
|
72
|
+
ocr_plugin = QwenOCRPlugin()
|
|
73
|
+
document = ocr_plugin.run(document)
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError(f"Format non supporté : {ext}")
|
|
77
|
+
|
|
78
|
+
print(f"-> Export demandé : {export_mode}")
|
|
79
|
+
if export_mode == "rag":
|
|
80
|
+
return self.rag_exporter.export(document, mode="semantic_chunks")
|
|
81
|
+
else:
|
|
82
|
+
return self.markdown_exporter.export(document)
|
|
83
|
+
|