mirror of
https://github.com/OLmatter/glm-coding-helper.git
synced 2026-10-06 15:13:13 +08:00
fix: fallback from broken GPU OCR in auto mode
This commit is contained in:
@@ -33,10 +33,11 @@ function Has-NvidiaGpu {
|
||||
return $LASTEXITCODE -eq 0
|
||||
}
|
||||
|
||||
$Selected = $Target
|
||||
if ($Selected -eq "auto") {
|
||||
$Selected = if (Has-NvidiaGpu) { "gpu" } else { "cpu" }
|
||||
$InstallTarget = $Target
|
||||
if ($InstallTarget -eq "auto") {
|
||||
$InstallTarget = if (Has-NvidiaGpu) { "gpu" } else { "cpu" }
|
||||
}
|
||||
$StartMode = if ($Target -eq "auto") { "auto" } else { $InstallTarget }
|
||||
|
||||
$CpuPython = Join-Path $Root ".venv_paddle\Scripts\python.exe"
|
||||
$GpuPython = Join-Path $Root ".venv_paddle_gpu\Scripts\python.exe"
|
||||
@@ -44,7 +45,7 @@ $ImportCode = "import ultralytics, paddleocr, paddlex, cv2, PIL, numpy"
|
||||
|
||||
$Ready = $false
|
||||
$SelectedPython = ""
|
||||
if ($Selected -eq "gpu") {
|
||||
if ($InstallTarget -eq "gpu") {
|
||||
$SelectedPython = $GpuPython
|
||||
$Ready = Test-PythonImports $GpuPython $ImportCode
|
||||
} else {
|
||||
@@ -53,8 +54,8 @@ if ($Selected -eq "gpu") {
|
||||
}
|
||||
|
||||
if (-not $Ready) {
|
||||
Write-Host "Backend environment is missing or incomplete. Installing $Selected environment..."
|
||||
$argsList = @("-Target", $Selected)
|
||||
Write-Host "Backend environment is missing or incomplete. Installing $InstallTarget environment..."
|
||||
$argsList = @("-Target", $InstallTarget)
|
||||
if ($SelectedPython -and (Test-Path $SelectedPython)) {
|
||||
Write-Host "Existing backend environment failed import checks. Recreating it..."
|
||||
$argsList += "-Recreate"
|
||||
@@ -66,5 +67,15 @@ if (-not $Ready) {
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File "scripts\bootstrap_windows.ps1" @argsList
|
||||
}
|
||||
|
||||
Write-Host "Starting backend in $Selected mode on port $Port..."
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File "scripts\start_backend.ps1" -Mode $Selected -Port $Port
|
||||
if ($Target -eq "auto" -and $InstallTarget -eq "gpu" -and -not (Test-PythonImports $CpuPython $ImportCode)) {
|
||||
Write-Host "CPU fallback environment is missing. Installing CPU environment for auto fallback..."
|
||||
$fallbackArgs = @("-Target", "cpu")
|
||||
foreach ($arg in $PipArg) {
|
||||
$fallbackArgs += "-PipArg"
|
||||
$fallbackArgs += $arg
|
||||
}
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File "scripts\bootstrap_windows.ps1" @fallbackArgs
|
||||
}
|
||||
|
||||
Write-Host "Starting backend in $StartMode mode on port $Port..."
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File "scripts\start_backend.ps1" -Mode $StartMode -Port $Port
|
||||
|
||||
@@ -74,6 +74,20 @@ def smoke_test(py: Path, mode: str) -> None:
|
||||
"print('cuda_count=', paddle.device.cuda.device_count() if paddle.is_compiled_with_cuda() else 0)"
|
||||
)
|
||||
run([str(py), "-c", gpu_code])
|
||||
gpu_ocr_code = (
|
||||
"import os; "
|
||||
f"os.environ['HOME'] = {str(ROOT / '.paddle_home_gpu')!r}; "
|
||||
f"os.environ['USERPROFILE'] = {str(ROOT / '.paddle_home_gpu')!r}; "
|
||||
f"os.environ['PADDLE_HOME'] = {str(ROOT / '.paddle_home_gpu' / '.cache' / 'paddle')!r}; "
|
||||
f"os.environ['PADDLE_PDX_CACHE_HOME'] = {str(ROOT / '.paddlex_cache_gpu')!r}; "
|
||||
"os.environ.setdefault('PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK', 'True'); "
|
||||
"from paddleocr import TextRecognition; "
|
||||
"r = TextRecognition(model_name='PP-OCRv5_server_rec', device='gpu:0', engine='paddle_dynamic'); "
|
||||
"close = getattr(r, 'close', None); "
|
||||
"close() if callable(close) else None; "
|
||||
"print('gpu ocr ok')"
|
||||
)
|
||||
run([str(py), "-c", gpu_ocr_code])
|
||||
|
||||
|
||||
def check_assets() -> None:
|
||||
|
||||
@@ -74,7 +74,21 @@ def _venv_python(name: str) -> Path:
|
||||
return ROOT / name / "bin" / "python"
|
||||
|
||||
|
||||
def detect_gpu(timeout: float = 8.0) -> tuple[bool, str]:
|
||||
def _gpu_probe_env() -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
paddle_home = ROOT / ".paddle_home_gpu"
|
||||
paddlex_cache = ROOT / ".paddlex_cache_gpu"
|
||||
env["HOME"] = str(paddle_home)
|
||||
env["USERPROFILE"] = str(paddle_home)
|
||||
env["PADDLE_HOME"] = str(paddle_home / ".cache" / "paddle")
|
||||
env["PADDLE_PDX_CACHE_HOME"] = str(paddlex_cache)
|
||||
env.setdefault("PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK", "True")
|
||||
env.setdefault("PYTHONUTF8", "1")
|
||||
env.setdefault("PYTHONIOENCODING", "utf-8")
|
||||
return env
|
||||
|
||||
|
||||
def detect_gpu(timeout: float = 45.0) -> tuple[bool, str]:
|
||||
if parse_bool(os.environ.get("CNCAPTCHA_SKIP_GPU_DETECT"), False):
|
||||
return False, "skipped by CNCAPTCHA_SKIP_GPU_DETECT"
|
||||
|
||||
@@ -82,6 +96,8 @@ def detect_gpu(timeout: float = 8.0) -> tuple[bool, str]:
|
||||
if not gpu_python.exists():
|
||||
return False, f"missing {gpu_python}"
|
||||
|
||||
env = _gpu_probe_env()
|
||||
|
||||
probe = (
|
||||
"import paddle; "
|
||||
"ok = paddle.is_compiled_with_cuda(); "
|
||||
@@ -92,20 +108,60 @@ def detect_gpu(timeout: float = 8.0) -> tuple[bool, str]:
|
||||
proc = subprocess.run(
|
||||
[str(gpu_python), "-c", probe],
|
||||
cwd=str(ROOT),
|
||||
env=env,
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=timeout,
|
||||
timeout=min(timeout, 10.0),
|
||||
check=False,
|
||||
)
|
||||
except Exception as exc:
|
||||
return False, f"probe failed: {exc}"
|
||||
|
||||
output = (proc.stdout or "").strip()
|
||||
if proc.returncode == 0 and output.startswith("ok"):
|
||||
if not (proc.returncode == 0 and output.startswith("ok")):
|
||||
reason = output or (proc.stderr or "").strip().splitlines()[-1:] or [f"returncode={proc.returncode}"]
|
||||
return False, str(reason[0])
|
||||
|
||||
if not parse_bool(os.environ.get("CNCAPTCHA_STRICT_GPU_DETECT"), True):
|
||||
return True, output
|
||||
reason = output or (proc.stderr or "").strip().splitlines()[-1:] or [f"returncode={proc.returncode}"]
|
||||
return False, str(reason[0])
|
||||
|
||||
model_name = os.environ.get("CNCAPTCHA_GPU_OCR_MODEL", "PP-OCRv5_server_rec")
|
||||
device = os.environ.get("CNCAPTCHA_GPU_OCR_DEVICE", "gpu:0")
|
||||
engine = os.environ.get("CNCAPTCHA_GPU_OCR_ENGINE", "paddle_dynamic")
|
||||
ocr_probe = (
|
||||
"from paddleocr import TextRecognition; "
|
||||
f"r = TextRecognition(model_name={model_name!r}, device={device!r}, engine={engine!r}); "
|
||||
"close = getattr(r, 'close', None); "
|
||||
"close() if callable(close) else None; "
|
||||
"print('ocr_ok')"
|
||||
)
|
||||
try:
|
||||
ocr_proc = subprocess.run(
|
||||
[str(gpu_python), "-c", ocr_probe],
|
||||
cwd=str(ROOT),
|
||||
env=env,
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=timeout,
|
||||
check=False,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
return False, f"GPU OCR probe timeout after {timeout:.0f}s"
|
||||
except Exception as exc:
|
||||
return False, f"GPU OCR probe failed: {exc}"
|
||||
|
||||
if ocr_proc.returncode == 0 and "ocr_ok" in (ocr_proc.stdout or ""):
|
||||
return True, output + "; ocr_ok"
|
||||
|
||||
reason_lines = [
|
||||
line.strip()
|
||||
for line in ((ocr_proc.stderr or "") + "\n" + (ocr_proc.stdout or "")).splitlines()
|
||||
if line.strip()
|
||||
]
|
||||
reason = reason_lines[-1] if reason_lines else f"returncode={ocr_proc.returncode}"
|
||||
return False, f"GPU OCR unavailable: {reason}"
|
||||
|
||||
|
||||
def resolve_backend_config(source: str = "env") -> BackendConfig:
|
||||
|
||||
Reference in New Issue
Block a user