aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/backends/audiocpp')
-rw-r--r--app/backends/audiocpp/__init__.py3
-rw-r--r--app/backends/audiocpp/catalog.py46
2 files changed, 49 insertions, 0 deletions
diff --git a/app/backends/audiocpp/__init__.py b/app/backends/audiocpp/__init__.py
index a0fd16b..b97032b 100644
--- a/app/backends/audiocpp/__init__.py
+++ b/app/backends/audiocpp/__init__.py
@@ -35,6 +35,8 @@ from .catalog import (
build_server_config,
load_server_config,
server_config_selections,
+ request_options_families,
+ supports_request_options,
)
from .models import (
delete_model_files,
@@ -83,6 +85,7 @@ __all__ = [
"detect_backend", "load_model_catalog", "is_design_package",
"package_dir_options", "build_model_entry", "build_server_config",
"load_server_config", "server_config_selections",
+ "request_options_families", "supports_request_options",
# models
"missing_model_entries", "installed_model_entries",
"unused_installed_entries", "delete_model_files", "install_models",
diff --git a/app/backends/audiocpp/catalog.py b/app/backends/audiocpp/catalog.py
index f1989e9..2892b9c 100644
--- a/app/backends/audiocpp/catalog.py
+++ b/app/backends/audiocpp/catalog.py
@@ -10,6 +10,52 @@ from .constants import TASK_TTS
DESIGN_PACKAGE_RE = re.compile(r"voice[\s_\-]?design", re.IGNORECASE)
+def request_options_families(audiocpp_dir: Path) -> Dict[str, dict]:
+ """Map the families whose spec defines per-request options.
+
+ Reads every ``model_specs/<family>.json`` in AUDIOCPP_DIR once and
+ returns ``{family_key: {"display_name": ...}}`` for the specs that
+ list request options (a non-empty ``options.request`` array) — the
+ families a "Request options" field makes sense for. The key is the
+ spec's ``family`` field (falling back to the file stem), matching
+ what ``GET /v1/models`` reports, so callers can look an entry up by
+ its family id. A missing or unreadable specs directory yields {}
+ (every family then counts as unknown rather than unsupported).
+ """
+ specs_dir = audiocpp_dir / "model_specs"
+ if not specs_dir.is_dir():
+ return {}
+ families: Dict[str, dict] = {}
+ for spec_path in sorted(specs_dir.glob("*.json")):
+ try:
+ spec = json.loads(spec_path.read_text(encoding="utf-8"))
+ except (OSError, ValueError):
+ continue
+ options = spec.get("options")
+ request = options.get("request") if isinstance(options, dict) else None
+ if not isinstance(request, list) or not request:
+ continue
+ family = str(spec.get("family") or spec_path.stem)
+ families[family] = {
+ "display_name": str(spec.get("display_name") or family),
+ }
+ return families
+
+
+def supports_request_options(families: Dict[str, dict],
+ family: str) -> Optional[bool]:
+ """Whether FAMILY accepts per-request options — None when unknown.
+
+ True only when FAMILIES (from request_options_families) lists the
+ family; False when it was read but does not define request options;
+ None when support cannot be determined from the local specs (no
+ checkout, or a family the specs do not describe).
+ """
+ if not families:
+ return None
+ return family in families
+
+
_BACKEND_DESCRIPTIONS = (
("cuda", "NVIDIA GPUs (fastest)"),
("vulkan", "cross-vendor GPU"),