Deploy CUDA-enforced runtime changes for OCR
Browse files
app.py
CHANGED
|
@@ -257,6 +257,27 @@ def _assert_model_on_cuda(model, model_id: str, context: str) -> None:
|
|
| 257 |
)
|
| 258 |
|
| 259 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
def _inference_torch_kwargs_for_model(strict_cuda: bool = False) -> Tuple[dict, list]:
|
| 261 |
kwargs_priority = []
|
| 262 |
dtype = _inference_dtype()
|
|
@@ -754,6 +775,11 @@ def _build_local_pipeline(model_id: str, hf_token: str, task: str, trust_remote_
|
|
| 754 |
try:
|
| 755 |
candidate_pipeline = hf_pipeline(candidate_task, **cleaned_kwargs)
|
| 756 |
if strict_cuda:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 757 |
candidate_model = getattr(candidate_pipeline, "model", None)
|
| 758 |
if candidate_model is not None and torch is not None and torch.cuda.is_available():
|
| 759 |
try:
|
|
@@ -1083,6 +1109,12 @@ def run_local_model(entry: dict, image_bytes: bytes, prompt: str, hf_token: str)
|
|
| 1083 |
|
| 1084 |
if pipeline is not None:
|
| 1085 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1086 |
if _strict_cuda_required():
|
| 1087 |
_assert_model_on_cuda(getattr(pipeline, "model", None), model_id, "pipeline execution")
|
| 1088 |
pipeline_model = getattr(pipeline, "model", None)
|
|
@@ -1238,7 +1270,9 @@ def run_single_model(entry: dict, image_bytes: bytes, data_uri: str, hf_token: s
|
|
| 1238 |
prompt = entry.get("prompt", DEFAULT_OCR_PROMPT)
|
| 1239 |
params = sanitize_generation_params(entry.get("parameters", {}))
|
| 1240 |
notes = entry.get("notes", "")
|
| 1241 |
-
|
|
|
|
|
|
|
| 1242 |
start = time.perf_counter()
|
| 1243 |
output = ""
|
| 1244 |
|
|
@@ -1298,6 +1332,8 @@ def _get_runtime_profile() -> Dict[str, object]:
|
|
| 1298 |
|
| 1299 |
if torch.cuda.is_available():
|
| 1300 |
profile["has_cuda"] = True
|
|
|
|
|
|
|
| 1301 |
props = torch.cuda.get_device_properties(0)
|
| 1302 |
profile["gpu_name"] = props.name
|
| 1303 |
profile["gpu_vram_gb"] = round(props.total_memory / (1024 ** 3), 1)
|
|
@@ -1310,7 +1346,9 @@ def _get_runtime_profile() -> Dict[str, object]:
|
|
| 1310 |
profile["gpu_free_vram_gb"] = round(free_approx / (1024 ** 3), 1)
|
| 1311 |
profile["gpu_reserved_vram_gb"] = round(torch.cuda.memory_reserved(0) / (1024 ** 3), 1)
|
| 1312 |
profile["gpu_allocated_vram_gb"] = round(torch.cuda.memory_allocated(0) / (1024 ** 3), 1)
|
| 1313 |
-
|
|
|
|
|
|
|
| 1314 |
profile["provider"] = "zero_gpu"
|
| 1315 |
except Exception:
|
| 1316 |
pass
|
|
@@ -1343,6 +1381,10 @@ def _startup_cuda_audit() -> None:
|
|
| 1343 |
f"cuda_built={runtime.get('torch_cuda_built')}"
|
| 1344 |
)
|
| 1345 |
if runtime.get("has_cuda"):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1346 |
print(
|
| 1347 |
"[startup] Compute backend: "
|
| 1348 |
f"{runtime.get('provider')} 路 {runtime.get('gpu_name')} 路 total {runtime.get('gpu_vram_gb')}GB 路 "
|
|
|
|
| 257 |
)
|
| 258 |
|
| 259 |
|
| 260 |
+
def _move_pipeline_to_cuda(pipeline, model_id: str, context: str):
|
| 261 |
+
if torch is None or not torch.cuda.is_available():
|
| 262 |
+
return pipeline
|
| 263 |
+
candidate_model = getattr(pipeline, "model", None)
|
| 264 |
+
try:
|
| 265 |
+
if hasattr(pipeline, "to"):
|
| 266 |
+
pipeline = pipeline.to("cuda")
|
| 267 |
+
elif candidate_model is not None:
|
| 268 |
+
candidate_model = candidate_model.to("cuda")
|
| 269 |
+
if hasattr(pipeline, "model"):
|
| 270 |
+
pipeline.model = candidate_model
|
| 271 |
+
else:
|
| 272 |
+
raise RuntimeError("pipeline has no move target.")
|
| 273 |
+
return pipeline
|
| 274 |
+
except Exception as exc:
|
| 275 |
+
raise RuntimeError(
|
| 276 |
+
f"{context}: {model_id} failed to move pipeline to CUDA ({type(exc).__name__}: {exc}). "
|
| 277 |
+
"If you intentionally allow CPU execution, set ALLOW_CPU_FALLBACK=1."
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
|
| 281 |
def _inference_torch_kwargs_for_model(strict_cuda: bool = False) -> Tuple[dict, list]:
|
| 282 |
kwargs_priority = []
|
| 283 |
dtype = _inference_dtype()
|
|
|
|
| 775 |
try:
|
| 776 |
candidate_pipeline = hf_pipeline(candidate_task, **cleaned_kwargs)
|
| 777 |
if strict_cuda:
|
| 778 |
+
candidate_pipeline = _move_pipeline_to_cuda(
|
| 779 |
+
candidate_pipeline,
|
| 780 |
+
model_id,
|
| 781 |
+
f"pipeline load for {candidate_task}",
|
| 782 |
+
)
|
| 783 |
candidate_model = getattr(candidate_pipeline, "model", None)
|
| 784 |
if candidate_model is not None and torch is not None and torch.cuda.is_available():
|
| 785 |
try:
|
|
|
|
| 1109 |
|
| 1110 |
if pipeline is not None:
|
| 1111 |
try:
|
| 1112 |
+
if torch is not None and torch.cuda.is_available():
|
| 1113 |
+
pipeline = _move_pipeline_to_cuda(
|
| 1114 |
+
pipeline,
|
| 1115 |
+
model_id,
|
| 1116 |
+
"pipeline execution",
|
| 1117 |
+
)
|
| 1118 |
if _strict_cuda_required():
|
| 1119 |
_assert_model_on_cuda(getattr(pipeline, "model", None), model_id, "pipeline execution")
|
| 1120 |
pipeline_model = getattr(pipeline, "model", None)
|
|
|
|
| 1270 |
prompt = entry.get("prompt", DEFAULT_OCR_PROMPT)
|
| 1271 |
params = sanitize_generation_params(entry.get("parameters", {}))
|
| 1272 |
notes = entry.get("notes", "")
|
| 1273 |
+
runtime = _get_runtime_profile()
|
| 1274 |
+
runtime_tag = f"runtime: {_inference_device_label()} | provider: {runtime.get('provider')}"
|
| 1275 |
+
notes = f"{notes} [{runtime_tag}]" if notes else runtime_tag
|
| 1276 |
start = time.perf_counter()
|
| 1277 |
output = ""
|
| 1278 |
|
|
|
|
| 1332 |
|
| 1333 |
if torch.cuda.is_available():
|
| 1334 |
profile["has_cuda"] = True
|
| 1335 |
+
if not profile["provider"] or profile["provider"] == "cpu":
|
| 1336 |
+
profile["provider"] = "cuda"
|
| 1337 |
props = torch.cuda.get_device_properties(0)
|
| 1338 |
profile["gpu_name"] = props.name
|
| 1339 |
profile["gpu_vram_gb"] = round(props.total_memory / (1024 ** 3), 1)
|
|
|
|
| 1346 |
profile["gpu_free_vram_gb"] = round(free_approx / (1024 ** 3), 1)
|
| 1347 |
profile["gpu_reserved_vram_gb"] = round(torch.cuda.memory_reserved(0) / (1024 ** 3), 1)
|
| 1348 |
profile["gpu_allocated_vram_gb"] = round(torch.cuda.memory_allocated(0) / (1024 ** 3), 1)
|
| 1349 |
+
provider = str(profile["provider"] or "").lower()
|
| 1350 |
+
normalized_name = str(props.name or "").lower()
|
| 1351 |
+
if "zero" in provider or "a10g" in normalized_name or "l4" in normalized_name:
|
| 1352 |
profile["provider"] = "zero_gpu"
|
| 1353 |
except Exception:
|
| 1354 |
pass
|
|
|
|
| 1381 |
f"cuda_built={runtime.get('torch_cuda_built')}"
|
| 1382 |
)
|
| 1383 |
if runtime.get("has_cuda"):
|
| 1384 |
+
provider = runtime.get("provider")
|
| 1385 |
+
if str(provider).lower() == "cpu":
|
| 1386 |
+
provider = "cuda"
|
| 1387 |
+
runtime["provider"] = provider
|
| 1388 |
print(
|
| 1389 |
"[startup] Compute backend: "
|
| 1390 |
f"{runtime.get('provider')} 路 {runtime.get('gpu_name')} 路 total {runtime.get('gpu_vram_gb')}GB 路 "
|