Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
C
coderai
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
coderai
Commits
a83749bf
Commit
a83749bf
authored
May 06, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: default whisper-server builder fields
parent
ee45a78c
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
120 additions
and
27 deletions
+120
-27
routes.py
codai/admin/routes.py
+23
-2
test_whisper_server_local_models.py
tests/test_whisper_server_local_models.py
+97
-25
No files found.
codai/admin/routes.py
View file @
a83749bf
...
...
@@ -16,6 +16,8 @@
"""Admin dashboard routes."""
from
pathlib
import
Path
import
re
import
shutil
from
typing
import
Optional
from
fastapi
import
APIRouter
,
Request
,
Response
,
Form
,
HTTPException
,
Depends
...
...
@@ -54,6 +56,25 @@ def set_config_manager(mgr):
config_manager
=
mgr
def
_next_whisper_server_model_id
(
audio_models
)
->
str
:
used_suffixes
=
set
()
for
model
in
audio_models
or
[]:
if
not
isinstance
(
model
,
dict
)
or
model
.
get
(
"backend"
)
!=
"whisper-server"
:
continue
match
=
re
.
fullmatch
(
r"whisper(\d+)"
,
str
(
model
.
get
(
"id"
)
or
""
)
.
strip
())
if
match
:
used_suffixes
.
add
(
int
(
match
.
group
(
1
)))
suffix
=
0
while
suffix
in
used_suffixes
:
suffix
+=
1
return
f
"whisper{suffix}"
def
_default_whisper_server_path
()
->
str
:
return
shutil
.
which
(
"whisper-server"
)
or
"/usr/local/bin/whisper-server"
def
get_current_user
(
request
:
Request
)
->
Optional
[
str
]:
"""Get the current logged-in user from session cookie."""
if
session_manager
is
None
:
...
...
@@ -1257,10 +1278,10 @@ async def api_model_configure(request: Request, username: str = Depends(require_
if
data
.
get
(
"backend"
)
==
"whisper-server"
:
model_id
=
(
data
.
get
(
"model_id"
)
or
""
)
.
strip
()
if
not
model_id
:
raise
HTTPException
(
status_code
=
400
,
detail
=
"model_id is required"
)
model_id
=
_next_whisper_server_model_id
(
config_manager
.
models_data
.
get
(
"audio_models"
,
[])
)
server_path
=
(
data
.
get
(
"server_path"
)
or
""
)
.
strip
()
if
not
server_path
:
raise
HTTPException
(
status_code
=
400
,
detail
=
"server_path is required"
)
server_path
=
_default_whisper_server_path
(
)
model_source
=
(
data
.
get
(
"model_source"
)
or
"cached-gguf"
)
.
strip
()
or
"cached-gguf"
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"
)
...
...
tests/test_whisper_server_local_models.py
View file @
a83749bf
...
...
@@ -2,7 +2,7 @@ from pathlib import Path
from
types
import
SimpleNamespace
import
pytest
from
fastapi
import
HTTPException
from
fastapi
import
FastAPI
,
HTTPException
from
fastapi.testclient
import
TestClient
...
...
@@ -49,15 +49,19 @@ def _build_config(tmp_path):
return
cfg
def
_build_admin_test_client
(
routes
):
app
=
FastAPI
()
app
.
include_router
(
routes
.
router
)
app
.
dependency_overrides
[
routes
.
require_admin
]
=
lambda
:
"admin"
return
app
,
TestClient
(
app
)
def
test_model_configure_persists_whisper_server_audio_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
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
@@ -94,7 +98,6 @@ def test_model_configure_persists_whisper_server_audio_model(monkeypatch, tmp_pa
def
test_model_configure_rejects_duplicate_whisper_server_model_id
(
monkeypatch
,
tmp_path
):
from
codai.admin
import
routes
from
codai.api.app
import
app
cfg
=
_build_config
(
tmp_path
)
cfg
.
models_data
[
"audio_models"
]
=
[
...
...
@@ -109,9 +112,7 @@ def test_model_configure_rejects_duplicate_whisper_server_model_id(monkeypatch,
}
]
monkeypatch
.
setattr
(
routes
,
"config_manager"
,
cfg
,
raising
=
False
)
app
.
dependency_overrides
[
routes
.
require_admin
]
=
lambda
:
"admin"
client
=
TestClient
(
app
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
@@ -132,15 +133,95 @@ def test_model_configure_rejects_duplicate_whisper_server_model_id(monkeypatch,
app
.
dependency_overrides
.
clear
()
def
test_model_configure_
accepts_cached_gguf_whisper_server_model
(
monkeypatch
,
tmp_path
):
def
test_model_configure_
defaults_missing_whisper_server_model_id_to_whisper0
(
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"
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
"model_id"
:
""
,
"model_type"
:
"audio_models"
,
"backend"
:
"whisper-server"
,
"server_path"
:
"/usr/local/bin/whisper-server"
,
"model_path"
:
"/models/ggml-base.bin"
,
"port"
:
8744
,
"gpu_device"
:
0
,
"load_mode"
:
"on-request"
,
},
)
client
=
TestClient
(
app
)
assert
response
.
status_code
==
200
assert
cfg
.
models_data
[
"audio_models"
][
0
][
"id"
]
==
"whisper0"
app
.
dependency_overrides
.
clear
()
def
test_model_configure_defaults_missing_whisper_server_model_id_to_smallest_free_suffix
(
monkeypatch
,
tmp_path
):
from
codai.admin
import
routes
cfg
=
_build_config
(
tmp_path
)
cfg
.
models_data
[
"audio_models"
]
=
[
{
"id"
:
"whisper0"
,
"backend"
:
"whisper-server"
},
{
"id"
:
"whisper1"
,
"backend"
:
"whisper-server"
},
{
"id"
:
"whisper3"
,
"backend"
:
"whisper-server"
},
]
monkeypatch
.
setattr
(
routes
,
"config_manager"
,
cfg
,
raising
=
False
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
"model_type"
:
"audio_models"
,
"backend"
:
"whisper-server"
,
"server_path"
:
"/usr/local/bin/whisper-server"
,
"model_path"
:
"/models/ggml-small.bin"
,
"port"
:
8745
,
"gpu_device"
:
1
,
"load_mode"
:
"load"
,
},
)
assert
response
.
status_code
==
200
assert
cfg
.
models_data
[
"audio_models"
][
-
1
][
"id"
]
==
"whisper2"
app
.
dependency_overrides
.
clear
()
def
test_model_configure_defaults_missing_whisper_server_path_to_usr_local_bin
(
monkeypatch
,
tmp_path
):
from
codai.admin
import
routes
cfg
=
_build_config
(
tmp_path
)
monkeypatch
.
setattr
(
routes
,
"config_manager"
,
cfg
,
raising
=
False
)
monkeypatch
.
setattr
(
routes
.
shutil
,
"which"
,
lambda
_
:
None
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
"model_id"
:
"whisper-vulkan-base"
,
"model_type"
:
"audio_models"
,
"backend"
:
"whisper-server"
,
"server_path"
:
""
,
"model_path"
:
"/models/ggml-base.bin"
,
"port"
:
8744
,
"gpu_device"
:
0
,
"load_mode"
:
"on-request"
,
},
)
assert
response
.
status_code
==
200
assert
cfg
.
models_data
[
"audio_models"
][
0
][
"server_path"
]
==
"/usr/local/bin/whisper-server"
app
.
dependency_overrides
.
clear
()
def
test_model_configure_accepts_cached_gguf_whisper_server_model
(
monkeypatch
,
tmp_path
):
from
codai.admin
import
routes
cfg
=
_build_config
(
tmp_path
)
monkeypatch
.
setattr
(
routes
,
"config_manager"
,
cfg
,
raising
=
False
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
@@ -176,13 +257,10 @@ def test_model_configure_accepts_cached_gguf_whisper_server_model(monkeypatch, t
def
test_model_configure_defaults_missing_whisper_server_model_source_to_cached_gguf
(
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
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
@@ -217,13 +295,10 @@ def test_model_configure_defaults_missing_whisper_server_model_source_to_cached_
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
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
@@ -247,13 +322,10 @@ def test_model_configure_rejects_cached_gguf_whisper_server_without_model_path(m
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
)
app
,
client
=
_build_admin_test_client
(
routes
)
response
=
client
.
post
(
"/admin/api/model-configure"
,
json
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment