feat: validate whisper-server gguf model sources

parent 623f273f
...@@ -1261,6 +1261,12 @@ async def api_model_configure(request: Request, username: str = Depends(require_ ...@@ -1261,6 +1261,12 @@ async def api_model_configure(request: Request, username: str = Depends(require_
server_path = (data.get("server_path") or "").strip() server_path = (data.get("server_path") or "").strip()
if not server_path: if not server_path:
raise HTTPException(status_code=400, detail="server_path is required") raise HTTPException(status_code=400, detail="server_path is required")
model_source = (data.get("model_source") or "manual-path").strip() or "manual-path"
if model_source not in {"cached-gguf", "manual-path"}:
raise HTTPException(status_code=400, detail="model_source must be one of: cached-gguf, manual-path")
model_path = (data.get("model_path") or "").strip()
if not model_path:
raise HTTPException(status_code=400, detail=f"model_path is required for {model_source}")
port = int(data.get("port", 8744)) port = int(data.get("port", 8744))
if port < 1 or port > 65535: if port < 1 or port > 65535:
raise HTTPException(status_code=400, detail="port must be between 1 and 65535") raise HTTPException(status_code=400, detail="port must be between 1 and 65535")
...@@ -1274,7 +1280,7 @@ async def api_model_configure(request: Request, username: str = Depends(require_ ...@@ -1274,7 +1280,7 @@ async def api_model_configure(request: Request, username: str = Depends(require_
"id": model_id, "id": model_id,
"backend": "whisper-server", "backend": "whisper-server",
"server_path": server_path, "server_path": server_path,
"model_path": (data.get("model_path") or "").strip() or None, "model_path": model_path,
"port": port, "port": port,
"gpu_device": gpu_device, "gpu_device": gpu_device,
"load_mode": data.get("load_mode", "on-request"), "load_mode": data.get("load_mode", "on-request"),
......
...@@ -132,6 +132,108 @@ def test_model_configure_rejects_duplicate_whisper_server_model_id(monkeypatch, ...@@ -132,6 +132,108 @@ def test_model_configure_rejects_duplicate_whisper_server_model_id(monkeypatch,
app.dependency_overrides.clear() app.dependency_overrides.clear()
def test_model_configure_accepts_cached_gguf_whisper_server_model(monkeypatch, tmp_path):
from codai.admin import routes
from codai.api.app import app
cfg = _build_config(tmp_path)
monkeypatch.setattr(routes, "config_manager", cfg, raising=False)
app.dependency_overrides[routes.require_admin] = lambda: "admin"
client = TestClient(app)
response = client.post(
"/admin/api/model-configure",
json={
"model_id": "whisper-vulkan-base",
"model_type": "audio_models",
"backend": "whisper-server",
"model_source": "cached-gguf",
"server_path": "/usr/local/bin/whisper-server",
"model_path": "/models/base.en.gguf",
"port": 8744,
"gpu_device": 0,
"load_mode": "on-request",
},
)
assert response.status_code == 200
assert cfg.models_data["audio_models"] == [
{
"id": "whisper-vulkan-base",
"backend": "whisper-server",
"server_path": "/usr/local/bin/whisper-server",
"model_path": "/models/base.en.gguf",
"port": 8744,
"gpu_device": 0,
"load_mode": "on-request",
"model_type": "audio_models",
"model_types": ["audio_models"],
}
]
app.dependency_overrides.clear()
def test_model_configure_rejects_cached_gguf_whisper_server_without_model_path(monkeypatch, tmp_path):
from codai.admin import routes
from codai.api.app import app
cfg = _build_config(tmp_path)
monkeypatch.setattr(routes, "config_manager", cfg, raising=False)
app.dependency_overrides[routes.require_admin] = lambda: "admin"
client = TestClient(app)
response = client.post(
"/admin/api/model-configure",
json={
"model_id": "whisper-vulkan-base",
"model_type": "audio_models",
"backend": "whisper-server",
"model_source": "cached-gguf",
"server_path": "/usr/local/bin/whisper-server",
"model_path": "",
"port": 8744,
"gpu_device": 0,
"load_mode": "on-request",
},
)
assert response.status_code == 400
assert response.json()["detail"] == "model_path is required for cached-gguf"
app.dependency_overrides.clear()
def test_model_configure_rejects_manual_path_whisper_server_without_model_path(monkeypatch, tmp_path):
from codai.admin import routes
from codai.api.app import app
cfg = _build_config(tmp_path)
monkeypatch.setattr(routes, "config_manager", cfg, raising=False)
app.dependency_overrides[routes.require_admin] = lambda: "admin"
client = TestClient(app)
response = client.post(
"/admin/api/model-configure",
json={
"model_id": "whisper-vulkan-base",
"model_type": "audio_models",
"backend": "whisper-server",
"model_source": "manual-path",
"server_path": "/usr/local/bin/whisper-server",
"model_path": "",
"port": 8744,
"gpu_device": 0,
"load_mode": "on-request",
},
)
assert response.status_code == 400
assert response.json()["detail"] == "model_path is required for manual-path"
app.dependency_overrides.clear()
def test_model_load_and_unload_manage_whisper_server_runtime(monkeypatch): def test_model_load_and_unload_manage_whisper_server_runtime(monkeypatch):
from codai.admin import routes from codai.admin import routes
from codai.api.app import app from codai.api.app import app
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment