fix(multimodal): 冻结推理环境并隔离迟到导入错误

This commit is contained in:
2026-09-05 02:09:15 +08:00
parent 6ee6cd7d73
commit cb1c6dfcf5
8 changed files with 38 additions and 12 deletions
+6 -4
View File
@@ -69,9 +69,10 @@ def configure(request):
return request
def interpreter():
def interpreter(config=None):
from app.local_models import components
if not os.getenv("APP_MODEL_PYTHON") and configuration().device == "cuda" and components.ready():
requested_device = (config or configuration()).device
if not os.getenv("APP_MODEL_PYTHON") and requested_device == "cuda" and components.ready():
return components.ROOT / "Scripts/python.exe"
return Path(os.getenv("APP_MODEL_PYTHON", str(BACKEND_DIR / ".venv-models" / ("Scripts/python.exe" if os.name == "nt" else "bin/python"))))
@@ -160,7 +161,8 @@ class Runtime:
async def _execute(self, key, operation, payload, config, diagnostics):
if read_state(key)["status"] != "installed":
raise ProviderError("LOCAL_MODEL_NOT_INSTALLED", "请先下载本地模型。")
if not interpreter().is_file():
executable = interpreter(config)
if not executable.is_file():
raise ProviderError("LOCAL_RUNTIME_NOT_INSTALLED", "请先安装本地模型运行环境。")
from app.services.usage_service import UsageAttempt
attempt = UsageAttempt("local-models", CATALOG[key].repository, "local", operation, source="local")
@@ -170,7 +172,7 @@ class Runtime:
env = {**os.environ, "HF_HUB_OFFLINE": "1", "TRANSFORMERS_OFFLINE": "1",
"HF_HUB_DISABLE_TELEMETRY": "1", "OMP_NUM_THREADS": str(config.cpu_threads),
"PYTHONIOENCODING": "utf-8"}
args = (str(interpreter()), str(Path(__file__).with_name("worker.py")))
args = (str(executable), str(Path(__file__).with_name("worker.py")))
options = {"env": env, "limit": 16 * 1024 * 1024,
**({"creationflags": 0x08000000} if os.name == "nt" else {})}
try:
+2 -2
View File
@@ -47,7 +47,7 @@ def test_local_model_missing_is_explicit():
def test_cancel_reaps_active_model_process(monkeypatch):
import app.local_models.runtime as module
monkeypatch.setattr(module,'read_state',lambda key:{'status':'installed'})
monkeypatch.setattr(module,'interpreter',lambda:Path(sys.executable))
monkeypatch.setattr(module,'interpreter',lambda *_:Path(sys.executable))
class Input:
def write(self, value):
request = json.loads(value)
@@ -92,7 +92,7 @@ def test_subprocess_fallback_runs_and_reaps_real_worker(monkeypatch, tmp_path, c
import app.local_models.process as process_module
monkeypatch.setattr(module, 'read_state', lambda key: {'status': 'installed'})
monkeypatch.setattr(module, 'interpreter', lambda: Path(sys.executable))
monkeypatch.setattr(module, 'interpreter', lambda *_: Path(sys.executable))
worker = tmp_path / 'worker.py'
worker.write_text(
'import json,sys,time\n'
@@ -21,7 +21,7 @@ def test_cuda_retries_only_device_failures_in_reaped_process(monkeypatch, code,
from app.services.usage_service import connection
monkeypatch.setattr(module, 'configuration', lambda: module.RuntimeConfig(device='cuda'))
monkeypatch.setattr(module, 'read_state', lambda key: {'status': 'installed'})
monkeypatch.setattr(module, 'interpreter', lambda: Path(sys.executable))
monkeypatch.setattr(module, 'interpreter', lambda *_: Path(sys.executable))
events = []
class Process:
+3 -2
View File
@@ -79,7 +79,8 @@ def test_interpreter_keeps_cpu_default_and_respects_explicit_override(monkeypatc
(components.ROOT / 'ready.json').write_text('{}')
monkeypatch.setattr(runtime, 'configuration', lambda: runtime.RuntimeConfig(device='cpu'))
assert runtime.interpreter() != python
monkeypatch.setattr(runtime, 'configuration', lambda: runtime.RuntimeConfig(device='cuda'))
assert runtime.interpreter() == python
# A queued attempt keeps its frozen device even after the saved setting changes.
assert runtime.interpreter(runtime.RuntimeConfig(device='cuda')) == python
assert runtime.interpreter(runtime.RuntimeConfig(device='cpu')) != python
monkeypatch.setenv('APP_MODEL_PYTHON', 'explicit-python.exe')
assert str(runtime.interpreter()) == 'explicit-python.exe'