natural-pdf 0.1.4__py3-none-any.whl → 0.1.5__py3-none-any.whl
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.
- docs/api/index.md +386 -0
- docs/assets/favicon.png +3 -0
- docs/assets/favicon.svg +3 -0
- docs/assets/javascripts/custom.js +17 -0
- docs/assets/logo.svg +3 -0
- docs/assets/sample-screen.png +0 -0
- docs/assets/social-preview.png +17 -0
- docs/assets/social-preview.svg +17 -0
- docs/assets/stylesheets/custom.css +65 -0
- docs/document-qa/index.ipynb +435 -0
- docs/document-qa/index.md +79 -0
- docs/element-selection/index.ipynb +915 -0
- docs/element-selection/index.md +229 -0
- docs/index.md +170 -0
- docs/installation/index.md +69 -0
- docs/interactive-widget/index.ipynb +962 -0
- docs/interactive-widget/index.md +12 -0
- docs/layout-analysis/index.ipynb +818 -0
- docs/layout-analysis/index.md +185 -0
- docs/ocr/index.md +222 -0
- docs/pdf-navigation/index.ipynb +314 -0
- docs/pdf-navigation/index.md +97 -0
- docs/regions/index.ipynb +816 -0
- docs/regions/index.md +294 -0
- docs/tables/index.ipynb +658 -0
- docs/tables/index.md +144 -0
- docs/text-analysis/index.ipynb +370 -0
- docs/text-analysis/index.md +105 -0
- docs/text-extraction/index.ipynb +1478 -0
- docs/text-extraction/index.md +292 -0
- docs/tutorials/01-loading-and-extraction.ipynb +1696 -0
- docs/tutorials/01-loading-and-extraction.md +95 -0
- docs/tutorials/02-finding-elements.ipynb +340 -0
- docs/tutorials/02-finding-elements.md +149 -0
- docs/tutorials/03-extracting-blocks.ipynb +147 -0
- docs/tutorials/03-extracting-blocks.md +48 -0
- docs/tutorials/04-table-extraction.ipynb +114 -0
- docs/tutorials/04-table-extraction.md +50 -0
- docs/tutorials/05-excluding-content.ipynb +270 -0
- docs/tutorials/05-excluding-content.md +109 -0
- docs/tutorials/06-document-qa.ipynb +332 -0
- docs/tutorials/06-document-qa.md +91 -0
- docs/tutorials/07-layout-analysis.ipynb +260 -0
- docs/tutorials/07-layout-analysis.md +66 -0
- docs/tutorials/07-working-with-regions.ipynb +409 -0
- docs/tutorials/07-working-with-regions.md +151 -0
- docs/tutorials/08-spatial-navigation.ipynb +508 -0
- docs/tutorials/08-spatial-navigation.md +190 -0
- docs/tutorials/09-section-extraction.ipynb +2434 -0
- docs/tutorials/09-section-extraction.md +256 -0
- docs/tutorials/10-form-field-extraction.ipynb +484 -0
- docs/tutorials/10-form-field-extraction.md +201 -0
- docs/tutorials/11-enhanced-table-processing.ipynb +54 -0
- docs/tutorials/11-enhanced-table-processing.md +9 -0
- docs/tutorials/12-ocr-integration.ipynb +586 -0
- docs/tutorials/12-ocr-integration.md +188 -0
- docs/tutorials/13-semantic-search.ipynb +1888 -0
- docs/tutorials/13-semantic-search.md +77 -0
- docs/visual-debugging/index.ipynb +2970 -0
- docs/visual-debugging/index.md +157 -0
- docs/visual-debugging/region.png +0 -0
- natural_pdf/__init__.py +39 -20
- natural_pdf/analyzers/__init__.py +2 -1
- natural_pdf/analyzers/layout/base.py +32 -24
- natural_pdf/analyzers/layout/docling.py +131 -72
- natural_pdf/analyzers/layout/layout_analyzer.py +156 -113
- natural_pdf/analyzers/layout/layout_manager.py +98 -58
- natural_pdf/analyzers/layout/layout_options.py +32 -17
- natural_pdf/analyzers/layout/paddle.py +152 -95
- natural_pdf/analyzers/layout/surya.py +164 -92
- natural_pdf/analyzers/layout/tatr.py +149 -84
- natural_pdf/analyzers/layout/yolo.py +84 -44
- natural_pdf/analyzers/text_options.py +22 -15
- natural_pdf/analyzers/text_structure.py +131 -85
- natural_pdf/analyzers/utils.py +30 -23
- natural_pdf/collections/pdf_collection.py +125 -97
- natural_pdf/core/__init__.py +1 -1
- natural_pdf/core/element_manager.py +416 -337
- natural_pdf/core/highlighting_service.py +268 -196
- natural_pdf/core/page.py +907 -513
- natural_pdf/core/pdf.py +385 -287
- natural_pdf/elements/__init__.py +1 -1
- natural_pdf/elements/base.py +302 -214
- natural_pdf/elements/collections.py +708 -508
- natural_pdf/elements/line.py +39 -36
- natural_pdf/elements/rect.py +32 -30
- natural_pdf/elements/region.py +854 -883
- natural_pdf/elements/text.py +122 -99
- natural_pdf/exporters/__init__.py +0 -1
- natural_pdf/exporters/searchable_pdf.py +261 -102
- natural_pdf/ocr/__init__.py +23 -14
- natural_pdf/ocr/engine.py +17 -8
- natural_pdf/ocr/engine_easyocr.py +63 -47
- natural_pdf/ocr/engine_paddle.py +97 -68
- natural_pdf/ocr/engine_surya.py +54 -44
- natural_pdf/ocr/ocr_manager.py +88 -62
- natural_pdf/ocr/ocr_options.py +16 -10
- natural_pdf/qa/__init__.py +1 -1
- natural_pdf/qa/document_qa.py +119 -111
- natural_pdf/search/__init__.py +37 -31
- natural_pdf/search/haystack_search_service.py +312 -189
- natural_pdf/search/haystack_utils.py +186 -122
- natural_pdf/search/search_options.py +25 -14
- natural_pdf/search/search_service_protocol.py +12 -6
- natural_pdf/search/searchable_mixin.py +261 -176
- natural_pdf/selectors/__init__.py +2 -1
- natural_pdf/selectors/parser.py +159 -316
- natural_pdf/templates/__init__.py +1 -1
- natural_pdf/utils/highlighting.py +8 -2
- natural_pdf/utils/reading_order.py +65 -63
- natural_pdf/utils/text_extraction.py +195 -0
- natural_pdf/utils/visualization.py +70 -61
- natural_pdf/widgets/__init__.py +2 -3
- natural_pdf/widgets/viewer.py +749 -718
- {natural_pdf-0.1.4.dist-info → natural_pdf-0.1.5.dist-info}/METADATA +15 -1
- natural_pdf-0.1.5.dist-info/RECORD +134 -0
- natural_pdf-0.1.5.dist-info/top_level.txt +5 -0
- notebooks/Examples.ipynb +1293 -0
- pdfs/.gitkeep +0 -0
- pdfs/01-practice.pdf +543 -0
- pdfs/0500000US42001.pdf +0 -0
- pdfs/0500000US42007.pdf +0 -0
- pdfs/2014 Statistics.pdf +0 -0
- pdfs/2019 Statistics.pdf +0 -0
- pdfs/Atlanta_Public_Schools_GA_sample.pdf +0 -0
- pdfs/needs-ocr.pdf +0 -0
- tests/test_loading.py +50 -0
- tests/test_optional_deps.py +298 -0
- natural_pdf-0.1.4.dist-info/RECORD +0 -61
- natural_pdf-0.1.4.dist-info/top_level.txt +0 -1
- {natural_pdf-0.1.4.dist-info → natural_pdf-0.1.5.dist-info}/WHEEL +0 -0
- {natural_pdf-0.1.4.dist-info → natural_pdf-0.1.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,15 +1,16 @@
|
|
1
1
|
# layout_manager.py
|
2
|
+
import copy
|
2
3
|
import logging
|
3
|
-
from typing import Dict, List,
|
4
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
5
|
+
|
4
6
|
from PIL import Image
|
5
|
-
import copy
|
6
7
|
|
7
8
|
# --- Import detector classes and options ---
|
8
9
|
# Use try-except blocks for robustness if some detectors might be missing dependencies
|
9
10
|
try:
|
10
11
|
from .base import LayoutDetector
|
11
12
|
except ImportError:
|
12
|
-
LayoutDetector = type(
|
13
|
+
LayoutDetector = type("LayoutDetector", (), {})
|
13
14
|
|
14
15
|
try:
|
15
16
|
from .yolo import YOLODocLayoutDetector
|
@@ -35,14 +36,20 @@ try:
|
|
35
36
|
from .docling import DoclingLayoutDetector
|
36
37
|
except ImportError:
|
37
38
|
DoclingLayoutDetector = None
|
38
|
-
|
39
|
+
|
39
40
|
from .layout_options import (
|
40
|
-
BaseLayoutOptions,
|
41
|
-
|
41
|
+
BaseLayoutOptions,
|
42
|
+
DoclingLayoutOptions,
|
43
|
+
LayoutOptions,
|
44
|
+
PaddleLayoutOptions,
|
45
|
+
SuryaLayoutOptions,
|
46
|
+
TATRLayoutOptions,
|
47
|
+
YOLOLayoutOptions,
|
42
48
|
)
|
43
49
|
|
44
50
|
logger = logging.getLogger(__name__)
|
45
51
|
|
52
|
+
|
46
53
|
class LayoutManager:
|
47
54
|
"""Manages layout detector selection, configuration, and execution."""
|
48
55
|
|
@@ -50,46 +57,70 @@ class LayoutManager:
|
|
50
57
|
ENGINE_REGISTRY: Dict[str, Dict[str, Any]] = {}
|
51
58
|
|
52
59
|
# Populate registry only with available detectors
|
53
|
-
if YOLODocLayoutDetector:
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
if YOLODocLayoutDetector:
|
61
|
+
ENGINE_REGISTRY["yolo"] = {
|
62
|
+
"class": YOLODocLayoutDetector,
|
63
|
+
"options_class": YOLOLayoutOptions,
|
64
|
+
}
|
65
|
+
if TableTransformerDetector:
|
66
|
+
ENGINE_REGISTRY["tatr"] = {
|
67
|
+
"class": TableTransformerDetector,
|
68
|
+
"options_class": TATRLayoutOptions,
|
69
|
+
}
|
70
|
+
if PaddleLayoutDetector:
|
71
|
+
ENGINE_REGISTRY["paddle"] = {
|
72
|
+
"class": PaddleLayoutDetector,
|
73
|
+
"options_class": PaddleLayoutOptions,
|
74
|
+
}
|
75
|
+
if SuryaLayoutDetector:
|
76
|
+
ENGINE_REGISTRY["surya"] = {
|
77
|
+
"class": SuryaLayoutDetector,
|
78
|
+
"options_class": SuryaLayoutOptions,
|
79
|
+
}
|
80
|
+
if DoclingLayoutDetector:
|
81
|
+
ENGINE_REGISTRY["docling"] = {
|
82
|
+
"class": DoclingLayoutDetector,
|
83
|
+
"options_class": DoclingLayoutOptions,
|
84
|
+
}
|
58
85
|
|
59
86
|
# Define the limited set of kwargs allowed for the simple analyze_layout call
|
60
|
-
SIMPLE_MODE_ALLOWED_KWARGS = {
|
61
|
-
'engine', 'confidence', 'classes', 'exclude_classes', 'device'
|
62
|
-
}
|
87
|
+
SIMPLE_MODE_ALLOWED_KWARGS = {"engine", "confidence", "classes", "exclude_classes", "device"}
|
63
88
|
|
64
89
|
def __init__(self):
|
65
90
|
"""Initializes the Layout Manager."""
|
66
91
|
# Cache for detector instances (different from model cache inside detector)
|
67
92
|
self._detector_instances: Dict[str, LayoutDetector] = {}
|
68
|
-
logger.info(
|
93
|
+
logger.info(
|
94
|
+
f"LayoutManager initialized. Available engines: {list(self.ENGINE_REGISTRY.keys())}"
|
95
|
+
)
|
69
96
|
|
70
97
|
def _get_engine_instance(self, engine_name: str) -> LayoutDetector:
|
71
98
|
"""Retrieves or creates an instance of the specified layout detector."""
|
72
99
|
engine_name = engine_name.lower()
|
73
100
|
if engine_name not in self.ENGINE_REGISTRY:
|
74
|
-
raise ValueError(
|
101
|
+
raise ValueError(
|
102
|
+
f"Unknown layout engine: '{engine_name}'. Available: {list(self.ENGINE_REGISTRY.keys())}"
|
103
|
+
)
|
75
104
|
|
76
105
|
if engine_name not in self._detector_instances:
|
77
106
|
logger.info(f"Creating instance of layout engine: {engine_name}")
|
78
|
-
engine_class = self.ENGINE_REGISTRY[engine_name][
|
79
|
-
detector_instance = engine_class()
|
107
|
+
engine_class = self.ENGINE_REGISTRY[engine_name]["class"]
|
108
|
+
detector_instance = engine_class() # Instantiate
|
80
109
|
if not detector_instance.is_available():
|
81
|
-
|
82
|
-
|
83
|
-
|
110
|
+
# Check availability before storing
|
111
|
+
raise RuntimeError(
|
112
|
+
f"Layout engine '{engine_name}' is not available. Please check dependencies."
|
113
|
+
)
|
114
|
+
self._detector_instances[engine_name] = detector_instance # Store if available
|
84
115
|
|
85
116
|
return self._detector_instances[engine_name]
|
86
117
|
|
87
118
|
def analyze_layout(
|
88
119
|
self,
|
89
120
|
image: Image.Image,
|
90
|
-
engine: Optional[str] = None,
|
121
|
+
engine: Optional[str] = None, # Default engine handled below
|
91
122
|
options: Optional[LayoutOptions] = None,
|
92
|
-
**kwargs
|
123
|
+
**kwargs,
|
93
124
|
) -> List[Dict[str, Any]]:
|
94
125
|
"""
|
95
126
|
Analyzes layout of a single image using simple args or an options object.
|
@@ -109,11 +140,11 @@ class LayoutManager:
|
|
109
140
|
selected_engine_name: str
|
110
141
|
|
111
142
|
if not isinstance(image, Image.Image):
|
112
|
-
|
143
|
+
raise TypeError("Input 'image' must be a PIL Image.")
|
113
144
|
|
114
145
|
available_engines = self.get_available_engines()
|
115
146
|
if not available_engines:
|
116
|
-
|
147
|
+
raise RuntimeError("No layout engines are available. Please check dependencies.")
|
117
148
|
|
118
149
|
# Determine default engine if not specified
|
119
150
|
default_engine = engine if engine else available_engines[0]
|
@@ -123,46 +154,55 @@ class LayoutManager:
|
|
123
154
|
# Advanced Mode: An options object was provided directly (or constructed by LayoutAnalyzer)
|
124
155
|
# Use this object directly, do not deep copy or reconstruct.
|
125
156
|
logger.debug(f"LayoutManager: Using provided options object: {type(options).__name__}")
|
126
|
-
final_options = options
|
157
|
+
final_options = options # Use the provided object directly
|
127
158
|
found_engine = False
|
128
159
|
for name, registry_entry in self.ENGINE_REGISTRY.items():
|
129
|
-
if isinstance(options, registry_entry[
|
160
|
+
if isinstance(options, registry_entry["options_class"]):
|
130
161
|
selected_engine_name = name
|
131
162
|
found_engine = True
|
132
163
|
break
|
133
164
|
if not found_engine:
|
134
|
-
|
165
|
+
raise TypeError(
|
166
|
+
f"Provided options object type '{type(options).__name__}' does not match any registered layout engine options."
|
167
|
+
)
|
135
168
|
# Ignore simple kwargs if options object is present
|
136
169
|
if kwargs:
|
137
|
-
logger.warning(
|
170
|
+
logger.warning(
|
171
|
+
f"Keyword arguments {list(kwargs.keys())} were provided alongside an 'options' object and will be ignored."
|
172
|
+
)
|
138
173
|
else:
|
139
|
-
# Simple Mode: No options object provided initially.
|
174
|
+
# Simple Mode: No options object provided initially.
|
140
175
|
# Determine engine from kwargs or default, then construct options.
|
141
176
|
selected_engine_name = default_engine.lower()
|
142
|
-
logger.debug(
|
177
|
+
logger.debug(
|
178
|
+
f"LayoutManager: Using simple mode. Engine: '{selected_engine_name}', kwargs: {kwargs}"
|
179
|
+
)
|
143
180
|
|
144
181
|
if selected_engine_name not in self.ENGINE_REGISTRY:
|
145
|
-
|
182
|
+
raise ValueError(
|
183
|
+
f"Unknown or unavailable layout engine: '{selected_engine_name}'. Available: {available_engines}"
|
184
|
+
)
|
146
185
|
|
147
186
|
unexpected_kwargs = set(kwargs.keys()) - self.SIMPLE_MODE_ALLOWED_KWARGS
|
148
187
|
if unexpected_kwargs:
|
149
|
-
raise TypeError(
|
188
|
+
raise TypeError(
|
189
|
+
f"Got unexpected keyword arguments in simple mode: {list(unexpected_kwargs)}. Use the 'options' parameter for detailed configuration."
|
190
|
+
)
|
150
191
|
|
151
|
-
options_class = self.ENGINE_REGISTRY[selected_engine_name][
|
192
|
+
options_class = self.ENGINE_REGISTRY[selected_engine_name]["options_class"]
|
152
193
|
# Use BaseLayoutOptions defaults unless overridden by kwargs
|
153
194
|
base_defaults = BaseLayoutOptions()
|
154
195
|
simple_args = {
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
196
|
+
"confidence": kwargs.get("confidence", base_defaults.confidence),
|
197
|
+
"classes": kwargs.get("classes"),
|
198
|
+
"exclude_classes": kwargs.get("exclude_classes"),
|
199
|
+
"device": kwargs.get("device", base_defaults.device),
|
159
200
|
}
|
160
201
|
# Filter out None values before passing to constructor
|
161
202
|
simple_args_filtered = {k: v for k, v in simple_args.items() if v is not None}
|
162
203
|
final_options = options_class(**simple_args_filtered)
|
163
204
|
logger.debug(f"LayoutManager: Constructed options for simple mode: {final_options}")
|
164
205
|
|
165
|
-
|
166
206
|
# --- Get Engine Instance and Process ---
|
167
207
|
try:
|
168
208
|
engine_instance = self._get_engine_instance(selected_engine_name)
|
@@ -175,29 +215,29 @@ class LayoutManager:
|
|
175
215
|
return detections
|
176
216
|
|
177
217
|
except (ImportError, RuntimeError, ValueError, TypeError) as e:
|
178
|
-
|
179
|
-
|
218
|
+
logger.error(
|
219
|
+
f"Layout analysis failed for engine '{selected_engine_name}': {e}", exc_info=True
|
220
|
+
)
|
221
|
+
raise # Re-raise expected errors
|
180
222
|
except Exception as e:
|
181
|
-
|
182
|
-
|
183
|
-
|
223
|
+
logger.error(f"An unexpected error occurred during layout analysis: {e}", exc_info=True)
|
224
|
+
raise # Re-raise unexpected errors
|
184
225
|
|
185
226
|
def get_available_engines(self) -> List[str]:
|
186
227
|
"""Returns a list of registered layout engine names that are currently available."""
|
187
228
|
available = []
|
188
229
|
for name, registry_entry in self.ENGINE_REGISTRY.items():
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
230
|
+
try:
|
231
|
+
engine_class = registry_entry["class"]
|
232
|
+
# Check availability without full instantiation if possible
|
233
|
+
if hasattr(engine_class, "is_available") and callable(engine_class.is_available):
|
234
|
+
# Create temporary instance only for check if needed, or use classmethod
|
235
|
+
if engine_class().is_available(): # Assumes instance needed for check
|
236
|
+
available.append(name)
|
237
|
+
else:
|
238
|
+
# Assume available if class exists (less robust)
|
239
|
+
available.append(name)
|
240
|
+
except Exception as e:
|
241
|
+
logger.debug(f"Layout engine '{name}' check failed: {e}")
|
242
|
+
pass
|
202
243
|
return available
|
203
|
-
|
@@ -1,32 +1,40 @@
|
|
1
1
|
# layout_options.py
|
2
2
|
import logging
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
5
5
|
|
6
6
|
logger = logging.getLogger(__name__)
|
7
7
|
|
8
|
+
|
8
9
|
# --- Base Layout Options ---
|
9
10
|
@dataclass
|
10
11
|
class BaseLayoutOptions:
|
11
12
|
"""Base options for layout detection engines."""
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
|
14
|
+
confidence: float = 0.5 # Minimum confidence threshold for detections
|
15
|
+
classes: Optional[List[str]] = None # Specific classes to detect (None for all)
|
16
|
+
exclude_classes: Optional[List[str]] = None # Classes to exclude
|
17
|
+
device: Optional[str] = "cpu" # Preferred device ('cpu', 'cuda', 'mps', etc.)
|
18
|
+
extra_args: Dict[str, Any] = field(
|
19
|
+
default_factory=dict
|
20
|
+
) # For engine-specific args not yet fields
|
21
|
+
|
17
22
|
|
18
23
|
# --- YOLO Specific Options ---
|
19
24
|
@dataclass
|
20
25
|
class YOLOLayoutOptions(BaseLayoutOptions):
|
21
26
|
"""Options specific to YOLO-based layout detection."""
|
27
|
+
|
22
28
|
model_repo: str = "juliozhao/DocLayout-YOLO-DocStructBench"
|
23
29
|
model_file: str = "doclayout_yolo_docstructbench_imgsz1024.pt"
|
24
|
-
image_size: int = 1024
|
30
|
+
image_size: int = 1024 # Input image size for the model
|
31
|
+
|
25
32
|
|
26
33
|
# --- TATR Specific Options ---
|
27
34
|
@dataclass
|
28
35
|
class TATRLayoutOptions(BaseLayoutOptions):
|
29
36
|
"""Options specific to Table Transformer (TATR) layout detection."""
|
37
|
+
|
30
38
|
# Which models to use (can be local paths or HF identifiers)
|
31
39
|
detection_model: str = "microsoft/table-transformer-detection"
|
32
40
|
structure_model: str = "microsoft/table-transformer-structure-recognition-v1.1-all"
|
@@ -36,35 +44,42 @@ class TATRLayoutOptions(BaseLayoutOptions):
|
|
36
44
|
# Whether to create cell regions (can be slow)
|
37
45
|
create_cells: bool = True
|
38
46
|
|
47
|
+
|
39
48
|
# --- Paddle Specific Options ---
|
40
49
|
@dataclass
|
41
50
|
class PaddleLayoutOptions(BaseLayoutOptions):
|
42
51
|
"""Options specific to PaddlePaddle PP-Structure layout detection."""
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
|
53
|
+
lang: str = "en" # Language ('en', 'ch', etc.)
|
54
|
+
use_angle_cls: bool = False # Use text angle classification?
|
55
|
+
enable_table: bool = True # Enable table structure detection?
|
56
|
+
show_log: bool = False # Show Paddle internal logs?
|
57
|
+
detect_text: bool = True # Also detect raw text boxes using PaddleOCR?
|
58
|
+
verbose: bool = False # Verbose logging for the detector class
|
59
|
+
|
49
60
|
|
50
61
|
# --- Surya Specific Options ---
|
51
62
|
@dataclass
|
52
63
|
class SuryaLayoutOptions(BaseLayoutOptions):
|
53
64
|
"""Options specific to Surya layout detection."""
|
54
|
-
|
55
|
-
|
65
|
+
|
66
|
+
model_name: str = "default" # Placeholder if different models become available
|
67
|
+
recognize_table_structure: bool = True # Automatically run table structure recognition?
|
68
|
+
|
56
69
|
|
57
70
|
# --- Docling Specific Options ---
|
58
71
|
@dataclass
|
59
72
|
class DoclingLayoutOptions(BaseLayoutOptions):
|
60
73
|
"""Options specific to Docling layout detection."""
|
74
|
+
|
61
75
|
# Pass kwargs directly to Docling's DocumentConverter via extra_args
|
62
76
|
# Common examples shown here for documentation, add others as needed to extra_args
|
63
77
|
# model_name: str = "ds4sd/SmolDocling-256M-preview" # Example model (pass via extra_args)
|
64
78
|
# prompt_text: Optional[str] = None # Optional prompt (pass via extra_args)
|
65
|
-
verbose: bool = False
|
79
|
+
verbose: bool = False # Verbose logging for the detector class
|
66
80
|
# Other kwargs like 'device', 'batch_size' can go in extra_args
|
67
81
|
|
82
|
+
|
68
83
|
# --- Union Type ---
|
69
84
|
LayoutOptions = Union[
|
70
85
|
YOLOLayoutOptions,
|
@@ -72,5 +87,5 @@ LayoutOptions = Union[
|
|
72
87
|
PaddleLayoutOptions,
|
73
88
|
SuryaLayoutOptions,
|
74
89
|
DoclingLayoutOptions,
|
75
|
-
BaseLayoutOptions
|
90
|
+
BaseLayoutOptions, # Include base for typing flexibility
|
76
91
|
]
|