feat: link downloaded gguf files to whisper-server models

parent 0a18f0f1
...@@ -202,7 +202,11 @@ async def admin_dashboard(request: Request, username: str = Depends(require_auth ...@@ -202,7 +202,11 @@ async def admin_dashboard(request: Request, username: str = Depends(require_auth
@router.get("/admin/models", response_class=HTMLResponse) @router.get("/admin/models", response_class=HTMLResponse)
async def models_page(request: Request, username: str = Depends(require_admin)): async def models_page(request: Request, username: str = Depends(require_admin)):
return templates.TemplateResponse(request, "models.html", {"username": username, "is_admin": True}) return templates.TemplateResponse(request, "models.html", {
"username": username,
"is_admin": True,
"whisper_server_default_source": "cached-gguf",
})
@router.get("/admin/tokens", response_class=HTMLResponse) @router.get("/admin/tokens", response_class=HTMLResponse)
...@@ -1261,7 +1265,7 @@ async def api_model_configure(request: Request, username: str = Depends(require_ ...@@ -1261,7 +1265,7 @@ 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" model_source = (data.get("model_source") or "cached-gguf").strip() or "cached-gguf"
if model_source not in {"cached-gguf", "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") raise HTTPException(status_code=400, detail="model_source must be one of: cached-gguf, manual-path")
model_path = (data.get("model_path") or "").strip() model_path = (data.get("model_path") or "").strip()
......
...@@ -102,8 +102,8 @@ ...@@ -102,8 +102,8 @@
<input id="ws-model-id" class="form-input" placeholder="whisper-vulkan-base"> <input id="ws-model-id" class="form-input" placeholder="whisper-vulkan-base">
<input id="ws-server-path" class="form-input" placeholder="/usr/local/bin/whisper-server"> <input id="ws-server-path" class="form-input" placeholder="/usr/local/bin/whisper-server">
<select id="ws-model-source" class="form-input" onchange="toggleWhisperModelSource()"> <select id="ws-model-source" class="form-input" onchange="toggleWhisperModelSource()">
<option value="cached-gguf">Downloaded GGUF</option> <option value="cached-gguf" {% if whisper_server_default_source == 'cached-gguf' %}selected{% endif %}>Downloaded GGUF</option>
<option value="manual-path">Manual path</option> <option value="manual-path" {% if whisper_server_default_source == 'manual-path' %}selected{% endif %}>Manual path</option>
</select> </select>
<select id="ws-gguf-select" class="form-input"> <select id="ws-gguf-select" class="form-input">
<option value="">Select downloaded GGUF</option> <option value="">Select downloaded GGUF</option>
...@@ -1158,6 +1158,13 @@ function toggleWhisperModelSource(){ ...@@ -1158,6 +1158,13 @@ function toggleWhisperModelSource(){
modelPath.style.display = useCached ? 'none' : ''; modelPath.style.display = useCached ? 'none' : '';
} }
function getWhisperServerModelPath(){
const modelSource = document.getElementById('ws-model-source').value;
return (modelSource === 'cached-gguf'
? document.getElementById('ws-gguf-select').value
: document.getElementById('ws-model-path').value.trim()) || null;
}
let _loadedKeys = new Set(); let _loadedKeys = new Set();
async function refreshLoadedStatus(){ async function refreshLoadedStatus(){
...@@ -1378,9 +1385,7 @@ async function addWhisperServerModel(){ ...@@ -1378,9 +1385,7 @@ async function addWhisperServerModel(){
backend: 'whisper-server', backend: 'whisper-server',
model_source: modelSource, model_source: modelSource,
server_path: document.getElementById('ws-server-path').value.trim(), server_path: document.getElementById('ws-server-path').value.trim(),
model_path: (modelSource === 'cached-gguf' model_path: getWhisperServerModelPath(),
? document.getElementById('ws-gguf-select').value
: document.getElementById('ws-model-path').value.trim()) || null,
port: parseInt(document.getElementById('ws-port').value, 10) || 8744, port: parseInt(document.getElementById('ws-port').value, 10) || 8744,
gpu_device: parseInt(document.getElementById('ws-gpu-device').value, 10) || 0, gpu_device: parseInt(document.getElementById('ws-gpu-device').value, 10) || 0,
load_mode: document.getElementById('ws-load-mode').value, load_mode: document.getElementById('ws-load-mode').value,
......
...@@ -436,6 +436,16 @@ def test_models_template_defines_whisper_server_gguf_prefill_helpers(): ...@@ -436,6 +436,16 @@ def test_models_template_defines_whisper_server_gguf_prefill_helpers():
assert "prefillWhisperServerFromGguf(path)" in template assert "prefillWhisperServerFromGguf(path)" in template
def test_models_template_submits_whisper_server_source_and_resolved_gguf_path():
template = Path("codai/admin/templates/models.html").read_text()
assert "function getWhisperServerModelPath()" in template
assert "const sourceSelect = document.getElementById('ws-model-source');" in template
assert "const ggufSelect = document.getElementById('ws-gguf-select');" in template
assert "model_source: modelSource," in template
assert "model_path: getWhisperServerModelPath()," in template
def test_models_template_adds_use_with_whisper_server_gguf_action(): def test_models_template_adds_use_with_whisper_server_gguf_action():
template = Path("codai/admin/templates/models.html").read_text() template = Path("codai/admin/templates/models.html").read_text()
......
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