74 lines
4.4 KiB
Python
74 lines
4.4 KiB
Python
"""Pinned audio.cpp build, isolated from model execution and existing runtimes."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
import sys
|
|
import time
|
|
from ltx_original_runtime import LTXOriginalRuntime
|
|
|
|
REVISION='f2b4937306daa25f5c78520f3c626ed31495a37a'
|
|
VERSION='v0.8.1'
|
|
class AudioCppRuntime(LTXOriginalRuntime):
|
|
name="audio.cpp"
|
|
def __init__(self,root):
|
|
super().__init__(root,None)
|
|
request=self.root/'resume-request'
|
|
if request.is_file():
|
|
request.unlink()
|
|
self.start()
|
|
def paths(self):
|
|
p=self.root/'active.json'
|
|
if p.is_file():
|
|
ident=json.loads(p.read_text()).get('id','')
|
|
if len(ident)==32 and all(c in '0123456789abcdef' for c in ident):
|
|
base=self.root/ident
|
|
if (base/'ready').is_file():return base/'build/bin/audiocpp_cli',base/'source'
|
|
return self.root/'missing-cli',self.root/'missing-source'
|
|
def status(self):
|
|
cli,source=self.paths()
|
|
return dict(installed=cli.is_file() and (source/'model_specs/yue2.json').is_file(),revision=REVISION,version=VERSION,job=dict(self.job) if self.job else None,required_disk_gib=6,adapter_ready=True,origin='0xShug0/audio.cpp',message='Gemeinsame Laufzeit. Ein Build startet kein Modell; Der YuE2-Musikworker ist angebunden; Profil und Komponenten werden benötigt. Andere Familien brauchen eigene geprüfte Anbindungen.')
|
|
def start(self):
|
|
if sys.platform!='linux':raise ValueError('audio.cpp wird auf dem Debian-Server gebaut.')
|
|
missing=[name for name in ('git','cmake','g++','nvcc','nvidia-smi') if not shutil.which(name)]
|
|
if missing:raise ValueError('Build-Werkzeuge fehlen: '+', '.join(missing)+'. Keine automatische Host-Paket- oder Treiberänderung.')
|
|
self.resume_id=(self.job or {}).get('id')
|
|
return super().start()
|
|
def _run(self):
|
|
base=self.root/self.job['id'];state='failed';phase='audio.cpp-Build fehlgeschlagen.'
|
|
try:
|
|
previous=self.root/getattr(self,'resume_id','missing') if getattr(self,'resume_id',None) else None
|
|
if previous and (previous/'source/.git').is_dir() and not (previous/'ready').exists():
|
|
base=previous;self.job['id']=previous.name;self._save()
|
|
else:base.mkdir(mode=0o700)
|
|
tmp=base/'tmp';tmp.mkdir(exist_ok=True)
|
|
env=dict(os.environ,TMPDIR=str(tmp),GIT_TERMINAL_PROMPT='0',OMP_NUM_THREADS='2')
|
|
source=base/'source';build=base/'build'
|
|
self._phase('Offizielle audio.cpp-Quelle herunterladen')
|
|
if not (source/'.git').is_dir():
|
|
self._command(['git','init',source],env)
|
|
self._command(['git','-C',source,'fetch','--depth','1','https://github.com/0xShug0/audio.cpp.git',REVISION],env)
|
|
self._command(['git','-C',source,'checkout','--detach','FETCH_HEAD'],env)
|
|
else:self._command(['git','-C',source,'rev-parse','--verify',REVISION+'^{commit}'],env)
|
|
# Compile for the actual available GPUs; no weight allocation or inference.
|
|
import subprocess
|
|
raw=subprocess.check_output(['nvidia-smi','--query-gpu=compute_cap','--format=csv,noheader'],text=True)
|
|
arch=sorted({line.strip().replace('.','') for line in raw.splitlines() if line.strip()})
|
|
if not arch or any(not a.isdigit() for a in arch):raise ValueError('CUDA-Architekturen nicht ermittelbar.')
|
|
self._phase('CUDA-Build konfigurieren · GPU-Ziele '+', '.join(arch))
|
|
self._command(['cmake','-S',source,'-B',build,'-DCMAKE_BUILD_TYPE=Release','-DENGINE_ENABLE_CUDA=ON','-DCMAKE_CUDA_ARCHITECTURES='+';'.join(arch),'-DAUDIOCPP_DEPLOYMENT_BUILD=ON','-DAUDIOCPP_BUILD_SERVER_FRONTENDS=OFF','-DENGINE_BUILD_TESTS=OFF'],env)
|
|
self._phase('audio.cpp bauen · sechs parallele Build-Jobs')
|
|
self._command(['cmake','--build',build,'--target','audiocpp_cli','audiocpp_server','--parallel','6'],env)
|
|
self._phase('Programmstart ohne Modell prüfen')
|
|
self._command([build/'bin/audiocpp_cli','--help'],env)
|
|
if not (source/'model_specs/yue2.json').is_file():raise ValueError('YuE2-Modellspezifikation fehlt.')
|
|
if self.cancel.is_set():raise InterruptedError()
|
|
(base/'ready').write_text(REVISION)
|
|
marker=self.root/'active.tmp';marker.write_text(json.dumps({'id':base.name}));marker.replace(self.root/'active.json')
|
|
state='complete';phase='audio.cpp installiert. Kein Modell gestartet; Deck-Worker noch erforderlich.'
|
|
except InterruptedError:state='cancelled';phase='Build abgebrochen.'
|
|
except Exception as exc:phase=str(exc)
|
|
finally:
|
|
# Keep unfinished compiler artifacts so retry resumes the same pinned build.
|
|
with self.lock:self.process=None;self.job.update(state=state,phase=phase,finished_at=time.time());self._save()
|