From 67e310caa90ce1d2112bc5e56bf8c3c26568c482 Mon Sep 17 00:00:00 2001 From: Success6666 Date: Sun, 26 Jul 2026 17:55:19 +0800 Subject: [PATCH] fix(ocr): support Latin languages with RapidOCR ONNX Signed-off-by: Success6666 --- docling/datamodel/pipeline_options.py | 2 +- docling/models/stages/ocr/rapid_ocr_model.py | 9 ++++-- tests/test_rapid_ocr_lang.py | 29 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docling/datamodel/pipeline_options.py b/docling/datamodel/pipeline_options.py index 874e5d8435..f99c589cdd 100644 --- a/docling/datamodel/pipeline_options.py +++ b/docling/datamodel/pipeline_options.py @@ -284,7 +284,7 @@ class RapidOcrOptions(OcrOptions): list[str], Field( description=( - "List of OCR languages. Note: RapidOCR currently supports 'english' and 'chinese' (default). " + "List of OCR languages. RapidOCR supports 'english', 'chinese' (default), and common Latin-script language aliases. " "See RapidOCR documentation for other supported languages." ) ), diff --git a/docling/models/stages/ocr/rapid_ocr_model.py b/docling/models/stages/ocr/rapid_ocr_model.py index 4730e83c26..522007ba25 100644 --- a/docling/models/stages/ocr/rapid_ocr_model.py +++ b/docling/models/stages/ocr/rapid_ocr_model.py @@ -261,7 +261,7 @@ def _rapidocr_lang_type_params(ocr_lang: str) -> dict[str, object]: return mapping.get(ocr_lang, {}) -def _rapidocr_torch_ppocrv4_params() -> dict[str, object]: +def _rapidocr_ppocrv4_params() -> dict[str, object]: try: from rapidocr.utils.typings import ModelType, OCRVersion # type: ignore except ImportError: @@ -433,8 +433,11 @@ def resolve_artifact_path( ) if det_model_path is None and rec_model_path is None: params.update(_rapidocr_lang_type_params(ocr_lang)) - if backend_enum == EngineType.TORCH: - params.update(_rapidocr_torch_ppocrv4_params()) + # PP-OCRv6 has per-language routes but no generic Latin route. + if backend_enum == EngineType.TORCH or ( + backend_enum == EngineType.ONNXRUNTIME and ocr_lang == "latin" + ): + params.update(_rapidocr_ppocrv4_params()) user_params = self.options.rapidocr_params if user_params: diff --git a/tests/test_rapid_ocr_lang.py b/tests/test_rapid_ocr_lang.py index 7da9ac06ad..d626cc5be6 100644 --- a/tests/test_rapid_ocr_lang.py +++ b/tests/test_rapid_ocr_lang.py @@ -217,3 +217,32 @@ def test_rapidocr_passes_lang_type_without_artifacts(monkeypatch) -> None: assert params["Det.lang_type"] == "en" # No pinned paths: rapidocr resolves the models itself. assert params["Rec.model_path"] is None + + +def test_rapidocr_uses_ppocrv4_for_onnx_latin_without_artifacts(monkeypatch) -> None: + captured_params: list[dict[str, object]] = [] + _install_fake_rapidocr(monkeypatch, captured_params) + + fake_typings = ModuleType("rapidocr.utils.typings") + fake_typings.LangDet = SimpleNamespace(EN="en", CH="ch", MULTI="multi") + fake_typings.LangRec = SimpleNamespace(EN="en", LATIN="latin", CH="ch") + fake_typings.ModelType = SimpleNamespace(MOBILE="mobile") + fake_typings.OCRVersion = SimpleNamespace(PPOCRV4="PP-OCRv4") + fake_utils = ModuleType("rapidocr.utils") + fake_utils.typings = fake_typings + monkeypatch.setitem(sys.modules, "rapidocr.utils", fake_utils) + monkeypatch.setitem(sys.modules, "rapidocr.utils.typings", fake_typings) + + RapidOcrModel( + enabled=True, + artifacts_path=None, + options=RapidOcrOptions(lang=["es"], backend="onnxruntime"), + accelerator_options=AcceleratorOptions(), + ) + + assert len(captured_params) == 1 + params = captured_params[0] + assert params["Rec.lang_type"] == "latin" + for stage in ("Det", "Cls", "Rec"): + assert params[f"{stage}.ocr_version"] == "PP-OCRv4" + assert params[f"{stage}.model_type"] == "mobile"