perf: Move expensive imports closer to usage (#1863)

* Move expensive imports closer to usage

Signed-off-by: William Easton <bill.easton@elastic.co>

* DCO Remediation Commit for William Easton <bill.easton@elastic.co>

I, William Easton <bill.easton@elastic.co>, hereby add my Signed-off-by to this commit: 8a7412ce5bb131a01bb6403067aeb948c9093b0b

Signed-off-by: William Easton <bill.easton@elastic.co>

* formatting fixes

Signed-off-by: William Easton <bill.easton@elastic.co>

* DCO Remediation Commit for William Easton <bill.easton@elastic.co>

I, William Easton <bill.easton@elastic.co>, hereby add my Signed-off-by to this commit: 8a7412ce5bb131a01bb6403067aeb948c9093b0b
I, William Easton <bill.easton@elastic.co>, hereby add my Signed-off-by to this commit: 963e34325071db5e844841f10c27b396a054a0a1

Signed-off-by: William Easton <bill.easton@elastic.co>

* Fix baseocrmodel test issue

Signed-off-by: William Easton <bill.easton@elastic.co>

---------

Signed-off-by: William Easton <bill.easton@elastic.co>
This commit is contained in:
William Easton 2025-07-01 15:27:17 -05:00 committed by GitHub
parent 56a0e104f7
commit 3089cf2d26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 22 additions and 15 deletions

View File

@ -3,14 +3,13 @@ import logging
from abc import abstractmethod from abc import abstractmethod
from collections.abc import Iterable from collections.abc import Iterable
from pathlib import Path from pathlib import Path
from typing import List, Optional, Type from typing import TYPE_CHECKING, List, Optional, Type
import numpy as np import numpy as np
from docling_core.types.doc import BoundingBox, CoordOrigin from docling_core.types.doc import BoundingBox, CoordOrigin
from docling_core.types.doc.page import TextCell from docling_core.types.doc.page import TextCell
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
from rtree import index from rtree import index
from scipy.ndimage import binary_dilation, find_objects, label
from docling.datamodel.accelerator_options import AcceleratorOptions from docling.datamodel.accelerator_options import AcceleratorOptions
from docling.datamodel.base_models import Page from docling.datamodel.base_models import Page
@ -31,11 +30,16 @@ class BaseOcrModel(BasePageModel, BaseModelWithOptions):
options: OcrOptions, options: OcrOptions,
accelerator_options: AcceleratorOptions, accelerator_options: AcceleratorOptions,
): ):
# Make sure any delay/error from import occurs on ocr model init and not first use
from scipy.ndimage import binary_dilation, find_objects, label
self.enabled = enabled self.enabled = enabled
self.options = options self.options = options
# Computes the optimum amount and coordinates of rectangles to OCR on a given page # Computes the optimum amount and coordinates of rectangles to OCR on a given page
def get_ocr_rects(self, page: Page) -> List[BoundingBox]: def get_ocr_rects(self, page: Page) -> List[BoundingBox]:
from scipy.ndimage import binary_dilation, find_objects, label
BITMAP_COVERAGE_TRESHOLD = 0.75 BITMAP_COVERAGE_TRESHOLD = 0.75
assert page.size is not None assert page.size is not None

View File

@ -7,7 +7,6 @@ from typing import Optional
import numpy as np import numpy as np
from docling_core.types.doc import DocItemLabel from docling_core.types.doc import DocItemLabel
from docling_ibm_models.layoutmodel.layout_predictor import LayoutPredictor
from PIL import Image from PIL import Image
from docling.datamodel.accelerator_options import AcceleratorOptions from docling.datamodel.accelerator_options import AcceleratorOptions
@ -51,6 +50,8 @@ class LayoutModel(BasePageModel):
def __init__( def __init__(
self, artifacts_path: Optional[Path], accelerator_options: AcceleratorOptions self, artifacts_path: Optional[Path], accelerator_options: AcceleratorOptions
): ):
from docling_ibm_models.layoutmodel.layout_predictor import LayoutPredictor
device = decide_device(accelerator_options.device) device = decide_device(accelerator_options.device)
if artifacts_path is None: if artifacts_path is None:

View File

@ -1,13 +1,10 @@
from docling.models.easyocr_model import EasyOcrModel
from docling.models.ocr_mac_model import OcrMacModel
from docling.models.picture_description_api_model import PictureDescriptionApiModel
from docling.models.picture_description_vlm_model import PictureDescriptionVlmModel
from docling.models.rapid_ocr_model import RapidOcrModel
from docling.models.tesseract_ocr_cli_model import TesseractOcrCliModel
from docling.models.tesseract_ocr_model import TesseractOcrModel
def ocr_engines(): def ocr_engines():
from docling.models.easyocr_model import EasyOcrModel
from docling.models.ocr_mac_model import OcrMacModel
from docling.models.rapid_ocr_model import RapidOcrModel
from docling.models.tesseract_ocr_cli_model import TesseractOcrCliModel
from docling.models.tesseract_ocr_model import TesseractOcrModel
return { return {
"ocr_engines": [ "ocr_engines": [
EasyOcrModel, EasyOcrModel,
@ -20,6 +17,9 @@ def ocr_engines():
def picture_description(): def picture_description():
from docling.models.picture_description_api_model import PictureDescriptionApiModel
from docling.models.picture_description_vlm_model import PictureDescriptionVlmModel
return { return {
"picture_description": [ "picture_description": [
PictureDescriptionVlmModel, PictureDescriptionVlmModel,

View File

@ -10,7 +10,6 @@ from docling_core.types.doc.page import (
BoundingRectangle, BoundingRectangle,
TextCellUnit, TextCellUnit,
) )
from docling_ibm_models.tableformer.data_management.tf_predictor import TFPredictor
from PIL import ImageDraw from PIL import ImageDraw
from docling.datamodel.accelerator_options import AcceleratorDevice, AcceleratorOptions from docling.datamodel.accelerator_options import AcceleratorDevice, AcceleratorOptions
@ -70,6 +69,9 @@ class TableStructureModel(BasePageModel):
# Third Party # Third Party
import docling_ibm_models.tableformer.common as c import docling_ibm_models.tableformer.common as c
from docling_ibm_models.tableformer.data_management.tf_predictor import (
TFPredictor,
)
device = decide_device(accelerator_options.device) device = decide_device(accelerator_options.device)

View File

@ -1,8 +1,6 @@
import logging import logging
from typing import List, Optional from typing import List, Optional
import torch
from docling.datamodel.accelerator_options import AcceleratorDevice from docling.datamodel.accelerator_options import AcceleratorDevice
_log = logging.getLogger(__name__) _log = logging.getLogger(__name__)
@ -18,6 +16,8 @@ def decide_device(
1. AUTO: Check for the best available device on the system. 1. AUTO: Check for the best available device on the system.
2. User-defined: Check if the device actually exists, otherwise fall-back to CPU 2. User-defined: Check if the device actually exists, otherwise fall-back to CPU
""" """
import torch
device = "cpu" device = "cpu"
has_cuda = torch.backends.cuda.is_built() and torch.cuda.is_available() has_cuda = torch.backends.cuda.is_built() and torch.cuda.is_available()