mathcraft-ocr 0.2.6__tar.gz → 0.2.7__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.
Potentially problematic release.
This version of mathcraft-ocr might be problematic. Click here for more details.
- {mathcraft_ocr-0.2.6/mathcraft_ocr.egg-info → mathcraft_ocr-0.2.7}/PKG-INFO +2 -2
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/README_MATHCRAFT_OCR.md +1 -1
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/__init__.py +1 -1
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/common.py +9 -1
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/text_recognizer.py +32 -3
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/error_patterns.py +14 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/providers.py +11 -18
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/runtime.py +2 -2
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/serialization.py +0 -1
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7/mathcraft_ocr.egg-info}/PKG-INFO +2 -2
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/pyproject.toml +1 -1
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/LICENSE +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/MANIFEST.in +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/__main__.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/__init__.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/formula_detector.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/formula_recognizer.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/adapters/text_detector.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/api.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/cache.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/cli.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/debug_blocks.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/doctor.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/downloader.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/errors.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/formula_lines.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/hardware.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/image.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/latex_alignment.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/latex_quality.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/layout.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/manifest.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/manifests/models.v1.json +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/profiles.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/results.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr/worker.py +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr.egg-info/SOURCES.txt +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr.egg-info/dependency_links.txt +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr.egg-info/entry_points.txt +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr.egg-info/requires.txt +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/mathcraft_ocr.egg-info/top_level.txt +0 -0
- {mathcraft_ocr-0.2.6 → mathcraft_ocr-0.2.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathcraft-ocr
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: ONNX-only OCR runtime for mathematical documents
|
|
5
5
|
Author: SakuraMathcraft
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -215,4 +215,4 @@ python -m build --no-isolation --outdir .\release_assets\mathcraft-ocr-package\d
|
|
|
215
215
|
|
|
216
216
|
## License
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
GPL-3.0-only. See `LICENSE`.
|
|
@@ -33,13 +33,21 @@ def create_session(model_path: str | Path, provider_info: ProviderInfo):
|
|
|
33
33
|
raise RuntimeError(
|
|
34
34
|
f"requested ONNX GPU provider {active}, but session providers are {actual}"
|
|
35
35
|
)
|
|
36
|
+
disable_fallback = getattr(session, "disable_fallback", None)
|
|
37
|
+
if not callable(disable_fallback):
|
|
38
|
+
raise RuntimeError("ONNX Runtime session cannot disable provider fallback")
|
|
39
|
+
disable_fallback()
|
|
36
40
|
return session
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
@lru_cache(maxsize=16)
|
|
40
44
|
def _create_session_cached(model_path: str, providers: tuple[str, ...]):
|
|
41
45
|
ort = _ort()
|
|
42
|
-
return ort.InferenceSession(
|
|
46
|
+
return ort.InferenceSession(
|
|
47
|
+
model_path,
|
|
48
|
+
providers=list(providers),
|
|
49
|
+
enable_fallback=False,
|
|
50
|
+
)
|
|
43
51
|
|
|
44
52
|
|
|
45
53
|
def clear_session_cache() -> None:
|
|
@@ -57,11 +57,21 @@ def _create_pp_text_recognizer(model_dir: Path, provider_info) -> TextRecognizer
|
|
|
57
57
|
active_provider = str(getattr(provider_info, "active_provider", "") or "")
|
|
58
58
|
use_cuda = active_provider in {"CUDAExecutionProvider", "TensorrtExecutionProvider"}
|
|
59
59
|
use_dml = active_provider == "DmlExecutionProvider"
|
|
60
|
-
return _create_pp_text_recognizer_cached(
|
|
60
|
+
return _create_pp_text_recognizer_cached(
|
|
61
|
+
str(model_dir),
|
|
62
|
+
active_provider,
|
|
63
|
+
use_cuda,
|
|
64
|
+
use_dml,
|
|
65
|
+
)
|
|
61
66
|
|
|
62
67
|
|
|
63
68
|
@lru_cache(maxsize=8)
|
|
64
|
-
def _create_pp_text_recognizer_cached(
|
|
69
|
+
def _create_pp_text_recognizer_cached(
|
|
70
|
+
model_dir: str,
|
|
71
|
+
active_provider: str,
|
|
72
|
+
use_cuda: bool,
|
|
73
|
+
use_dml: bool,
|
|
74
|
+
) -> TextRecognizer:
|
|
65
75
|
model_dir = Path(model_dir)
|
|
66
76
|
model_candidates = sorted(model_dir.glob("**/*rec*.onnx"))
|
|
67
77
|
if not model_candidates:
|
|
@@ -111,7 +121,26 @@ def _create_pp_text_recognizer_cached(model_dir: str, use_cuda: bool, use_dml: b
|
|
|
111
121
|
},
|
|
112
122
|
},
|
|
113
123
|
})
|
|
114
|
-
|
|
124
|
+
recognizer = TextRecognizer(config)
|
|
125
|
+
_enforce_strict_provider(recognizer, active_provider)
|
|
126
|
+
return recognizer
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _enforce_strict_provider(recognizer: TextRecognizer, active_provider: str) -> None:
|
|
130
|
+
engine = getattr(recognizer, "session", None)
|
|
131
|
+
session = getattr(engine, "session", None)
|
|
132
|
+
if session is None:
|
|
133
|
+
raise RuntimeError("RapidOCR did not expose its ONNX Runtime session")
|
|
134
|
+
actual = list(session.get_providers() or [])
|
|
135
|
+
if not active_provider or not actual or actual[0] != active_provider:
|
|
136
|
+
raise RuntimeError(
|
|
137
|
+
f"requested ONNX provider {active_provider or '<none>'}, "
|
|
138
|
+
f"but RapidOCR session providers are {actual}"
|
|
139
|
+
)
|
|
140
|
+
disable_fallback = getattr(session, "disable_fallback", None)
|
|
141
|
+
if not callable(disable_fallback):
|
|
142
|
+
raise RuntimeError("RapidOCR ONNX Runtime session cannot disable provider fallback")
|
|
143
|
+
disable_fallback()
|
|
115
144
|
|
|
116
145
|
|
|
117
146
|
def clear_text_recognizer_cache() -> None:
|
|
@@ -17,6 +17,13 @@ CUDA_RUNTIME_ERROR_MARKERS = (
|
|
|
17
17
|
"cufft",
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
+
GPU_PROVIDER_ERROR_MARKERS = (
|
|
21
|
+
"gpu provider was requested",
|
|
22
|
+
"requested onnx gpu provider",
|
|
23
|
+
"requested onnx provider dmlexecutionprovider",
|
|
24
|
+
"requested onnx provider tensorrtexecutionprovider",
|
|
25
|
+
)
|
|
26
|
+
|
|
20
27
|
ONNXRUNTIME_INSTALL_ERROR_MARKERS = (
|
|
21
28
|
"failed to import onnxruntime",
|
|
22
29
|
"failed to query onnx providers",
|
|
@@ -31,6 +38,11 @@ def looks_like_cuda_runtime_error(detail: object) -> bool:
|
|
|
31
38
|
return any(marker in text for marker in CUDA_RUNTIME_ERROR_MARKERS)
|
|
32
39
|
|
|
33
40
|
|
|
41
|
+
def looks_like_gpu_provider_error(detail: object) -> bool:
|
|
42
|
+
text = str(detail or "").lower()
|
|
43
|
+
return any(marker in text for marker in GPU_PROVIDER_ERROR_MARKERS)
|
|
44
|
+
|
|
45
|
+
|
|
34
46
|
def looks_like_onnxruntime_install_error(detail: object) -> bool:
|
|
35
47
|
text = str(detail or "").lower()
|
|
36
48
|
return any(marker in text for marker in ONNXRUNTIME_INSTALL_ERROR_MARKERS)
|
|
@@ -38,7 +50,9 @@ def looks_like_onnxruntime_install_error(detail: object) -> bool:
|
|
|
38
50
|
|
|
39
51
|
__all__ = [
|
|
40
52
|
"CUDA_RUNTIME_ERROR_MARKERS",
|
|
53
|
+
"GPU_PROVIDER_ERROR_MARKERS",
|
|
41
54
|
"ONNXRUNTIME_INSTALL_ERROR_MARKERS",
|
|
42
55
|
"looks_like_cuda_runtime_error",
|
|
56
|
+
"looks_like_gpu_provider_error",
|
|
43
57
|
"looks_like_onnxruntime_install_error",
|
|
44
58
|
]
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import importlib
|
|
6
|
-
import os
|
|
7
6
|
from dataclasses import dataclass
|
|
8
7
|
|
|
9
8
|
from .errors import ProviderError
|
|
@@ -23,7 +22,6 @@ class ProviderInfo:
|
|
|
23
22
|
device: str
|
|
24
23
|
gpu_requested: bool
|
|
25
24
|
gpu_runtime_ok: bool
|
|
26
|
-
cpu_fallback: bool
|
|
27
25
|
|
|
28
26
|
@property
|
|
29
27
|
def use_cuda(self) -> bool:
|
|
@@ -56,26 +54,17 @@ def detect_providers(prefer: str = "auto") -> ProviderInfo:
|
|
|
56
54
|
except Exception as exc: # pragma: no cover - runtime environment dependent
|
|
57
55
|
raise ProviderError(f"failed to query ONNX providers: {exc}") from exc
|
|
58
56
|
|
|
59
|
-
force_cpu = os.environ.get("MATHCRAFT_FORCE_ORT_CPU", "").strip() == "1"
|
|
60
57
|
gpu_candidates = tuple(name for name in GPU_PROVIDER_NAMES if name in available)
|
|
61
58
|
gpu_visible = bool(gpu_candidates)
|
|
62
|
-
if force_cpu:
|
|
63
|
-
return ProviderInfo(
|
|
64
|
-
available_providers=available,
|
|
65
|
-
active_provider="CPUExecutionProvider" if "CPUExecutionProvider" in available else None,
|
|
66
|
-
device="cpu",
|
|
67
|
-
gpu_requested=(prefer_norm in {"auto", "gpu"}),
|
|
68
|
-
gpu_runtime_ok=False,
|
|
69
|
-
cpu_fallback=True,
|
|
70
|
-
)
|
|
71
59
|
if prefer_norm == "cpu":
|
|
60
|
+
if "CPUExecutionProvider" not in available:
|
|
61
|
+
raise ProviderError(f"CPUExecutionProvider unavailable: {available}")
|
|
72
62
|
return ProviderInfo(
|
|
73
63
|
available_providers=available,
|
|
74
|
-
active_provider="CPUExecutionProvider"
|
|
64
|
+
active_provider="CPUExecutionProvider",
|
|
75
65
|
device="cpu",
|
|
76
66
|
gpu_requested=False,
|
|
77
67
|
gpu_runtime_ok=False,
|
|
78
|
-
cpu_fallback=False,
|
|
79
68
|
)
|
|
80
69
|
if gpu_visible:
|
|
81
70
|
return ProviderInfo(
|
|
@@ -84,13 +73,17 @@ def detect_providers(prefer: str = "auto") -> ProviderInfo:
|
|
|
84
73
|
device="gpu",
|
|
85
74
|
gpu_requested=True,
|
|
86
75
|
gpu_runtime_ok=True,
|
|
87
|
-
cpu_fallback=False,
|
|
88
76
|
)
|
|
77
|
+
if prefer_norm == "gpu":
|
|
78
|
+
raise ProviderError(
|
|
79
|
+
f"GPU provider was requested but none is available: {available}"
|
|
80
|
+
)
|
|
81
|
+
if "CPUExecutionProvider" not in available:
|
|
82
|
+
raise ProviderError(f"no supported ONNX execution provider is available: {available}")
|
|
89
83
|
return ProviderInfo(
|
|
90
84
|
available_providers=available,
|
|
91
|
-
active_provider="CPUExecutionProvider"
|
|
85
|
+
active_provider="CPUExecutionProvider",
|
|
92
86
|
device="cpu",
|
|
93
|
-
gpu_requested=
|
|
87
|
+
gpu_requested=False,
|
|
94
88
|
gpu_runtime_ok=False,
|
|
95
|
-
cpu_fallback=(prefer_norm == "gpu"),
|
|
96
89
|
)
|
|
@@ -22,7 +22,7 @@ from .adapters.text_recognizer import (
|
|
|
22
22
|
from .cache import ModelCacheState, inspect_manifest_roots, resolve_model_roots, resolve_user_models_dir
|
|
23
23
|
from .doctor import DoctorReport, run_doctor
|
|
24
24
|
from .downloader import download_model_archive
|
|
25
|
-
from .error_patterns import looks_like_cuda_runtime_error
|
|
25
|
+
from .error_patterns import looks_like_cuda_runtime_error, looks_like_gpu_provider_error
|
|
26
26
|
from .errors import ModelCacheError
|
|
27
27
|
from .formula_lines import (
|
|
28
28
|
FormulaLineGroup,
|
|
@@ -207,7 +207,7 @@ class MathCraftRuntime:
|
|
|
207
207
|
@staticmethod
|
|
208
208
|
def _looks_like_broken_model_error(exc: Exception) -> bool:
|
|
209
209
|
text = str(exc).lower()
|
|
210
|
-
if looks_like_cuda_runtime_error(text):
|
|
210
|
+
if looks_like_cuda_runtime_error(text) or looks_like_gpu_provider_error(text):
|
|
211
211
|
return False
|
|
212
212
|
needles = (
|
|
213
213
|
"missing",
|
|
@@ -71,7 +71,6 @@ def provider_info_to_json(provider_info) -> dict:
|
|
|
71
71
|
"device": provider_info.device,
|
|
72
72
|
"gpu_requested": provider_info.gpu_requested,
|
|
73
73
|
"gpu_runtime_ok": provider_info.gpu_runtime_ok,
|
|
74
|
-
"cpu_fallback": provider_info.cpu_fallback,
|
|
75
74
|
"use_cuda": provider_info.use_cuda,
|
|
76
75
|
"use_dml": provider_info.use_dml,
|
|
77
76
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathcraft-ocr
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: ONNX-only OCR runtime for mathematical documents
|
|
5
5
|
Author: SakuraMathcraft
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -215,4 +215,4 @@ python -m build --no-isolation --outdir .\release_assets\mathcraft-ocr-package\d
|
|
|
215
215
|
|
|
216
216
|
## License
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
GPL-3.0-only. See `LICENSE`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|