docling 2.9.0__tar.gz → 2.10.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.
- {docling-2.9.0 → docling-2.10.0}/PKG-INFO +4 -4
- {docling-2.9.0 → docling-2.10.0}/docling/backend/docling_parse_backend.py +1 -1
- {docling-2.9.0 → docling-2.10.0}/docling/backend/docling_parse_v2_backend.py +7 -5
- {docling-2.9.0 → docling-2.10.0}/docling/cli/main.py +7 -5
- docling-2.10.0/docling/datamodel/document.py +309 -0
- {docling-2.9.0 → docling-2.10.0}/docling/datamodel/pipeline_options.py +5 -1
- {docling-2.9.0 → docling-2.10.0}/docling/document_converter.py +5 -5
- {docling-2.9.0 → docling-2.10.0}/docling/models/ds_glm_model.py +2 -2
- {docling-2.9.0 → docling-2.10.0}/docling/pipeline/standard_pdf_pipeline.py +2 -0
- docling-2.10.0/docling/utils/glm_utils.py +336 -0
- {docling-2.9.0 → docling-2.10.0}/pyproject.toml +4 -4
- docling-2.9.0/docling/datamodel/document.py +0 -560
- {docling-2.9.0 → docling-2.10.0}/LICENSE +0 -0
- {docling-2.9.0 → docling-2.10.0}/README.md +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/abstract_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/asciidoc_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/html_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/md_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/msexcel_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/mspowerpoint_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/msword_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/pdf_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/backend/pypdfium2_backend.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/chunking/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/cli/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/datamodel/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/datamodel/base_models.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/datamodel/settings.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/exceptions.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/base_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/base_ocr_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/easyocr_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/layout_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/ocr_mac_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/page_assemble_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/page_preprocessing_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/rapid_ocr_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/table_structure_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/tesseract_ocr_cli_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/models/tesseract_ocr_model.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/pipeline/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/pipeline/base_pipeline.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/pipeline/simple_pipeline.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/py.typed +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/utils/__init__.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/utils/export.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/utils/layout_utils.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/utils/profiling.py +0 -0
- {docling-2.9.0 → docling-2.10.0}/docling/utils/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: docling
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.10.0
|
4
4
|
Summary: SDK and CLI for parsing PDF, DOCX, HTML, and more, to a unified document representation for powering downstream workflows such as gen AI applications.
|
5
5
|
Home-page: https://github.com/DS4SD/docling
|
6
6
|
License: MIT
|
@@ -25,10 +25,10 @@ Provides-Extra: rapidocr
|
|
25
25
|
Provides-Extra: tesserocr
|
26
26
|
Requires-Dist: beautifulsoup4 (>=4.12.3,<5.0.0)
|
27
27
|
Requires-Dist: certifi (>=2024.7.4)
|
28
|
-
Requires-Dist: deepsearch-glm (>=0.
|
29
|
-
Requires-Dist: docling-core[chunking] (>=2.
|
28
|
+
Requires-Dist: deepsearch-glm (>=1.0.0,<2.0.0)
|
29
|
+
Requires-Dist: docling-core[chunking] (>=2.9.0,<3.0.0)
|
30
30
|
Requires-Dist: docling-ibm-models (>=2.0.6,<3.0.0)
|
31
|
-
Requires-Dist: docling-parse (>=
|
31
|
+
Requires-Dist: docling-parse (>=3.0.0,<4.0.0)
|
32
32
|
Requires-Dist: easyocr (>=1.7,<2.0)
|
33
33
|
Requires-Dist: filetype (>=1.2.0,<2.0.0)
|
34
34
|
Requires-Dist: huggingface_hub (>=0.23,<1)
|
@@ -6,7 +6,7 @@ from typing import Iterable, List, Optional, Union
|
|
6
6
|
|
7
7
|
import pypdfium2 as pdfium
|
8
8
|
from docling_core.types.doc import BoundingBox, CoordOrigin, Size
|
9
|
-
from docling_parse.
|
9
|
+
from docling_parse.pdf_parsers import pdf_parser_v1
|
10
10
|
from PIL import Image, ImageDraw
|
11
11
|
from pypdfium2 import PdfPage
|
12
12
|
|
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Iterable, List, Optional, Union
|
|
6
6
|
|
7
7
|
import pypdfium2 as pdfium
|
8
8
|
from docling_core.types.doc import BoundingBox, CoordOrigin
|
9
|
-
from docling_parse.
|
9
|
+
from docling_parse.pdf_parsers import pdf_parser_v2
|
10
10
|
from PIL import Image, ImageDraw
|
11
11
|
from pypdfium2 import PdfPage
|
12
12
|
|
@@ -210,12 +210,14 @@ class DoclingParseV2DocumentBackend(PdfDocumentBackend):
|
|
210
210
|
self.parser = pdf_parser_v2("fatal")
|
211
211
|
|
212
212
|
success = False
|
213
|
-
if isinstance(path_or_stream, BytesIO):
|
213
|
+
if isinstance(self.path_or_stream, BytesIO):
|
214
214
|
success = self.parser.load_document_from_bytesio(
|
215
|
-
self.document_hash, path_or_stream
|
215
|
+
self.document_hash, self.path_or_stream
|
216
|
+
)
|
217
|
+
elif isinstance(self.path_or_stream, Path):
|
218
|
+
success = self.parser.load_document(
|
219
|
+
self.document_hash, str(self.path_or_stream)
|
216
220
|
)
|
217
|
-
elif isinstance(path_or_stream, Path):
|
218
|
-
success = self.parser.load_document(self.document_hash, str(path_or_stream))
|
219
221
|
|
220
222
|
if not success:
|
221
223
|
raise RuntimeError(
|
@@ -208,7 +208,7 @@ def convert(
|
|
208
208
|
] = None,
|
209
209
|
pdf_backend: Annotated[
|
210
210
|
PdfBackend, typer.Option(..., help="The PDF backend to use.")
|
211
|
-
] = PdfBackend.
|
211
|
+
] = PdfBackend.DLPARSE_V2,
|
212
212
|
table_mode: Annotated[
|
213
213
|
TableFormerMode,
|
214
214
|
typer.Option(..., help="The mode to use in the table structure model."),
|
@@ -372,11 +372,13 @@ def convert(
|
|
372
372
|
else:
|
373
373
|
raise RuntimeError(f"Unexpected PDF backend type {pdf_backend}")
|
374
374
|
|
375
|
+
pdf_format_option = PdfFormatOption(
|
376
|
+
pipeline_options=pipeline_options,
|
377
|
+
backend=backend, # pdf_backend
|
378
|
+
)
|
375
379
|
format_options: Dict[InputFormat, FormatOption] = {
|
376
|
-
InputFormat.PDF:
|
377
|
-
|
378
|
-
backend=backend, # pdf_backend
|
379
|
-
)
|
380
|
+
InputFormat.PDF: pdf_format_option,
|
381
|
+
InputFormat.IMAGE: pdf_format_option,
|
380
382
|
}
|
381
383
|
doc_converter = DocumentConverter(
|
382
384
|
allowed_formats=from_formats,
|
@@ -0,0 +1,309 @@
|
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
from enum import Enum
|
4
|
+
from io import BytesIO
|
5
|
+
from pathlib import Path, PurePath
|
6
|
+
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Type, Union
|
7
|
+
|
8
|
+
import filetype
|
9
|
+
from docling_core.types.doc import (
|
10
|
+
DocItem,
|
11
|
+
DocItemLabel,
|
12
|
+
DoclingDocument,
|
13
|
+
PictureItem,
|
14
|
+
SectionHeaderItem,
|
15
|
+
TableItem,
|
16
|
+
TextItem,
|
17
|
+
)
|
18
|
+
from docling_core.types.doc.document import ListItem
|
19
|
+
from docling_core.types.legacy_doc.base import (
|
20
|
+
BaseText,
|
21
|
+
Figure,
|
22
|
+
GlmTableCell,
|
23
|
+
PageDimensions,
|
24
|
+
PageReference,
|
25
|
+
Prov,
|
26
|
+
Ref,
|
27
|
+
)
|
28
|
+
from docling_core.types.legacy_doc.base import Table as DsSchemaTable
|
29
|
+
from docling_core.types.legacy_doc.base import TableCell
|
30
|
+
from docling_core.types.legacy_doc.document import (
|
31
|
+
CCSDocumentDescription as DsDocumentDescription,
|
32
|
+
)
|
33
|
+
from docling_core.types.legacy_doc.document import CCSFileInfoObject as DsFileInfoObject
|
34
|
+
from docling_core.types.legacy_doc.document import ExportedCCSDocument as DsDocument
|
35
|
+
from docling_core.utils.file import resolve_source_to_stream
|
36
|
+
from docling_core.utils.legacy import docling_document_to_legacy
|
37
|
+
from pydantic import BaseModel
|
38
|
+
from typing_extensions import deprecated
|
39
|
+
|
40
|
+
from docling.backend.abstract_backend import (
|
41
|
+
AbstractDocumentBackend,
|
42
|
+
PaginatedDocumentBackend,
|
43
|
+
)
|
44
|
+
from docling.datamodel.base_models import (
|
45
|
+
AssembledUnit,
|
46
|
+
ConversionStatus,
|
47
|
+
DocumentStream,
|
48
|
+
ErrorItem,
|
49
|
+
FormatToExtensions,
|
50
|
+
FormatToMimeType,
|
51
|
+
InputFormat,
|
52
|
+
MimeTypeToFormat,
|
53
|
+
Page,
|
54
|
+
)
|
55
|
+
from docling.datamodel.settings import DocumentLimits
|
56
|
+
from docling.utils.profiling import ProfilingItem
|
57
|
+
from docling.utils.utils import create_file_hash, create_hash
|
58
|
+
|
59
|
+
if TYPE_CHECKING:
|
60
|
+
from docling.document_converter import FormatOption
|
61
|
+
|
62
|
+
_log = logging.getLogger(__name__)
|
63
|
+
|
64
|
+
layout_label_to_ds_type = {
|
65
|
+
DocItemLabel.TITLE: "title",
|
66
|
+
DocItemLabel.DOCUMENT_INDEX: "table-of-contents",
|
67
|
+
DocItemLabel.SECTION_HEADER: "subtitle-level-1",
|
68
|
+
DocItemLabel.CHECKBOX_SELECTED: "checkbox-selected",
|
69
|
+
DocItemLabel.CHECKBOX_UNSELECTED: "checkbox-unselected",
|
70
|
+
DocItemLabel.CAPTION: "caption",
|
71
|
+
DocItemLabel.PAGE_HEADER: "page-header",
|
72
|
+
DocItemLabel.PAGE_FOOTER: "page-footer",
|
73
|
+
DocItemLabel.FOOTNOTE: "footnote",
|
74
|
+
DocItemLabel.TABLE: "table",
|
75
|
+
DocItemLabel.FORMULA: "equation",
|
76
|
+
DocItemLabel.LIST_ITEM: "paragraph",
|
77
|
+
DocItemLabel.CODE: "paragraph",
|
78
|
+
DocItemLabel.PICTURE: "figure",
|
79
|
+
DocItemLabel.TEXT: "paragraph",
|
80
|
+
DocItemLabel.PARAGRAPH: "paragraph",
|
81
|
+
}
|
82
|
+
|
83
|
+
_EMPTY_DOCLING_DOC = DoclingDocument(name="dummy")
|
84
|
+
|
85
|
+
|
86
|
+
class InputDocument(BaseModel):
|
87
|
+
file: PurePath
|
88
|
+
document_hash: str # = None
|
89
|
+
valid: bool = True
|
90
|
+
limits: DocumentLimits = DocumentLimits()
|
91
|
+
format: InputFormat # = None
|
92
|
+
|
93
|
+
filesize: Optional[int] = None
|
94
|
+
page_count: int = 0
|
95
|
+
|
96
|
+
_backend: AbstractDocumentBackend # Internal PDF backend used
|
97
|
+
|
98
|
+
def __init__(
|
99
|
+
self,
|
100
|
+
path_or_stream: Union[BytesIO, Path],
|
101
|
+
format: InputFormat,
|
102
|
+
backend: Type[AbstractDocumentBackend],
|
103
|
+
filename: Optional[str] = None,
|
104
|
+
limits: Optional[DocumentLimits] = None,
|
105
|
+
):
|
106
|
+
super().__init__(
|
107
|
+
file="", document_hash="", format=InputFormat.PDF
|
108
|
+
) # initialize with dummy values
|
109
|
+
|
110
|
+
self.limits = limits or DocumentLimits()
|
111
|
+
self.format = format
|
112
|
+
|
113
|
+
try:
|
114
|
+
if isinstance(path_or_stream, Path):
|
115
|
+
self.file = path_or_stream
|
116
|
+
self.filesize = path_or_stream.stat().st_size
|
117
|
+
if self.filesize > self.limits.max_file_size:
|
118
|
+
self.valid = False
|
119
|
+
else:
|
120
|
+
self.document_hash = create_file_hash(path_or_stream)
|
121
|
+
self._init_doc(backend, path_or_stream)
|
122
|
+
|
123
|
+
elif isinstance(path_or_stream, BytesIO):
|
124
|
+
assert (
|
125
|
+
filename is not None
|
126
|
+
), "Can't construct InputDocument from stream without providing filename arg."
|
127
|
+
self.file = PurePath(filename)
|
128
|
+
self.filesize = path_or_stream.getbuffer().nbytes
|
129
|
+
|
130
|
+
if self.filesize > self.limits.max_file_size:
|
131
|
+
self.valid = False
|
132
|
+
else:
|
133
|
+
self.document_hash = create_file_hash(path_or_stream)
|
134
|
+
self._init_doc(backend, path_or_stream)
|
135
|
+
else:
|
136
|
+
raise RuntimeError(
|
137
|
+
f"Unexpected type path_or_stream: {type(path_or_stream)}"
|
138
|
+
)
|
139
|
+
|
140
|
+
# For paginated backends, check if the maximum page count is exceeded.
|
141
|
+
if self.valid and self._backend.is_valid():
|
142
|
+
if self._backend.supports_pagination() and isinstance(
|
143
|
+
self._backend, PaginatedDocumentBackend
|
144
|
+
):
|
145
|
+
self.page_count = self._backend.page_count()
|
146
|
+
if not self.page_count <= self.limits.max_num_pages:
|
147
|
+
self.valid = False
|
148
|
+
|
149
|
+
except (FileNotFoundError, OSError) as e:
|
150
|
+
self.valid = False
|
151
|
+
_log.exception(
|
152
|
+
f"File {self.file.name} not found or cannot be opened.", exc_info=e
|
153
|
+
)
|
154
|
+
# raise
|
155
|
+
except RuntimeError as e:
|
156
|
+
self.valid = False
|
157
|
+
_log.exception(
|
158
|
+
f"An unexpected error occurred while opening the document {self.file.name}",
|
159
|
+
exc_info=e,
|
160
|
+
)
|
161
|
+
# raise
|
162
|
+
|
163
|
+
def _init_doc(
|
164
|
+
self,
|
165
|
+
backend: Type[AbstractDocumentBackend],
|
166
|
+
path_or_stream: Union[BytesIO, Path],
|
167
|
+
) -> None:
|
168
|
+
self._backend = backend(self, path_or_stream=path_or_stream)
|
169
|
+
if not self._backend.is_valid():
|
170
|
+
self.valid = False
|
171
|
+
|
172
|
+
|
173
|
+
class DocumentFormat(str, Enum):
|
174
|
+
V2 = "v2"
|
175
|
+
V1 = "v1"
|
176
|
+
|
177
|
+
|
178
|
+
class ConversionResult(BaseModel):
|
179
|
+
input: InputDocument
|
180
|
+
|
181
|
+
status: ConversionStatus = ConversionStatus.PENDING # failure, success
|
182
|
+
errors: List[ErrorItem] = [] # structure to keep errors
|
183
|
+
|
184
|
+
pages: List[Page] = []
|
185
|
+
assembled: AssembledUnit = AssembledUnit()
|
186
|
+
timings: Dict[str, ProfilingItem] = {}
|
187
|
+
|
188
|
+
document: DoclingDocument = _EMPTY_DOCLING_DOC
|
189
|
+
|
190
|
+
@property
|
191
|
+
@deprecated("Use document instead.")
|
192
|
+
def legacy_document(self):
|
193
|
+
return docling_document_to_legacy(self.document)
|
194
|
+
|
195
|
+
|
196
|
+
class _DummyBackend(AbstractDocumentBackend):
|
197
|
+
def __init__(self, *args, **kwargs):
|
198
|
+
super().__init__(*args, **kwargs)
|
199
|
+
|
200
|
+
def is_valid(self) -> bool:
|
201
|
+
return False
|
202
|
+
|
203
|
+
@classmethod
|
204
|
+
def supported_formats(cls) -> Set[InputFormat]:
|
205
|
+
return set()
|
206
|
+
|
207
|
+
@classmethod
|
208
|
+
def supports_pagination(cls) -> bool:
|
209
|
+
return False
|
210
|
+
|
211
|
+
def unload(self):
|
212
|
+
return super().unload()
|
213
|
+
|
214
|
+
|
215
|
+
class _DocumentConversionInput(BaseModel):
|
216
|
+
|
217
|
+
path_or_stream_iterator: Iterable[Union[Path, str, DocumentStream]]
|
218
|
+
limits: Optional[DocumentLimits] = DocumentLimits()
|
219
|
+
|
220
|
+
def docs(
|
221
|
+
self, format_options: Dict[InputFormat, "FormatOption"]
|
222
|
+
) -> Iterable[InputDocument]:
|
223
|
+
for item in self.path_or_stream_iterator:
|
224
|
+
obj = resolve_source_to_stream(item) if isinstance(item, str) else item
|
225
|
+
format = self._guess_format(obj)
|
226
|
+
backend: Type[AbstractDocumentBackend]
|
227
|
+
if format not in format_options.keys():
|
228
|
+
_log.error(
|
229
|
+
f"Input document {obj.name} does not match any allowed format."
|
230
|
+
)
|
231
|
+
backend = _DummyBackend
|
232
|
+
else:
|
233
|
+
backend = format_options[format].backend
|
234
|
+
|
235
|
+
if isinstance(obj, Path):
|
236
|
+
yield InputDocument(
|
237
|
+
path_or_stream=obj,
|
238
|
+
format=format,
|
239
|
+
filename=obj.name,
|
240
|
+
limits=self.limits,
|
241
|
+
backend=backend,
|
242
|
+
)
|
243
|
+
elif isinstance(obj, DocumentStream):
|
244
|
+
yield InputDocument(
|
245
|
+
path_or_stream=obj.stream,
|
246
|
+
format=format,
|
247
|
+
filename=obj.name,
|
248
|
+
limits=self.limits,
|
249
|
+
backend=backend,
|
250
|
+
)
|
251
|
+
else:
|
252
|
+
raise RuntimeError(f"Unexpected obj type in iterator: {type(obj)}")
|
253
|
+
|
254
|
+
def _guess_format(self, obj: Union[Path, DocumentStream]):
|
255
|
+
content = b"" # empty binary blob
|
256
|
+
format = None
|
257
|
+
|
258
|
+
if isinstance(obj, Path):
|
259
|
+
mime = filetype.guess_mime(str(obj))
|
260
|
+
if mime is None:
|
261
|
+
ext = obj.suffix[1:]
|
262
|
+
mime = self._mime_from_extension(ext)
|
263
|
+
if mime is None: # must guess from
|
264
|
+
with obj.open("rb") as f:
|
265
|
+
content = f.read(1024) # Read first 1KB
|
266
|
+
|
267
|
+
elif isinstance(obj, DocumentStream):
|
268
|
+
content = obj.stream.read(8192)
|
269
|
+
obj.stream.seek(0)
|
270
|
+
mime = filetype.guess_mime(content)
|
271
|
+
if mime is None:
|
272
|
+
ext = (
|
273
|
+
obj.name.rsplit(".", 1)[-1]
|
274
|
+
if ("." in obj.name and not obj.name.startswith("."))
|
275
|
+
else ""
|
276
|
+
)
|
277
|
+
mime = self._mime_from_extension(ext)
|
278
|
+
|
279
|
+
mime = mime or self._detect_html_xhtml(content)
|
280
|
+
mime = mime or "text/plain"
|
281
|
+
|
282
|
+
format = MimeTypeToFormat.get(mime)
|
283
|
+
return format
|
284
|
+
|
285
|
+
def _mime_from_extension(self, ext):
|
286
|
+
mime = None
|
287
|
+
if ext in FormatToExtensions[InputFormat.ASCIIDOC]:
|
288
|
+
mime = FormatToMimeType[InputFormat.ASCIIDOC][0]
|
289
|
+
elif ext in FormatToExtensions[InputFormat.HTML]:
|
290
|
+
mime = FormatToMimeType[InputFormat.HTML][0]
|
291
|
+
elif ext in FormatToExtensions[InputFormat.MD]:
|
292
|
+
mime = FormatToMimeType[InputFormat.MD][0]
|
293
|
+
|
294
|
+
return mime
|
295
|
+
|
296
|
+
def _detect_html_xhtml(self, content):
|
297
|
+
content_str = content.decode("ascii", errors="ignore").lower()
|
298
|
+
# Remove XML comments
|
299
|
+
content_str = re.sub(r"<!--(.*?)-->", "", content_str, flags=re.DOTALL)
|
300
|
+
content_str = content_str.lstrip()
|
301
|
+
|
302
|
+
if re.match(r"<\?xml", content_str):
|
303
|
+
if "xhtml" in content_str[:1000]:
|
304
|
+
return "application/xhtml+xml"
|
305
|
+
|
306
|
+
if re.match(r"<!doctype\s+html|<html|<head|<body", content_str):
|
307
|
+
return "text/html"
|
308
|
+
|
309
|
+
return None
|
@@ -143,7 +143,11 @@ class PdfPipelineOptions(PipelineOptions):
|
|
143
143
|
|
144
144
|
table_structure_options: TableStructureOptions = TableStructureOptions()
|
145
145
|
ocr_options: Union[
|
146
|
-
EasyOcrOptions,
|
146
|
+
EasyOcrOptions,
|
147
|
+
TesseractCliOcrOptions,
|
148
|
+
TesseractOcrOptions,
|
149
|
+
OcrMacOptions,
|
150
|
+
RapidOcrOptions,
|
147
151
|
] = Field(EasyOcrOptions(), discriminator="kind")
|
148
152
|
|
149
153
|
images_scale: float = 1.0
|
@@ -9,7 +9,7 @@ from pydantic import BaseModel, ConfigDict, model_validator, validate_call
|
|
9
9
|
|
10
10
|
from docling.backend.abstract_backend import AbstractDocumentBackend
|
11
11
|
from docling.backend.asciidoc_backend import AsciiDocBackend
|
12
|
-
from docling.backend.
|
12
|
+
from docling.backend.docling_parse_v2_backend import DoclingParseV2DocumentBackend
|
13
13
|
from docling.backend.html_backend import HTMLDocumentBackend
|
14
14
|
from docling.backend.md_backend import MarkdownDocumentBackend
|
15
15
|
from docling.backend.msexcel_backend import MsExcelDocumentBackend
|
@@ -84,12 +84,12 @@ class HTMLFormatOption(FormatOption):
|
|
84
84
|
|
85
85
|
class PdfFormatOption(FormatOption):
|
86
86
|
pipeline_cls: Type = StandardPdfPipeline
|
87
|
-
backend: Type[AbstractDocumentBackend] =
|
87
|
+
backend: Type[AbstractDocumentBackend] = DoclingParseV2DocumentBackend
|
88
88
|
|
89
89
|
|
90
90
|
class ImageFormatOption(FormatOption):
|
91
91
|
pipeline_cls: Type = StandardPdfPipeline
|
92
|
-
backend: Type[AbstractDocumentBackend] =
|
92
|
+
backend: Type[AbstractDocumentBackend] = DoclingParseV2DocumentBackend
|
93
93
|
|
94
94
|
|
95
95
|
def _get_default_option(format: InputFormat) -> FormatOption:
|
@@ -113,10 +113,10 @@ def _get_default_option(format: InputFormat) -> FormatOption:
|
|
113
113
|
pipeline_cls=SimplePipeline, backend=HTMLDocumentBackend
|
114
114
|
),
|
115
115
|
InputFormat.IMAGE: FormatOption(
|
116
|
-
pipeline_cls=StandardPdfPipeline, backend=
|
116
|
+
pipeline_cls=StandardPdfPipeline, backend=DoclingParseV2DocumentBackend
|
117
117
|
),
|
118
118
|
InputFormat.PDF: FormatOption(
|
119
|
-
pipeline_cls=StandardPdfPipeline, backend=
|
119
|
+
pipeline_cls=StandardPdfPipeline, backend=DoclingParseV2DocumentBackend
|
120
120
|
),
|
121
121
|
}
|
122
122
|
if (options := format_to_default_options.get(format)) is not None:
|
@@ -4,7 +4,6 @@ from pathlib import Path
|
|
4
4
|
from typing import List, Union
|
5
5
|
|
6
6
|
from deepsearch_glm.nlp_utils import init_nlp_model
|
7
|
-
from deepsearch_glm.utils.doc_utils import to_docling_document
|
8
7
|
from deepsearch_glm.utils.load_pretrained_models import load_pretrained_nlp_models
|
9
8
|
from docling_core.types.doc import BoundingBox, CoordOrigin, DoclingDocument
|
10
9
|
from docling_core.types.legacy_doc.base import BoundingBox as DsBoundingBox
|
@@ -29,6 +28,7 @@ from pydantic import BaseModel, ConfigDict
|
|
29
28
|
from docling.datamodel.base_models import Cluster, FigureElement, Table, TextElement
|
30
29
|
from docling.datamodel.document import ConversionResult, layout_label_to_ds_type
|
31
30
|
from docling.datamodel.settings import settings
|
31
|
+
from docling.utils.glm_utils import to_docling_document
|
32
32
|
from docling.utils.profiling import ProfilingScope, TimeRecorder
|
33
33
|
from docling.utils.utils import create_hash
|
34
34
|
|
@@ -232,7 +232,7 @@ class GlmModel:
|
|
232
232
|
def __call__(self, conv_res: ConversionResult) -> DoclingDocument:
|
233
233
|
with TimeRecorder(conv_res, "glm", scope=ProfilingScope.DOCUMENT):
|
234
234
|
ds_doc = self._to_legacy_document(conv_res)
|
235
|
-
ds_doc_dict = ds_doc.model_dump(by_alias=True)
|
235
|
+
ds_doc_dict = ds_doc.model_dump(by_alias=True, exclude_none=True)
|
236
236
|
|
237
237
|
glm_doc = self.model.apply_on_doc(ds_doc_dict)
|
238
238
|
|
@@ -97,7 +97,9 @@ class StandardPdfPipeline(PaginatedPipeline):
|
|
97
97
|
local_dir: Optional[Path] = None, force: bool = False
|
98
98
|
) -> Path:
|
99
99
|
from huggingface_hub import snapshot_download
|
100
|
+
from huggingface_hub.utils import disable_progress_bars
|
100
101
|
|
102
|
+
disable_progress_bars()
|
101
103
|
download_path = snapshot_download(
|
102
104
|
repo_id="ds4sd/docling-models",
|
103
105
|
force_download=force,
|