feat(menu): nicht nutzbare TTS-Provider ausblenden + GPU-Erkennung
Menue zeigt nur tatsaechlich nutzbare Vorlese-Optionen, um Verwirrung durch folgenlose Eintraege zu vermeiden: - Backend ist alleinige Quelle: /api/config liefert fertiges tts_menu (Chatterbox nur wenn erreichbar, Cloud nur mit OpenRouter-TTS, Cartesia nur mit Key). piper bleibt garantierter, immer sichtbarer Default. - Frontend blendet aus statt auszugrauen; 'Im Geraet' nur auf Mobilgeraeten (isMobile). Aktive/gespeicherte Auswahl auf einen sichtbaren Provider geklemmt -> kein Server-422. - 4x refresh*Preset + 3x /api/config-Fetch -> 1x refreshTtsMenu; /api/config serverseitig 30s gecacht (spart die bisher kostenpflichtige OpenRouter-Probe pro Seitenladen). GPU-Erkennung zentralisiert (keine Dopplung): - app/capabilities.py: detect_physical_gpus/resolve_gpus (nvidia-smi). - Neues Setting GPUS (auto|none|0,1,2), beim Start an CUDA_VISIBLE_DEVICES gekoppelt -> angezeigt = real nutzbar. admin_llm nutzt dieselbe Erkennung. Tests: tests/test_capabilities.py (Maske, Kopplung, Menue-Sichtbarkeit, GPUs). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6bf281fc30
commit
5e128a74ce
7 changed files with 333 additions and 114 deletions
|
|
@ -14,6 +14,7 @@ import subprocess
|
|||
from pathlib import Path
|
||||
|
||||
from app.config import settings
|
||||
from app.capabilities import detect_physical_gpus
|
||||
|
||||
ALLOWED_BACKENDS = {"ollama", "llamacpp"}
|
||||
_SCRIPT = Path(__file__).resolve().parent.parent / "scripts" / "llm-server" / "switch-llm.sh"
|
||||
|
|
@ -74,28 +75,6 @@ async def _ollama_loaded() -> tuple[bool, list[dict]]:
|
|||
return True, models
|
||||
|
||||
|
||||
async def _gpus() -> list[dict]:
|
||||
out = await _run([
|
||||
"nvidia-smi",
|
||||
"--query-gpu=index,memory.used,memory.total",
|
||||
"--format=csv,noheader,nounits",
|
||||
])
|
||||
if out is None:
|
||||
return []
|
||||
gpus: list[dict] = []
|
||||
for ln in out.splitlines():
|
||||
parts = [p.strip() for p in ln.split(",")]
|
||||
if len(parts) == 3 and parts[0].isdigit():
|
||||
used, total = int(parts[1]), int(parts[2])
|
||||
gpus.append({
|
||||
"index": int(parts[0]),
|
||||
"used_mib": used,
|
||||
"total_mib": total,
|
||||
"percent": round(used / total * 100) if total else 0,
|
||||
})
|
||||
return gpus
|
||||
|
||||
|
||||
async def _gateway_service_active() -> bool:
|
||||
out = await _run(["systemctl", "is-active", "voice-assistant.service"], timeout=4.0)
|
||||
return bool(out and out.strip() == "active")
|
||||
|
|
@ -108,7 +87,7 @@ async def llm_status() -> dict:
|
|||
llamacpp, (ollama_reachable, ollama_models), gpus, gw = await asyncio.gather(
|
||||
_llamacpp_running(),
|
||||
_ollama_loaded(),
|
||||
_gpus(),
|
||||
detect_physical_gpus(),
|
||||
_gateway_service_active(),
|
||||
)
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue