Remove Seed-VC after failed German quality test
This commit is contained in:
@@ -36,8 +36,6 @@ VOICE_LABEL_KEY = "com.mike-ai.voice-worker"
|
||||
VOICE_WORKER = os.environ.get("VOICE_WORKER", "").strip()
|
||||
VOICE_CHANGE_LABEL_KEY = "com.mike-ai.voice-change-worker"
|
||||
VOICE_CHANGE_WORKER = os.environ.get("VOICE_CHANGE_WORKER", "").strip()
|
||||
SEED_VC_LABEL_KEY = "com.mike-ai.seed-vc-worker"
|
||||
SEED_VC_WORKER = os.environ.get("SEED_VC_WORKER", "").strip()
|
||||
APPLIO_LABEL_KEY = "com.mike-ai.applio-worker"
|
||||
APPLIO_WORKER = os.environ.get("APPLIO_WORKER", "").strip()
|
||||
LOCK = threading.Lock()
|
||||
@@ -152,17 +150,6 @@ def voice_change_container() -> dict:
|
||||
return matches[0]
|
||||
|
||||
|
||||
def seed_vc_container() -> dict:
|
||||
if not SEED_VC_WORKER:
|
||||
raise RuntimeError("Seed-VC worker is not configured")
|
||||
matches = [item for item in labelled_containers(SEED_VC_LABEL_KEY)
|
||||
if item.get("Labels", {}).get(SEED_VC_LABEL_KEY) == SEED_VC_WORKER]
|
||||
if len(matches) != 1:
|
||||
raise RuntimeError(
|
||||
f"expected exactly one Seed-VC worker {SEED_VC_WORKER!r}, found {len(matches)}")
|
||||
return matches[0]
|
||||
|
||||
|
||||
def applio_container() -> dict:
|
||||
if not APPLIO_WORKER:
|
||||
raise RuntimeError("Applio worker is not configured")
|
||||
@@ -194,11 +181,6 @@ def stop_voice_change_if_configured() -> None:
|
||||
stop_container(voice_change_container(), timeout=30)
|
||||
|
||||
|
||||
def stop_seed_vc_if_configured() -> None:
|
||||
if SEED_VC_WORKER:
|
||||
stop_container(seed_vc_container(), timeout=30)
|
||||
|
||||
|
||||
def stop_applio_if_configured() -> None:
|
||||
if APPLIO_WORKER:
|
||||
stop_container(applio_container(), timeout=30)
|
||||
@@ -209,8 +191,6 @@ def stop_voice_tools(except_kind: str | None = None) -> None:
|
||||
stop_voice_if_configured()
|
||||
if except_kind != "voicechange":
|
||||
stop_voice_change_if_configured()
|
||||
if except_kind != "seedvc":
|
||||
stop_seed_vc_if_configured()
|
||||
if except_kind != "applio":
|
||||
stop_applio_if_configured()
|
||||
|
||||
@@ -348,26 +328,6 @@ def set_voice_change_worker(running: bool) -> dict:
|
||||
"state": "running" if running else "stopped"}
|
||||
|
||||
|
||||
def set_seed_vc_worker(running: bool) -> dict:
|
||||
"""Start Seed-VC exclusively, or stop it before another mode is loaded."""
|
||||
with LOCK:
|
||||
item = seed_vc_container()
|
||||
if running:
|
||||
for profile_item in containers().values():
|
||||
stop_container(profile_item)
|
||||
for worker in image_containers():
|
||||
stop_container(worker, timeout=20)
|
||||
stop_container(tts_container(), timeout=30)
|
||||
stop_music_if_configured()
|
||||
stop_separator_if_configured()
|
||||
stop_voice_tools("seedvc")
|
||||
start_container(item)
|
||||
else:
|
||||
stop_container(item, timeout=30)
|
||||
return {"seed_vc_worker": SEED_VC_WORKER,
|
||||
"state": "running" if running else "stopped"}
|
||||
|
||||
|
||||
def set_applio_worker(running: bool) -> dict:
|
||||
"""Start Applio exclusively, or stop it before another mode is loaded."""
|
||||
with LOCK:
|
||||
@@ -498,13 +458,6 @@ class Handler(BaseHTTPRequestHandler):
|
||||
"unhealthy" if "(unhealthy)" in voice_change_status else
|
||||
"starting" if voice_change.get("State") == "running" else
|
||||
"stopped")
|
||||
seed_vc = seed_vc_container() if SEED_VC_WORKER else {}
|
||||
seed_vc_status = seed_vc.get("Status", "")
|
||||
seed_vc_health = ("disabled" if not SEED_VC_WORKER else
|
||||
"healthy" if "(healthy)" in seed_vc_status else
|
||||
"unhealthy" if "(unhealthy)" in seed_vc_status else
|
||||
"starting" if seed_vc.get("State") == "running" else
|
||||
"stopped")
|
||||
applio = applio_container() if APPLIO_WORKER else {}
|
||||
applio_status = applio.get("Status", "")
|
||||
applio_health = ("disabled" if not APPLIO_WORKER else
|
||||
@@ -521,8 +474,6 @@ class Handler(BaseHTTPRequestHandler):
|
||||
"voice_health": voice_health,
|
||||
"voice_change_worker": voice_change.get("State", "disabled"),
|
||||
"voice_change_health": voice_change_health,
|
||||
"seed_vc_worker": seed_vc.get("State", "disabled"),
|
||||
"seed_vc_health": seed_vc_health,
|
||||
"applio_worker": applio.get("State", "disabled"),
|
||||
"applio_health": applio_health,
|
||||
"profiles": {name: items.get(name, {}).get(
|
||||
@@ -570,13 +521,6 @@ class Handler(BaseHTTPRequestHandler):
|
||||
log.exception("voice-change worker transition failed")
|
||||
self.reply(503, {"error": str(exc)})
|
||||
return
|
||||
if self.path in {"/workers/seed-vc/start", "/workers/seed-vc/stop"}:
|
||||
try:
|
||||
self.reply(200, set_seed_vc_worker(self.path.endswith("/start")))
|
||||
except Exception as exc:
|
||||
log.exception("Seed-VC worker transition failed")
|
||||
self.reply(503, {"error": str(exc)})
|
||||
return
|
||||
if self.path in {"/workers/applio/start", "/workers/applio/stop"}:
|
||||
try:
|
||||
self.reply(200, set_applio_worker(self.path.endswith("/start")))
|
||||
|
||||
@@ -83,7 +83,6 @@ start_proxy 7862 music-worker:7860
|
||||
start_proxy 8007 stem-separator:8080
|
||||
start_proxy 8008 voice-studio:8008
|
||||
start_proxy 8009 xvc-studio:8009
|
||||
start_proxy 8010 seed-vc-studio:7860
|
||||
start_proxy 8011 applio-studio:6969
|
||||
start_proxy 8202 mcp-athena-operator:8000
|
||||
start_proxy 9443 portainer:9443
|
||||
|
||||
@@ -30,7 +30,6 @@ MUSIC_ORIGINAL_UI_URL = os.getenv(
|
||||
SEPARATOR_UI_URL = os.getenv("SEPARATOR_UI_URL", "http://192.168.1.212:8007/")
|
||||
VOICE_UI_URL = os.getenv("VOICE_UI_URL", "http://192.168.1.212:8008/")
|
||||
VOICE_CHANGE_UI_URL = os.getenv("VOICE_CHANGE_UI_URL", "http://192.168.1.212:8009/")
|
||||
SEED_VC_UI_URL = os.getenv("SEED_VC_UI_URL", "http://192.168.1.212:8010/")
|
||||
APPLIO_UI_URL = os.getenv("APPLIO_UI_URL", "http://192.168.1.212:8011/")
|
||||
HOST_PROC = Path(os.getenv("HOST_PROC", "/host/proc"))
|
||||
HOST_DATA = os.getenv("HOST_DATA", "/host/data")
|
||||
@@ -281,7 +280,7 @@ def router_status() -> tuple[dict[str, Any], str | None]:
|
||||
|
||||
|
||||
def change_mode(mode: str) -> tuple[int, dict[str, Any]]:
|
||||
if mode not in {"llm", "music", "separation", "voice", "voicechange", "seedvc", "applio"}:
|
||||
if mode not in {"llm", "music", "separation", "voice", "voicechange", "applio"}:
|
||||
return 400, {"error": "invalid mode"}
|
||||
headers = {"Accept": "application/json", "Content-Type": "application/json"}
|
||||
if ROUTER_API_KEY:
|
||||
@@ -639,7 +638,7 @@ HTML = r'''<!doctype html>
|
||||
</style></head><body><main>
|
||||
<div class="top"><div><div class="eyebrow">Mike AI · Live Telemetry</div><h1>Athena llama.cpp Dashboard</h1></div><div class="live"><span class="dot" id="dot"></span><span id="updated">verbinde …</span></div></div>
|
||||
<section class="grid">
|
||||
<article class="card span12"><div class="mode-row"><div><div class="label">Athena Betriebsmodus</div><div class="value" id="operatingMode">–</div><div class="sub" id="modeStatus">Status wird geladen …</div></div><div class="mode-buttons"><button id="llmMode" onclick="setMode('llm')">LLM-Betrieb</button><button id="musicMode" onclick="setMode('music')">Musikstudio</button><button id="separationMode" onclick="setMode('separation')">Audio trennen</button><button id="voiceMode" onclick="setMode('voice')">Voice Studio</button><button id="voiceChangeMode" onclick="setMode('voicechange')">X-VC</button><button id="seedVcMode" onclick="setMode('seedvc')">Seed-VC</button><button id="applioMode" onclick="setMode('applio')">Applio / RVC · Modell nötig</button><span id="musicOpen" hidden><a class="stable" href="__MUSIC_ORIGINAL_UI_URL__" target="_blank" rel="noopener">Original UI · stabil</a><a class="experimental" href="__MUSIC_COMMUNITY_UI_URL__" target="_blank" rel="noopener">Community UI · experimentell</a></span><span id="separatorOpen" hidden><a class="stable" href="__SEPARATOR_UI_URL__" target="_blank" rel="noopener">Separator öffnen</a></span><span id="voiceOpen" hidden><a class="stable" href="__VOICE_UI_URL__" target="_blank" rel="noopener">Voice Studio öffnen</a></span><span id="voiceChangeOpen" hidden><a class="experimental" href="__VOICE_CHANGE_UI_URL__" target="_blank" rel="noopener">X-VC öffnen</a></span><span id="seedVcOpen" hidden><a class="experimental" href="__SEED_VC_UI_URL__" target="_blank" rel="noopener">Seed-VC öffnen</a></span><span id="applioOpen" hidden><a class="experimental" href="__APPLIO_UI_URL__" target="_blank" rel="noopener">Applio öffnen · RVC-Modell erforderlich</a></span></div></div></article>
|
||||
<article class="card span12"><div class="mode-row"><div><div class="label">Athena Betriebsmodus</div><div class="value" id="operatingMode">–</div><div class="sub" id="modeStatus">Status wird geladen …</div></div><div class="mode-buttons"><button id="llmMode" onclick="setMode('llm')">LLM-Betrieb</button><button id="musicMode" onclick="setMode('music')">Musikstudio</button><button id="separationMode" onclick="setMode('separation')">Audio trennen</button><button id="voiceMode" onclick="setMode('voice')">Voice Studio</button><button id="voiceChangeMode" onclick="setMode('voicechange')">X-VC</button><button id="applioMode" onclick="setMode('applio')">Applio / RVC · Modell nötig</button><span id="musicOpen" hidden><a class="stable" href="__MUSIC_ORIGINAL_UI_URL__" target="_blank" rel="noopener">Original UI · stabil</a><a class="experimental" href="__MUSIC_COMMUNITY_UI_URL__" target="_blank" rel="noopener">Community UI · experimentell</a></span><span id="separatorOpen" hidden><a class="stable" href="__SEPARATOR_UI_URL__" target="_blank" rel="noopener">Separator öffnen</a></span><span id="voiceOpen" hidden><a class="stable" href="__VOICE_UI_URL__" target="_blank" rel="noopener">Voice Studio öffnen</a></span><span id="voiceChangeOpen" hidden><a class="experimental" href="__VOICE_CHANGE_UI_URL__" target="_blank" rel="noopener">X-VC öffnen</a></span><span id="applioOpen" hidden><a class="experimental" href="__APPLIO_UI_URL__" target="_blank" rel="noopener">Applio öffnen · RVC-Modell erforderlich</a></span></div></div></article>
|
||||
<article class="card span3"><div class="label">Aktives Profil</div><div class="value" id="profile">–</div><div class="sub" id="profileSub">Router wird abgefragt</div></article>
|
||||
<article class="card span3"><div class="label">Modell</div><div class="value" id="model">–</div><div class="sub" id="modelSub">–</div></article>
|
||||
<article class="card span3"><div class="label">CPU</div><div class="value" id="cpu">–</div><div class="bar"><div class="fill" id="cpuBar"></div></div><div class="sub" id="load">–</div></article>
|
||||
@@ -678,20 +677,20 @@ const $=id=>document.getElementById(id); const pct=n=>n==null?'–':`${n.toFixed
|
||||
function gpuCard(g){let total=g.memory_total_mib||0,used=g.memory_used_mib||0,p=total?used/total*100:0,load=Math.max(0,Math.min(100,g.gpu_percent||0));return `<article class="card span6"><div class="gpu-title"><div><div class="label">GPU ${g.index}</div><div class="value">${g.name}</div></div><span class="badge">${g.pstate||'–'}</span></div><div class="metrics"><div class="metric"><b>${pct(g.gpu_percent)}</b><span>GPU-Kern</span></div><div class="metric"><b>${(used/1024).toFixed(1)} / ${(total/1024).toFixed(1)} GiB</b><span>VRAM</span></div><div class="metric"><b>${g.temperature_c??'–'} °C</b><span>Temperatur</span></div><div class="metric"><b>${g.power_w??'–'} / ${g.power_limit_w??'–'} W</b><span>Leistung</span></div><div class="metric"><b>${g.graphics_clock_mhz??'–'} MHz</b><span>Grafiktakt</span></div><div class="metric"><b>${g.memory_clock_mhz??'–'} MHz</b><span>Speichertakt</span></div><div class="metric"><b>${pct(g.memory_controller_percent)}</b><span>Memory Controller</span></div><div class="metric"><b>${pct(g.fan_percent)}</b><span>Lüfter</span></div></div><div class="bar-label"><span>GPU-Auslastung</span><span>${load.toFixed(1)} %</span></div><div class="bar"><div class="fill gpu-load" style="width:${load}%"></div></div><div class="bar-label"><span>VRAM-Belegung</span><span>${p.toFixed(1)} %</span></div><div class="bar"><div class="fill" style="width:${Math.min(100,p)}%"></div></div><div class="sub">${(g.memory_free_mib/1024).toFixed(1)} GiB VRAM frei</div></article>`}
|
||||
const imagePhaseLabel=p=>({"stopping-qwen":"Qwen wird entladen","loading-image":"Bildmodell wird geladen","generating":"Bild wird generiert","unloading-image":"Bildmodell wird entladen","restoring-qwen":"Qwen wird wiederhergestellt"}[p]||p||'bereit');
|
||||
let modeBusy=false;
|
||||
async function setMode(mode){if(modeBusy)return;modeBusy=true;for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','seedVcMode','applioMode'])$(id).disabled=true;$('modeStatus').textContent='Umschaltung angefordert …';try{let r=await fetch('/api/mode',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mode})});let d=await r.json();if(!r.ok)throw Error(d?.error?.message||d?.error||`HTTP ${r.status}`);$('modeStatus').textContent='Umschaltung läuft …'}catch(e){$('modeStatus').textContent=e.message;$('modeStatus').classList.add('mode-error')}finally{modeBusy=false;setTimeout(refresh,250)}}
|
||||
async function setMode(mode){if(modeBusy)return;modeBusy=true;for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','applioMode'])$(id).disabled=true;$('modeStatus').textContent='Umschaltung angefordert …';try{let r=await fetch('/api/mode',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({mode})});let d=await r.json();if(!r.ok)throw Error(d?.error?.message||d?.error||`HTTP ${r.status}`);$('modeStatus').textContent='Umschaltung läuft …'}catch(e){$('modeStatus').textContent=e.message;$('modeStatus').classList.add('mode-error')}finally{modeBusy=false;setTimeout(refresh,250)}}
|
||||
async function refresh(){try{let r=await fetch('/api/status',{cache:'no-store'});if(!r.ok)throw Error(`HTTP ${r.status}`);let d=await r.json(),c=d.cpu||{},m=c.memory||{},rt=d.router||{},up=rt.upstream||{},q=rt.qwen||{},lr=d.llama_runtime||{},img=rt.image||{},imageActive=img.phase&&img.phase!=='idle';let md=rt.mode||{},switchingMode=md.phase&&md.phase!=='ready',modeName=md.active==='music'?'Musikstudio':md.active==='separation'?'Stimmtrennung':md.active==='voice'?'Voice Studio':'LLM-Betrieb';$('operatingMode').textContent=modeName;$('modeStatus').textContent=switchingMode?`Umschaltung: ${md.phase}`:(md.last_error||`Musik: ${md.music_worker||'–'} · Separator: ${md.separator_worker||'–'} · Voice: ${md.voice_worker||'–'}${md.return_profile?` · Rückkehr zu ${md.return_profile}`:''}`);$('modeStatus').classList.toggle('mode-error',!!md.last_error);$('llmMode').classList.toggle('active',md.active==='llm');$('musicMode').classList.toggle('active',md.active==='music');$('separationMode').classList.toggle('active',md.active==='separation');$('voiceMode').classList.toggle('active',md.active==='voice');$('llmMode').disabled=$('musicMode').disabled=$('separationMode').disabled=$('voiceMode').disabled=modeBusy||switchingMode||!md.enabled;$('musicOpen').hidden=md.active!=='music';$('separatorOpen').hidden=md.active!=='separation';$('voiceOpen').hidden=md.active!=='voice';$('profile').textContent=imageActive?'Bildgenerierung':(rt.current_profile||'nicht geladen');$('profileSub').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching?`Wechsel zu ${rt.switching}`:`Kontext: ${up.ctx?up.ctx.toLocaleString('de-DE'):'–'} Token`);$('model').textContent=imageActive?(img.model||'Bildmodell'):(up.model||'–');$('modelSub').textContent=imageActive?`${img.model_loaded?'geladen':'wird vorbereitet'} · Worker ${img.worker||'–'}`:(lr.model_file|| (up.reachable?'llama.cpp erreichbar':'llama.cpp nicht erreichbar'));$('cpu').textContent=pct(c.usage_percent);$('cpuBar').style.width=`${c.usage_percent||0}%`;$('load').textContent=`${c.logical_cpus||'–'} Threads · Load ${(c.load||[]).join(' / ')}`;let rp=m.total?m.used/m.total*100:0;$('ram').textContent=pct(rp);$('ramBar').style.width=`${rp}%`;$('ramSub').textContent=`${gib(m.used)} / ${gib(m.total)}`;$('gpuCards').innerHTML=(d.gpus||[]).map(gpuCard).join('')||'<article class="card span12 error">Keine GPU-Daten verfügbar</article>';$('availability').textContent=imageActive?imagePhaseLabel(img.phase):(q.available?'bereit':'nicht bereit');$('availability').className=`value status ${(imageActive||q.available)?'':'bad'}`;$('activeChats').textContent=q.active_chats??'–';$('routerUptime').textContent=dur(rt.uptime_seconds);$('switching').textContent=imageActive?imagePhaseLabel(img.phase):(rt.switching||'nein');let disk=c.disk_data||{},dp=disk.total?disk.used/disk.total*100:null;$('dataDisk').textContent=pct(dp);$('processes').innerHTML=(d.gpu_processes||[]).map(p=>`<tr><td>${(d.gpus||[]).find(g=>g.uuid===p.gpu_uuid)?.index??'–'}</td><td>${p.name}</td><td>${p.pid}</td><td>${p.memory_mib??'–'} MiB</td></tr>`).join('')||'<tr><td colspan="4">Keine Compute-Prozesse gemeldet</td></tr>';let runtime=[['Modell-Datei',lr.model_file],['PID',lr.pid],['Kontext',lr.context_size?lr.context_size.toLocaleString('de-DE'):'–'],['Batch / µBatch',`${lr.batch_size??'–'} / ${lr.ubatch_size??'–'}`],['Parallel',lr.parallel],['Threads',`${lr.threads??'–'} / ${lr.threads_batch??'–'}`],['Geräte',lr.device],['Tensor-Split',lr.tensor_split],['KV-Cache',`${lr.cache_k??'–'} / ${lr.cache_v??'–'}`],['Flash Attention',lr.flash_attention?'an':'aus'],['Prompt-Cache',lr.prompt_cache?'an':'aus'],['MTP Draft',lr.mtp_draft_tokens]];$('runtime').innerHTML=runtime.map(([k,v])=>`<div class="metric"><b>${v??'–'}</b><span>${k}</span></div>`).join('');let es=Object.entries(d.errors||{}).filter(([,v])=>v);$('errors').hidden=!es.length;$('errors').textContent=es.map(([k,v])=>`${k}: ${v}`).join('\n');$('updated').textContent=`Live · ${new Date(d.timestamp*1000).toLocaleTimeString('de-DE')}`;$('dot').style.background='var(--green)'}catch(e){$('updated').textContent=`Verbindung gestört: ${e.message}`;$('dot').style.background='var(--red)'}}refresh();setInterval(refresh,1000);
|
||||
</script><script>
|
||||
const baseSetMode=setMode;
|
||||
setMode=async function(mode){
|
||||
if(modeBusy)return;
|
||||
for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','seedVcMode','applioMode'])$(id).disabled=true;
|
||||
for(const id of ['llmMode','musicMode','separationMode','voiceMode','voiceChangeMode','applioMode'])$(id).disabled=true;
|
||||
await baseSetMode(mode);
|
||||
};
|
||||
async function refreshVoiceChange(){
|
||||
try{
|
||||
const response=await fetch('/api/status',{cache:'no-store'}); if(!response.ok)return;
|
||||
const data=await response.json(),mode=data.router?.mode||{},busy=modeBusy||(mode.phase&&mode.phase!=='ready')||!mode.enabled;
|
||||
const modes=[['voicechange','voiceChangeMode','voiceChangeOpen','X-VC Voice Changer'],['seedvc','seedVcMode','seedVcOpen','Seed-VC'],['applio','applioMode','applioOpen','Applio / RVC']];
|
||||
const modes=[['voicechange','voiceChangeMode','voiceChangeOpen','X-VC Voice Changer'],['applio','applioMode','applioOpen','Applio / RVC']];
|
||||
for(const [name,button,link,label] of modes){const active=mode.active===name;$(button).classList.toggle('active',active);$(button).disabled=busy;$(link).hidden=!active;if(active)$('operatingMode').textContent=label;}
|
||||
}catch(_error){}
|
||||
}
|
||||
@@ -701,8 +700,7 @@ setTimeout(()=>{refreshVoiceChange();setInterval(refreshVoiceChange,1000)},150);
|
||||
).replace("__MUSIC_COMMUNITY_UI_URL__", MUSIC_COMMUNITY_UI_URL
|
||||
).replace("__SEPARATOR_UI_URL__", SEPARATOR_UI_URL
|
||||
).replace("__VOICE_UI_URL__", VOICE_UI_URL
|
||||
).replace("__VOICE_CHANGE_UI_URL__", VOICE_CHANGE_UI_URL).replace(
|
||||
"__SEED_VC_UI_URL__", SEED_VC_UI_URL
|
||||
).replace("__VOICE_CHANGE_UI_URL__", VOICE_CHANGE_UI_URL
|
||||
).replace("__APPLIO_UI_URL__", APPLIO_UI_URL)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user