mirror of
https://github.com/DS4SD/docling.git
synced 2025-12-08 12:48:28 +00:00
feat: AutoOCR model selecting the best OCR model available and deprecating the usage of EasyOCR (#2391)
* add auto ocr model Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> * Apply suggestions from code review Co-authored-by: Christoph Auer <60343111+cau-git@users.noreply.github.com> Signed-off-by: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> * add final log warning Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> * propagate default options Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> * allow rapidocr models download Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> * remove modelscope Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> --------- Signed-off-by: Michele Dolfi <dol@zurich.ibm.com> Signed-off-by: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> Co-authored-by: Christoph Auer <60343111+cau-git@users.noreply.github.com>
This commit is contained in:
@@ -49,7 +49,7 @@ from docling.datamodel.document import ConversionResult
|
||||
from docling.datamodel.pipeline_options import (
|
||||
AsrPipelineOptions,
|
||||
ConvertPipelineOptions,
|
||||
EasyOcrOptions,
|
||||
OcrAutoOptions,
|
||||
OcrOptions,
|
||||
PaginatedPipelineOptions,
|
||||
PdfBackend,
|
||||
@@ -374,7 +374,7 @@ def convert( # noqa: C901
|
||||
f"Use the option --show-external-plugins to see the options allowed with external plugins."
|
||||
),
|
||||
),
|
||||
] = EasyOcrOptions.kind,
|
||||
] = OcrAutoOptions.kind,
|
||||
ocr_lang: Annotated[
|
||||
Optional[str],
|
||||
typer.Option(
|
||||
|
||||
@@ -38,6 +38,7 @@ class _AvailableModels(str, Enum):
|
||||
SMOLDOCLING = "smoldocling"
|
||||
SMOLDOCLING_MLX = "smoldocling_mlx"
|
||||
GRANITE_VISION = "granite_vision"
|
||||
RAPIDOCR = "rapidocr"
|
||||
EASYOCR = "easyocr"
|
||||
|
||||
|
||||
@@ -46,7 +47,7 @@ _default_models = [
|
||||
_AvailableModels.TABLEFORMER,
|
||||
_AvailableModels.CODE_FORMULA,
|
||||
_AvailableModels.PICTURE_CLASSIFIER,
|
||||
_AvailableModels.EASYOCR,
|
||||
_AvailableModels.RAPIDOCR,
|
||||
]
|
||||
|
||||
|
||||
@@ -115,6 +116,7 @@ def download(
|
||||
with_smoldocling=_AvailableModels.SMOLDOCLING in to_download,
|
||||
with_smoldocling_mlx=_AvailableModels.SMOLDOCLING_MLX in to_download,
|
||||
with_granite_vision=_AvailableModels.GRANITE_VISION in to_download,
|
||||
with_rapidocr=_AvailableModels.RAPIDOCR in to_download,
|
||||
with_easyocr=_AvailableModels.EASYOCR in to_download,
|
||||
)
|
||||
|
||||
|
||||
@@ -81,6 +81,13 @@ class OcrOptions(BaseOptions):
|
||||
)
|
||||
|
||||
|
||||
class OcrAutoOptions(OcrOptions):
|
||||
"""Options for pick OCR engine automatically."""
|
||||
|
||||
kind: ClassVar[Literal["auto"]] = "auto"
|
||||
lang: List[str] = []
|
||||
|
||||
|
||||
class RapidOcrOptions(OcrOptions):
|
||||
"""Options for the RapidOCR engine."""
|
||||
|
||||
@@ -255,6 +262,7 @@ class PdfBackend(str, Enum):
|
||||
class OcrEngine(str, Enum):
|
||||
"""Enum of valid OCR engines."""
|
||||
|
||||
AUTO = "auto"
|
||||
EASYOCR = "easyocr"
|
||||
TESSERACT_CLI = "tesseract_cli"
|
||||
TESSERACT = "tesseract"
|
||||
@@ -336,7 +344,7 @@ class PdfPipelineOptions(PaginatedPipelineOptions):
|
||||
# If True, text from backend will be used instead of generated text
|
||||
|
||||
table_structure_options: TableStructureOptions = TableStructureOptions()
|
||||
ocr_options: OcrOptions = EasyOcrOptions()
|
||||
ocr_options: OcrOptions = OcrAutoOptions()
|
||||
layout_options: LayoutOptions = LayoutOptions()
|
||||
|
||||
images_scale: float = 1.0
|
||||
|
||||
132
docling/models/auto_ocr_model.py
Normal file
132
docling/models/auto_ocr_model.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import logging
|
||||
import sys
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Optional, Type
|
||||
|
||||
from docling.datamodel.accelerator_options import AcceleratorOptions
|
||||
from docling.datamodel.base_models import Page
|
||||
from docling.datamodel.document import ConversionResult
|
||||
from docling.datamodel.pipeline_options import (
|
||||
EasyOcrOptions,
|
||||
OcrAutoOptions,
|
||||
OcrMacOptions,
|
||||
OcrOptions,
|
||||
RapidOcrOptions,
|
||||
)
|
||||
from docling.models.base_ocr_model import BaseOcrModel
|
||||
from docling.models.easyocr_model import EasyOcrModel
|
||||
from docling.models.ocr_mac_model import OcrMacModel
|
||||
from docling.models.rapid_ocr_model import RapidOcrModel
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OcrAutoModel(BaseOcrModel):
|
||||
def __init__(
|
||||
self,
|
||||
enabled: bool,
|
||||
artifacts_path: Optional[Path],
|
||||
options: OcrAutoOptions,
|
||||
accelerator_options: AcceleratorOptions,
|
||||
):
|
||||
super().__init__(
|
||||
enabled=enabled,
|
||||
artifacts_path=artifacts_path,
|
||||
options=options,
|
||||
accelerator_options=accelerator_options,
|
||||
)
|
||||
self.options: OcrAutoOptions
|
||||
|
||||
self._engine: Optional[BaseOcrModel] = None
|
||||
if self.enabled:
|
||||
if "darwin" == sys.platform:
|
||||
try:
|
||||
from ocrmac import ocrmac
|
||||
|
||||
self._engine = OcrMacModel(
|
||||
enabled=self.enabled,
|
||||
artifacts_path=artifacts_path,
|
||||
options=OcrMacOptions(
|
||||
bitmap_area_threshold=self.options.bitmap_area_threshold,
|
||||
force_full_page_ocr=self.options.force_full_page_ocr,
|
||||
),
|
||||
accelerator_options=accelerator_options,
|
||||
)
|
||||
_log.info("Auto OCR model selected ocrmac.")
|
||||
except ImportError:
|
||||
_log.info("ocrmac cannot be used because ocrmac is not installed.")
|
||||
|
||||
if self._engine is None:
|
||||
try:
|
||||
import onnxruntime
|
||||
from rapidocr import EngineType, RapidOCR # type: ignore
|
||||
|
||||
self._engine = RapidOcrModel(
|
||||
enabled=self.enabled,
|
||||
artifacts_path=artifacts_path,
|
||||
options=RapidOcrOptions(
|
||||
backend="onnxruntime",
|
||||
bitmap_area_threshold=self.options.bitmap_area_threshold,
|
||||
force_full_page_ocr=self.options.force_full_page_ocr,
|
||||
),
|
||||
accelerator_options=accelerator_options,
|
||||
)
|
||||
_log.info("Auto OCR model selected rapidocr with onnxruntime.")
|
||||
except ImportError:
|
||||
_log.info(
|
||||
"rapidocr cannot be used because onnxruntime is not installed."
|
||||
)
|
||||
|
||||
if self._engine is None:
|
||||
try:
|
||||
import easyocr
|
||||
|
||||
self._engine = EasyOcrModel(
|
||||
enabled=self.enabled,
|
||||
artifacts_path=artifacts_path,
|
||||
options=EasyOcrOptions(
|
||||
bitmap_area_threshold=self.options.bitmap_area_threshold,
|
||||
force_full_page_ocr=self.options.force_full_page_ocr,
|
||||
),
|
||||
accelerator_options=accelerator_options,
|
||||
)
|
||||
_log.info("Auto OCR model selected easyocr.")
|
||||
except ImportError:
|
||||
_log.info("easyocr cannot be used because it is not installed.")
|
||||
|
||||
if self._engine is None:
|
||||
try:
|
||||
import torch
|
||||
from rapidocr import EngineType, RapidOCR # type: ignore
|
||||
|
||||
self._engine = RapidOcrModel(
|
||||
enabled=self.enabled,
|
||||
artifacts_path=artifacts_path,
|
||||
options=RapidOcrOptions(
|
||||
backend="torch",
|
||||
bitmap_area_threshold=self.options.bitmap_area_threshold,
|
||||
force_full_page_ocr=self.options.force_full_page_ocr,
|
||||
),
|
||||
accelerator_options=accelerator_options,
|
||||
)
|
||||
_log.info("Auto OCR model selected rapidocr with torch.")
|
||||
except ImportError:
|
||||
_log.info(
|
||||
"rapidocr cannot be used because rapidocr or torch is not installed."
|
||||
)
|
||||
|
||||
if self._engine is None:
|
||||
_log.warning("No OCR engine found. Please review the install details.")
|
||||
|
||||
def __call__(
|
||||
self, conv_res: ConversionResult, page_batch: Iterable[Page]
|
||||
) -> Iterable[Page]:
|
||||
if not self.enabled or self._engine is None:
|
||||
yield from page_batch
|
||||
return
|
||||
yield from self._engine(conv_res, page_batch)
|
||||
|
||||
@classmethod
|
||||
def get_options_type(cls) -> Type[OcrOptions]:
|
||||
return OcrAutoOptions
|
||||
@@ -1,4 +1,5 @@
|
||||
def ocr_engines():
|
||||
from docling.models.auto_ocr_model import OcrAutoModel
|
||||
from docling.models.easyocr_model import EasyOcrModel
|
||||
from docling.models.ocr_mac_model import OcrMacModel
|
||||
from docling.models.rapid_ocr_model import RapidOcrModel
|
||||
@@ -7,6 +8,7 @@ def ocr_engines():
|
||||
|
||||
return {
|
||||
"ocr_engines": [
|
||||
OcrAutoModel,
|
||||
EasyOcrModel,
|
||||
OcrMacModel,
|
||||
RapidOcrModel,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Optional, Type
|
||||
from typing import Literal, Optional, Type, TypedDict
|
||||
|
||||
import numpy
|
||||
from docling_core.types.doc import BoundingBox, CoordOrigin
|
||||
@@ -18,11 +18,67 @@ from docling.datamodel.settings import settings
|
||||
from docling.models.base_ocr_model import BaseOcrModel
|
||||
from docling.utils.accelerator_utils import decide_device
|
||||
from docling.utils.profiling import TimeRecorder
|
||||
from docling.utils.utils import download_url_with_progress
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
_ModelPathEngines = Literal["onnxruntime", "torch"]
|
||||
_ModelPathTypes = Literal[
|
||||
"det_model_path", "cls_model_path", "rec_model_path", "rec_keys_path"
|
||||
]
|
||||
|
||||
|
||||
class _ModelPathDetail(TypedDict):
|
||||
url: str
|
||||
path: str
|
||||
|
||||
|
||||
class RapidOcrModel(BaseOcrModel):
|
||||
_model_repo_folder = "RapidOcr"
|
||||
# from https://github.com/RapidAI/RapidOCR/blob/main/python/rapidocr/default_models.yaml
|
||||
# matching the default config in https://github.com/RapidAI/RapidOCR/blob/main/python/rapidocr/config.yaml
|
||||
# and naming f"{file_info.engine_type.value}.{file_info.ocr_version.value}.{file_info.task_type.value}"
|
||||
_default_models: dict[
|
||||
_ModelPathEngines, dict[_ModelPathTypes, _ModelPathDetail]
|
||||
] = {
|
||||
"onnxruntime": {
|
||||
"det_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/onnx/PP-OCRv4/det/ch_PP-OCRv4_det_infer.onnx",
|
||||
"path": "onnx/PP-OCRv4/det/ch_PP-OCRv4_det_infer.onnx",
|
||||
},
|
||||
"cls_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/onnx/PP-OCRv4/cls/ch_ppocr_mobile_v2.0_cls_infer.onnx",
|
||||
"path": "onnx/PP-OCRv4/cls/ch_ppocr_mobile_v2.0_cls_infer.onnx",
|
||||
},
|
||||
"rec_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/onnx/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer.onnx",
|
||||
"path": "onnx/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer.onnx",
|
||||
},
|
||||
"rec_keys_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v2.0.7/paddle/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer/ppocr_keys_v1.txt",
|
||||
"path": "paddle/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer/ppocr_keys_v1.txt",
|
||||
},
|
||||
},
|
||||
"torch": {
|
||||
"det_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/torch/PP-OCRv4/det/ch_PP-OCRv4_det_infer.pth",
|
||||
"path": "torch/PP-OCRv4/det/ch_PP-OCRv4_det_infer.pth",
|
||||
},
|
||||
"cls_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/torch/PP-OCRv4/cls/ch_ptocr_mobile_v2.0_cls_infer.pth",
|
||||
"path": "torch/PP-OCRv4/cls/ch_ptocr_mobile_v2.0_cls_infer.pth",
|
||||
},
|
||||
"rec_model_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/torch/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer.pth",
|
||||
"path": "torch/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer.pth",
|
||||
},
|
||||
"rec_keys_path": {
|
||||
"url": "https://www.modelscope.cn/models/RapidAI/RapidOCR/resolve/v3.4.0/paddle/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer/ppocr_keys_v1.txt",
|
||||
"path": "paddle/PP-OCRv4/rec/ch_PP-OCRv4_rec_infer/ppocr_keys_v1.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
enabled: bool,
|
||||
@@ -62,25 +118,66 @@ class RapidOcrModel(BaseOcrModel):
|
||||
}
|
||||
backend_enum = _ALIASES.get(self.options.backend, EngineType.ONNXRUNTIME)
|
||||
|
||||
det_model_path = self.options.det_model_path
|
||||
cls_model_path = self.options.cls_model_path
|
||||
rec_model_path = self.options.rec_model_path
|
||||
rec_keys_path = self.options.rec_keys_path
|
||||
if artifacts_path is not None:
|
||||
det_model_path = (
|
||||
det_model_path
|
||||
or artifacts_path
|
||||
/ self._model_repo_folder
|
||||
/ self._default_models[backend_enum.value]["det_model_path"]["path"]
|
||||
)
|
||||
cls_model_path = (
|
||||
cls_model_path
|
||||
or artifacts_path
|
||||
/ self._model_repo_folder
|
||||
/ self._default_models[backend_enum.value]["cls_model_path"]["path"]
|
||||
)
|
||||
rec_model_path = (
|
||||
rec_model_path
|
||||
or artifacts_path
|
||||
/ self._model_repo_folder
|
||||
/ self._default_models[backend_enum.value]["rec_model_path"]["path"]
|
||||
)
|
||||
rec_keys_path = (
|
||||
rec_keys_path
|
||||
or artifacts_path
|
||||
/ self._model_repo_folder
|
||||
/ self._default_models[backend_enum.value]["rec_keys_path"]["path"]
|
||||
)
|
||||
|
||||
for model_path in (
|
||||
rec_keys_path,
|
||||
cls_model_path,
|
||||
rec_model_path,
|
||||
rec_keys_path,
|
||||
):
|
||||
if model_path is None:
|
||||
continue
|
||||
if not Path(model_path).exists():
|
||||
_log.warning(f"The provided model path {model_path} is not found.")
|
||||
|
||||
params = {
|
||||
# Global settings (these are still correct)
|
||||
"Global.text_score": self.options.text_score,
|
||||
"Global.font_path": self.options.font_path,
|
||||
# "Global.verbose": self.options.print_verbose,
|
||||
# Detection model settings
|
||||
"Det.model_path": self.options.det_model_path,
|
||||
"Det.model_path": det_model_path,
|
||||
"Det.use_cuda": use_cuda,
|
||||
"Det.use_dml": use_dml,
|
||||
"Det.intra_op_num_threads": intra_op_num_threads,
|
||||
# Classification model settings
|
||||
"Cls.model_path": self.options.cls_model_path,
|
||||
"Cls.model_path": cls_model_path,
|
||||
"Cls.use_cuda": use_cuda,
|
||||
"Cls.use_dml": use_dml,
|
||||
"Cls.intra_op_num_threads": intra_op_num_threads,
|
||||
# Recognition model settings
|
||||
"Rec.model_path": self.options.rec_model_path,
|
||||
"Rec.model_path": rec_model_path,
|
||||
"Rec.font_path": self.options.rec_font_path,
|
||||
"Rec.keys_path": self.options.rec_keys_path,
|
||||
"Rec.keys_path": rec_keys_path,
|
||||
"Rec.use_cuda": use_cuda,
|
||||
"Rec.use_dml": use_dml,
|
||||
"Rec.intra_op_num_threads": intra_op_num_threads,
|
||||
@@ -102,6 +199,30 @@ class RapidOcrModel(BaseOcrModel):
|
||||
params=params,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def download_models(
|
||||
backend: _ModelPathEngines,
|
||||
local_dir: Optional[Path] = None,
|
||||
force: bool = False,
|
||||
progress: bool = False,
|
||||
) -> Path:
|
||||
if local_dir is None:
|
||||
local_dir = settings.cache_dir / "models" / RapidOcrModel._model_repo_folder
|
||||
|
||||
local_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Download models
|
||||
for model_type, model_details in RapidOcrModel._default_models[backend].items():
|
||||
output_path = local_dir / model_details["path"]
|
||||
if output_path.exists() and not force:
|
||||
continue
|
||||
output_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
buf = download_url_with_progress(model_details["url"], progress=progress)
|
||||
with output_path.open("wb") as fw:
|
||||
fw.write(buf.read())
|
||||
|
||||
return local_dir
|
||||
|
||||
def __call__(
|
||||
self, conv_res: ConversionResult, page_batch: Iterable[Page]
|
||||
) -> Iterable[Page]:
|
||||
|
||||
@@ -20,6 +20,7 @@ from docling.models.document_picture_classifier import DocumentPictureClassifier
|
||||
from docling.models.easyocr_model import EasyOcrModel
|
||||
from docling.models.layout_model import LayoutModel
|
||||
from docling.models.picture_description_vlm_model import PictureDescriptionVlmModel
|
||||
from docling.models.rapid_ocr_model import RapidOcrModel
|
||||
from docling.models.table_structure_model import TableStructureModel
|
||||
from docling.models.utils.hf_model_download import download_hf_model
|
||||
|
||||
@@ -41,6 +42,7 @@ def download_models(
|
||||
with_smoldocling: bool = False,
|
||||
with_smoldocling_mlx: bool = False,
|
||||
with_granite_vision: bool = False,
|
||||
with_rapidocr: bool = True,
|
||||
with_easyocr: bool = True,
|
||||
):
|
||||
if output_dir is None:
|
||||
@@ -135,6 +137,16 @@ def download_models(
|
||||
progress=progress,
|
||||
)
|
||||
|
||||
if with_rapidocr:
|
||||
for backend in ("torch", "onnxruntime"):
|
||||
_log.info(f"Downloading rapidocr {backend} models...")
|
||||
RapidOcrModel.download_models(
|
||||
backend=backend,
|
||||
local_dir=output_dir / RapidOcrModel._model_repo_folder,
|
||||
force=force,
|
||||
progress=progress,
|
||||
)
|
||||
|
||||
if with_easyocr:
|
||||
_log.info("Downloading easyocr models...")
|
||||
EasyOcrModel.download_models(
|
||||
|
||||
@@ -52,7 +52,8 @@ dependencies = [
|
||||
'pydantic-settings (>=2.3.0,<3.0.0)',
|
||||
'huggingface_hub (>=0.23,<1)',
|
||||
'requests (>=2.32.2,<3.0.0)',
|
||||
'easyocr (>=1.7,<2.0)',
|
||||
'ocrmac (>=1.0.0,<2.0.0) ; sys_platform == "darwin"',
|
||||
'rapidocr (>=3.3,<4.0.0) ; python_version < "3.14"',
|
||||
'certifi (>=2024.7.4)',
|
||||
'rtree (>=1.3.0,<2.0.0)',
|
||||
'typer (>=0.12.5,<0.20.0)',
|
||||
@@ -88,6 +89,7 @@ docling = "docling.cli.main:app"
|
||||
docling-tools = "docling.cli.tools:app"
|
||||
|
||||
[project.optional-dependencies]
|
||||
easyocr = ['easyocr (>=1.7,<2.0)']
|
||||
tesserocr = ['tesserocr (>=2.7.1,<3.0.0)']
|
||||
ocrmac = ['ocrmac (>=1.0.0,<2.0.0) ; sys_platform == "darwin"']
|
||||
vlm = [
|
||||
@@ -100,7 +102,6 @@ vlm = [
|
||||
rapidocr = [
|
||||
'rapidocr (>=3.3,<4.0.0) ; python_version < "3.14"',
|
||||
'onnxruntime (>=1.7.0,<2.0.0)',
|
||||
"modelscope>=1.29.0",
|
||||
# 'onnxruntime (>=1.7.0,<2.0.0) ; python_version >= "3.10"',
|
||||
# 'onnxruntime (>=1.7.0,<1.20.0) ; python_version < "3.10"',
|
||||
]
|
||||
@@ -143,6 +144,7 @@ examples = [
|
||||
"langchain-huggingface>=0.0.3",
|
||||
"langchain-milvus~=0.1",
|
||||
"langchain-text-splitters~=0.2",
|
||||
"modelscope>=1.29.0",
|
||||
]
|
||||
constraints = [
|
||||
'onnxruntime (>=1.7.0,<2.0.0) ; python_version >= "3.10"',
|
||||
@@ -252,6 +254,7 @@ module = [
|
||||
"docling_ibm_models.*",
|
||||
"easyocr.*",
|
||||
"ocrmac.*",
|
||||
"onnxruntime.*",
|
||||
"mlx_vlm.*",
|
||||
"lxml.*",
|
||||
"huggingface_hub.*",
|
||||
|
||||
21
uv.lock
generated
21
uv.lock
generated
@@ -1093,11 +1093,11 @@ dependencies = [
|
||||
{ name = "docling-core", extra = ["chunking"] },
|
||||
{ name = "docling-ibm-models" },
|
||||
{ name = "docling-parse" },
|
||||
{ name = "easyocr" },
|
||||
{ name = "filetype" },
|
||||
{ name = "huggingface-hub" },
|
||||
{ name = "lxml" },
|
||||
{ name = "marko" },
|
||||
{ name = "ocrmac", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "openpyxl" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pillow" },
|
||||
@@ -1109,6 +1109,7 @@ dependencies = [
|
||||
{ name = "pypdfium2" },
|
||||
{ name = "python-docx" },
|
||||
{ name = "python-pptx" },
|
||||
{ name = "rapidocr", marker = "python_full_version < '3.14'" },
|
||||
{ name = "requests" },
|
||||
{ name = "rtree" },
|
||||
{ name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
||||
@@ -1122,11 +1123,13 @@ dependencies = [
|
||||
asr = [
|
||||
{ name = "openai-whisper" },
|
||||
]
|
||||
easyocr = [
|
||||
{ name = "easyocr" },
|
||||
]
|
||||
ocrmac = [
|
||||
{ name = "ocrmac", marker = "sys_platform == 'darwin'" },
|
||||
]
|
||||
rapidocr = [
|
||||
{ name = "modelscope" },
|
||||
{ name = "onnxruntime", version = "1.19.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
||||
{ name = "onnxruntime", version = "1.23.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
||||
{ name = "rapidocr", marker = "python_full_version < '3.14'" },
|
||||
@@ -1181,6 +1184,7 @@ examples = [
|
||||
{ name = "langchain-huggingface" },
|
||||
{ name = "langchain-milvus" },
|
||||
{ name = "langchain-text-splitters" },
|
||||
{ name = "modelscope" },
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
|
||||
@@ -1193,13 +1197,13 @@ requires-dist = [
|
||||
{ name = "docling-core", extras = ["chunking"], specifier = ">=2.48.2,<3.0.0" },
|
||||
{ name = "docling-ibm-models", specifier = ">=3.9.1,<4" },
|
||||
{ name = "docling-parse", specifier = ">=4.4.0,<5.0.0" },
|
||||
{ name = "easyocr", specifier = ">=1.7,<2.0" },
|
||||
{ name = "easyocr", marker = "extra == 'easyocr'", specifier = ">=1.7,<2.0" },
|
||||
{ name = "filetype", specifier = ">=1.2.0,<2.0.0" },
|
||||
{ name = "huggingface-hub", specifier = ">=0.23,<1" },
|
||||
{ name = "lxml", specifier = ">=4.0.0,<6.0.0" },
|
||||
{ name = "marko", specifier = ">=2.1.2,<3.0.0" },
|
||||
{ name = "mlx-vlm", marker = "python_full_version >= '3.10' and platform_machine == 'arm64' and sys_platform == 'darwin' and extra == 'vlm'", specifier = ">=0.3.0,<1.0.0" },
|
||||
{ name = "modelscope", marker = "extra == 'rapidocr'", specifier = ">=1.29.0" },
|
||||
{ name = "ocrmac", marker = "sys_platform == 'darwin'", specifier = ">=1.0.0,<2.0.0" },
|
||||
{ name = "ocrmac", marker = "sys_platform == 'darwin' and extra == 'ocrmac'", specifier = ">=1.0.0,<2.0.0" },
|
||||
{ name = "onnxruntime", marker = "extra == 'rapidocr'", specifier = ">=1.7.0,<2.0.0" },
|
||||
{ name = "openai-whisper", marker = "extra == 'asr'", specifier = ">=20250625" },
|
||||
@@ -1215,6 +1219,7 @@ requires-dist = [
|
||||
{ name = "python-docx", specifier = ">=1.1.2,<2.0.0" },
|
||||
{ name = "python-pptx", specifier = ">=1.0.2,<2.0.0" },
|
||||
{ name = "qwen-vl-utils", marker = "extra == 'vlm'", specifier = ">=0.0.11" },
|
||||
{ name = "rapidocr", marker = "python_full_version < '3.14'", specifier = ">=3.3,<4.0.0" },
|
||||
{ name = "rapidocr", marker = "python_full_version < '3.14' and extra == 'rapidocr'", specifier = ">=3.3,<4.0.0" },
|
||||
{ name = "requests", specifier = ">=2.32.2,<3.0.0" },
|
||||
{ name = "rtree", specifier = ">=1.3.0,<2.0.0" },
|
||||
@@ -1225,7 +1230,7 @@ requires-dist = [
|
||||
{ name = "typer", specifier = ">=0.12.5,<0.20.0" },
|
||||
{ name = "vllm", marker = "python_full_version >= '3.10' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'vlm'", specifier = ">=0.10.0,<1.0.0" },
|
||||
]
|
||||
provides-extras = ["tesserocr", "ocrmac", "vlm", "rapidocr", "asr"]
|
||||
provides-extras = ["easyocr", "tesserocr", "ocrmac", "vlm", "rapidocr", "asr"]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
constraints = [
|
||||
@@ -1265,6 +1270,7 @@ examples = [
|
||||
{ name = "langchain-huggingface", specifier = ">=0.0.3" },
|
||||
{ name = "langchain-milvus", specifier = "~=0.1" },
|
||||
{ name = "langchain-text-splitters", specifier = "~=0.2" },
|
||||
{ name = "modelscope", specifier = ">=1.29.0" },
|
||||
{ name = "python-dotenv", specifier = "~=1.0" },
|
||||
]
|
||||
|
||||
@@ -5039,6 +5045,9 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/8a/b35a615ae6f04550d696bb179c414538b3b477999435fdd4ad75b76139e4/pybase64-1.4.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:a370dea7b1cee2a36a4d5445d4e09cc243816c5bc8def61f602db5a6f5438e52", size = 54320, upload-time = "2025-07-27T13:03:27.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/a9/8bd4f9bcc53689f1b457ecefed1eaa080e4949d65a62c31a38b7253d5226/pybase64-1.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9aa4de83f02e462a6f4e066811c71d6af31b52d7484de635582d0e3ec3d6cc3e", size = 56482, upload-time = "2025-07-27T13:03:28.942Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/e5/4a7735b54a1191f61c3f5c2952212c85c2d6b06eb5fb3671c7603395f70c/pybase64-1.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83a1c2f9ed00fee8f064d548c8654a480741131f280e5750bb32475b7ec8ee38", size = 70959, upload-time = "2025-07-27T13:03:30.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/56/5337f27a8b8d2d6693f46f7b36bae47895e5820bfa259b0072574a4e1057/pybase64-1.4.2-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:0f331aa59549de21f690b6ccc79360ffed1155c3cfbc852eb5c097c0b8565a2b", size = 33888, upload-time = "2025-07-27T13:03:35.698Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/ff/470768f0fe6de0aa302a8cb1bdf2f9f5cffc3f69e60466153be68bc953aa/pybase64-1.4.2-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:69d3f0445b0faeef7bb7f93bf8c18d850785e2a77f12835f49e524cc54af04e7", size = 30914, upload-time = "2025-07-27T13:03:38.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/6b/d328736662665e0892409dc410353ebef175b1be5eb6bab1dad579efa6df/pybase64-1.4.2-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2372b257b1f4dd512f317fb27e77d313afd137334de64c87de8374027aacd88a", size = 31380, upload-time = "2025-07-27T13:03:39.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/96/7ff718f87c67f4147c181b73d0928897cefa17dc75d7abc6e37730d5908f/pybase64-1.4.2-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:fb794502b4b1ec91c4ca5d283ae71aef65e3de7721057bd9e2b3ec79f7a62d7d", size = 38230, upload-time = "2025-07-27T13:03:41.637Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/ab/db4dbdfccb9ca874d6ce34a0784761471885d96730de85cee3d300381529/pybase64-1.4.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d377d48acf53abf4b926c2a7a24a19deb092f366a04ffd856bf4b3aa330b025d", size = 71608, upload-time = "2025-07-27T13:03:47.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/58/7f2cef1ceccc682088958448d56727369de83fa6b29148478f4d2acd107a/pybase64-1.4.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:ab9cdb6a8176a5cb967f53e6ad60e40c83caaa1ae31c5e1b29e5c8f507f17538", size = 56413, upload-time = "2025-07-27T13:03:49.908Z" },
|
||||
@@ -5060,6 +5069,8 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/f0/c392c4ac8ccb7a34b28377c21faa2395313e3c676d76c382642e19a20703/pybase64-1.4.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad59362fc267bf15498a318c9e076686e4beeb0dfe09b457fabbc2b32468b97a", size = 58103, upload-time = "2025-07-27T13:04:29.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/30/00ab21316e7df8f526aa3e3dc06f74de6711d51c65b020575d0105a025b2/pybase64-1.4.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:01593bd064e7dcd6c86d04e94e44acfe364049500c20ac68ca1e708fbb2ca970", size = 60779, upload-time = "2025-07-27T13:04:31.549Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/65/114ca81839b1805ce4a2b7d58bc16e95634734a2059991f6382fc71caf3e/pybase64-1.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5b81547ad8ea271c79fdf10da89a1e9313cb15edcba2a17adf8871735e9c02a0", size = 74684, upload-time = "2025-07-27T13:04:32.976Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/bf/00a87d951473ce96c8c08af22b6983e681bfabdb78dd2dcf7ee58eac0932/pybase64-1.4.2-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:4157ad277a32cf4f02a975dffc62a3c67d73dfa4609b2c1978ef47e722b18b8e", size = 30924, upload-time = "2025-07-27T13:04:39.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/43/dee58c9d60e60e6fb32dc6da722d84592e22f13c277297eb4ce6baf99a99/pybase64-1.4.2-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:e113267dc349cf624eb4f4fbf53fd77835e1aa048ac6877399af426aab435757", size = 31390, upload-time = "2025-07-27T13:04:40.995Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/11/b28906fc2e330b8b1ab4bc845a7bef808b8506734e90ed79c6062b095112/pybase64-1.4.2-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:cea5aaf218fd9c5c23afacfe86fd4464dfedc1a0316dd3b5b4075b068cc67df0", size = 38212, upload-time = "2025-07-27T13:04:42.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/2e/851eb51284b97354ee5dfa1309624ab90920696e91a33cd85b13d20cc5c1/pybase64-1.4.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a3e54dcf0d0305ec88473c9d0009f698cabf86f88a8a10090efeff2879c421bb", size = 71674, upload-time = "2025-07-27T13:04:49.294Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/8e/3479266bc0e65f6cc48b3938d4a83bff045330649869d950a378f2ddece0/pybase64-1.4.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:753da25d4fd20be7bda2746f545935773beea12d5cb5ec56ec2d2960796477b1", size = 56461, upload-time = "2025-07-27T13:04:52.37Z" },
|
||||
|
||||
Reference in New Issue
Block a user