mirror of
https://github.com/debpalash/VoiceStudio.git
synced 2026-10-02 09:34:38 +08:00
The engine matrix (five columns, three-line rows, every chip on every row) becomes a shadcn table with three columns — Engine · Runs on · Status — and one primary action per row (Use / Install). Everything else lives in a detail panel for the selected row: GPU compatibility chips, isolation, hints and reasons, health and self-test probes, one-click install progress, setup snippet, disk usage, docs, license, the curated-model picker, and now the engine's downloadable WEIGHTS. Weights belong to their engine: every models.yaml entry names the backend ids that load it (`engines:`), the detail panel lists and installs them (EngineWeights, on the model store's install/cancel/remove flow via the extracted useModelDownloads hook), and the sherpa-onnx engine shows its dictation-model picker there. The page's "Downloaded weights" list and recommendation card are gone; only weights no engine owns (speaker diarisation) remain in a small "Other weights" list. A backend test pins the mapping: every entry has an `engines` list and every id is a real backend. - useEngineInventory: the matrix's state machines extracted verbatim (shared/local fetch, residency, health/self-test cooldowns, install poller with overlap guard + epoch, disk-usage generations, license). - Row status phrases: GPU active / CPU fallback / CPU / Available / Needs setup / Installing… / failed; routing "unavailable" never reads Ready. Group captions keep "Ready to use" / "Add more engines". - Engine titles read "Engines" (each locale's own word); backend "Model Catalogue → Engines/Models" messages and docs updated to the new structure. - Dead matrix CSS (phone-tier grid) removed; scopeReco and RecoBanner gone.
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
"""Every catalog model names the engines that load it.
|
|
|
|
The Model Catalogue lists downloadable weights UNDER their engine (the
|
|
`engines:` list in ``config/models.yaml``); a row with no owner falls into a
|
|
small "other weights" list instead. That only works if the mapping stays
|
|
complete and points at real backend ids, so this pins both: each entry
|
|
carries an explicit ``engines`` list (empty is allowed, and means "pipeline
|
|
weights no single engine owns"), and every id it names is a backend the
|
|
engines router would list for TTS or ASR.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
YAML_PATH = Path(__file__).resolve().parents[2] / "backend" / "config" / "models.yaml"
|
|
|
|
|
|
def _catalog() -> list[dict]:
|
|
with open(YAML_PATH, encoding="utf-8") as f:
|
|
data = yaml.safe_load(f)
|
|
models = data.get("models") if isinstance(data, dict) else data
|
|
assert isinstance(models, list) and models, "models.yaml has no model list"
|
|
return models
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def known_engine_ids() -> set[str]:
|
|
from services import asr_backend, tts_backend
|
|
|
|
ids = {b["id"] for b in tts_backend.list_backends(include_hidden=True)}
|
|
ids |= {b["id"] for b in asr_backend.list_backends()}
|
|
return ids
|
|
|
|
|
|
def test_every_model_declares_its_engines():
|
|
missing = [m["repo_id"] for m in _catalog() if not isinstance(m.get("engines"), list)]
|
|
assert not missing, (
|
|
"models.yaml entries without an `engines:` list (use `engines: []` for "
|
|
f"pipeline weights no engine owns): {missing}"
|
|
)
|
|
|
|
|
|
def test_engine_ids_in_models_yaml_exist(known_engine_ids):
|
|
unknown = {
|
|
(m["repo_id"], e)
|
|
for m in _catalog()
|
|
for e in m.get("engines") or []
|
|
if e not in known_engine_ids
|
|
}
|
|
assert not unknown, f"models.yaml names engine ids the registry does not have: {sorted(unknown)}"
|
|
|
|
|
|
def test_sherpa_dictation_models_belong_to_the_sherpa_engine():
|
|
for m in _catalog():
|
|
if m.get("engine") == "sherpa-onnx":
|
|
assert m.get("engines") == ["sherpa-onnx-asr"], m["repo_id"]
|