Transcription: dwindle model choice to Whisper Base + Whisper Large v3

Registry now lists exactly two models instead of five:
- 'Whisper Base' — names the actual bundled model (was 'Base (default)').
- 'Whisper Large v3' — kept; honest copy on size/speed/RAM.
tiny/small/medium removed from the registry (validate_model_name now
rejects them; existing rows keep their saved model — all current data
is 'base', still valid).
Detail screen shows the model that WILL run by real display name
('Whisper Base (default)') instead of 'Use default (base)'; the picker
lists the two models with the default marked inline.
Backend 78 passed/1 skipped; app 34/34; engine hot-reloaded clean.
This commit is contained in:
avi 2026-09-15 07:24:57 -05:00
commit 087e8386f5
4 changed files with 43 additions and 64 deletions

View file

@ -59,16 +59,16 @@ async def upload_recording(client, token, client_id, session_model=None, finaliz
return r
async def test_models_endpoint_lists_five(client):
async def test_models_endpoint_lists_two(client):
token = await user_tokens(client)
r = await client.get("/api/v1/models", headers={"Authorization": f"Bearer {token}"})
assert r.status_code == 200, r.text
body = r.json()
assert body["default_model"] == "base"
assert [m["name"] for m in body["models"]] == ["tiny", "base", "small", "medium", "large-v3"]
assert [m["name"] for m in body["models"]] == ["base", "large-v3"]
base = next(m for m in body["models"] if m["name"] == "base")
assert base["is_default"] is True
assert "ordinary computers" in base["description"]
assert "bundled model" in base["description"]
for m in body["models"]:
assert isinstance(m["downloaded"], bool)
assert isinstance(m["available"], bool)
@ -79,32 +79,32 @@ async def test_default_get_put_validation(client):
h = {"Authorization": f"Bearer {token}"}
r = await client.get("/api/v1/models/default", headers=h)
assert r.json() == {"default_model": "base"}
r = await client.put("/api/v1/models/default", json={"model": "small"}, headers=h)
r = await client.put("/api/v1/models/default", json={"model": "large-v3"}, headers=h)
assert r.status_code == 200, r.text
assert r.json() == {"default_model": "small"}
assert r.json() == {"default_model": "large-v3"}
r = await client.put("/api/v1/models/default", json={"model": "xxl-turbo"}, headers=h)
assert r.status_code == 422
assert "Supported models" in r.text
# rejected change did not stick
r = await client.get("/api/v1/models/default", headers=h)
assert r.json() == {"default_model": "small"}
assert r.json() == {"default_model": "large-v3"}
async def test_finalize_override_and_default_history(client):
token = await user_tokens(client)
h = {"Authorization": f"Bearer {token}"}
r = await upload_recording(client, token, "m-override-1", finalize_model="small")
r = await upload_recording(client, token, "m-override-1", finalize_model="large-v3")
assert r.status_code == 201, r.text
assert r.json()["transcription_model"] == "small"
assert r.json()["transcription_model"] == "large-v3"
r = await upload_recording(client, token, "m-default-1")
assert r.json()["transcription_model"] == "base"
# Changing the default affects future rows only.
r = await client.put("/api/v1/models/default", json={"model": "tiny"}, headers=h)
r = await client.put("/api/v1/models/default", json={"model": "large-v3"}, headers=h)
assert r.status_code == 200
r = await upload_recording(client, token, "m-default-2")
assert r.json()["transcription_model"] == "tiny"
assert r.json()["transcription_model"] == "large-v3"
async with db_session._session_factory() as s:
got = dict((await s.execute(
@ -112,19 +112,20 @@ async def test_finalize_override_and_default_history(client):
.where(Recording.client_recording_id.in_(
["m-override-1", "m-default-1", "m-default-2"])))
).all())
assert got == {"m-override-1": "small", "m-default-1": "base", "m-default-2": "tiny"}
assert got == {"m-override-1": "large-v3", "m-default-1": "base",
"m-default-2": "large-v3"}
async def test_session_override_and_finalize_wins(client):
token = await user_tokens(client)
r = await upload_recording(client, token, "m-sess-1", session_model="small")
r = await upload_recording(client, token, "m-sess-1", session_model="large-v3")
assert r.status_code == 201, r.text
assert r.json()["transcription_model"] == "small"
assert r.json()["transcription_model"] == "large-v3"
r = await upload_recording(client, token, "m-sess-2", session_model="small",
finalize_model="tiny")
r = await upload_recording(client, token, "m-sess-2", session_model="large-v3",
finalize_model="base")
assert r.status_code == 201, r.text
assert r.json()["transcription_model"] == "tiny"
assert r.json()["transcription_model"] == "base"
async def test_finalize_invalid_override_rejected(client):
@ -175,15 +176,15 @@ async def _run_with_spy(monkeypatch, recording_id):
async def test_worker_uses_saved_model(client, monkeypatch):
token = await user_tokens(client)
rec = (await upload_recording(client, token, "m-work-1", finalize_model="small")).json()
rec = (await upload_recording(client, token, "m-work-1", finalize_model="large-v3")).json()
await _run_with_spy(monkeypatch, rec["id"])
# Last construction is the worker rebuild from the saved model.
assert SpyTranscriber.seen_models[-1] == "small"
assert SpyTranscriber.seen_models[-1] == "large-v3"
h = {"Authorization": f"Bearer {token}"}
r = await client.get(f"/api/v1/recordings/{rec['id']}/transcript", headers=h)
assert r.status_code == 200
assert r.json()["model"] == "small"
assert r.json()["model"] == "large-v3"
r = await client.get(f"/api/v1/recordings/{rec['id']}/jobs", headers=h)
job = next(j for j in r.json() if j["job_type"] == "transcribe")
@ -197,7 +198,7 @@ async def test_worker_keeps_history_after_default_change(client, monkeypatch):
h = {"Authorization": f"Bearer {token}"}
rec = (await upload_recording(client, token, "m-work-2")).json()
assert rec["transcription_model"] == "base"
r = await client.put("/api/v1/models/default", json={"model": "tiny"}, headers=h)
r = await client.put("/api/v1/models/default", json={"model": "large-v3"}, headers=h)
assert r.status_code == 200
await _run_with_spy(monkeypatch, rec["id"])
assert SpyTranscriber.seen_models[-1] == "base"
@ -229,15 +230,15 @@ async def test_unavailable_model_fails_with_instructions(client, monkeypatch):
async def test_reupload_explicit_override_updates_model(client):
token = await user_tokens(client)
r = await upload_recording(client, token, "m-reup-1", finalize_model="small")
assert r.json()["transcription_model"] == "small"
r = await upload_recording(client, token, "m-reup-1", finalize_model="large-v3")
assert r.json()["transcription_model"] == "large-v3"
# Same client id, new explicit choice: model history moves with it.
r = await upload_recording(client, token, "m-reup-1", finalize_model="tiny")
r = await upload_recording(client, token, "m-reup-1", finalize_model="base")
assert r.status_code == 201, r.text
assert r.json()["transcription_model"] == "tiny"
assert r.json()["transcription_model"] == "base"
# Same client id, no choice: history untouched.
r = await upload_recording(client, token, "m-reup-1")
assert r.json()["transcription_model"] == "tiny"
assert r.json()["transcription_model"] == "base"
async def test_models_need_auth(client):