- Neues xtts_worker.py: Coqui XTTS-v2, HTTP-API auf Port 8085 - Router: TTS_WORKER_URL → 8085, TTS_MODEL → xtts-v2, TTS_VOICES → claribel - deploy: mike-ai-xtts.service, install.sh + deploy.sh aktualisiert - Tests: 54/54 bestanden (mock_tts_worker + test_local.sh auf XTTS umgestellt) - README: TTS-Section auf XTTS-v2 aktualisiert - Kokoro-Service gestoppt und deaktiviert (Dateien bleiben als Backup)
159 lines
5.9 KiB
Bash
Executable File
159 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
||
# AI Profile Router – Installation/Update auf dem Zielsystem.
|
||
# Wird als root auf dem Zielsystem ausgeführt (per SSH, vgl. deploy.sh).
|
||
# Erwartet ai_profile_router.py, image_worker.py, xtts_worker.py,
|
||
# mike-ai-profile-router.service und mike-ai-xtts.service im selben
|
||
# Verzeichnis wie dieses Skript.
|
||
set -euo pipefail
|
||
|
||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
INSTALL_DIR=/opt/mike-ai/ai-profile-router
|
||
SERVICE=mike-ai-profile-router.service
|
||
XTTS_SERVICE=mike-ai-xtts.service
|
||
WHISPER_SERVICE=mike-ai-whisper.service
|
||
OLD_SERVICE=mike-ai-local-llm-router.service
|
||
OLD_DIR=/opt/mike-ai/local-llm-router
|
||
BACKUP_DIR=/opt/mike-ai/.backup-ai-profile-router-$(date +%Y%m%d-%H%M%S)
|
||
VENV="$INSTALL_DIR/venv"
|
||
MODEL_DIR=/opt/mike-ai/models/FLUX.2-klein-base-4B
|
||
IMAGE_DIR="$INSTALL_DIR/images"
|
||
XTTS_VENV=/opt/mike-ai/xtts/venv
|
||
XTTS_CACHE=/opt/mike-ai/xtts/.cache
|
||
|
||
echo "== AI Profile Router: Installation/Update =="
|
||
|
||
# --- 1. Bestehenden (alten) Router entfernen, mit Backup -------------------
|
||
if [ -f "/etc/systemd/system/${OLD_SERVICE}" ]; then
|
||
echo "-- Entferne alten Router ${OLD_SERVICE} (Backup: ${BACKUP_DIR})"
|
||
mkdir -p "$BACKUP_DIR"
|
||
systemctl stop "$OLD_SERVICE" 2>/dev/null || true
|
||
systemctl disable "$OLD_SERVICE" 2>/dev/null || true
|
||
mv "/etc/systemd/system/${OLD_SERVICE}" "$BACKUP_DIR/"
|
||
if [ -d "$OLD_DIR" ]; then
|
||
mv "$OLD_DIR" "$BACKUP_DIR/local-llm-router"
|
||
fi
|
||
else
|
||
echo "-- Kein alter Router gefunden"
|
||
fi
|
||
|
||
# --- 2. Neue Dateien installieren -------------------------------------------
|
||
mkdir -p "$INSTALL_DIR" "$IMAGE_DIR"
|
||
install -m 0755 "$DIR/ai_profile_router.py" "$INSTALL_DIR/ai_profile_router.py"
|
||
install -m 0755 "$DIR/image_worker.py" "$INSTALL_DIR/image_worker.py"
|
||
install -m 0755 "$DIR/xtts_worker.py" "$INSTALL_DIR/xtts_worker.py"
|
||
install -m 0755 "$DIR/stt_worker.py" "$INSTALL_DIR/stt_worker.py"
|
||
install -m 0644 "$DIR/${SERVICE}" "/etc/systemd/system/${SERVICE}"
|
||
install -m 0644 "$DIR/${XTTS_SERVICE}" "/etc/systemd/system/${XTTS_SERVICE}"
|
||
install -m 0644 "$DIR/${WHISPER_SERVICE}" "/etc/systemd/system/${WHISPER_SERVICE}"
|
||
|
||
# --- 3. Python-Venv mit Bild-Abhängigkeiten ---------------------------------
|
||
if [ ! -x "$VENV/bin/python" ]; then
|
||
echo "-- Erstelle Python-Venv in $VENV"
|
||
python3 -m venv "$VENV"
|
||
fi
|
||
echo "-- Installiere/aktualisiere Bild-Abhängigkeiten (torch, diffusers, ...)"
|
||
"$VENV/bin/pip" install --quiet --upgrade pip
|
||
"$VENV/bin/pip" install --quiet \
|
||
torch \
|
||
diffusers \
|
||
transformers \
|
||
accelerate
|
||
|
||
# --- 4. FLUX-Modell (nur wenn noch nicht vorhanden) --------------------------
|
||
if [ -f "$MODEL_DIR/model_index.json" ]; then
|
||
echo "-- FLUX-Modell vorhanden: $MODEL_DIR"
|
||
else
|
||
echo "-- Lade FLUX.2-klein-base-4B nach $MODEL_DIR (kann dauern)"
|
||
"$VENV/bin/python" - <<'PY'
|
||
import os
|
||
from huggingface_hub import snapshot_download
|
||
snapshot_download(
|
||
repo_id="black-forest-labs/FLUX.2-klein-base-4B",
|
||
local_dir="/opt/mike-ai/models/FLUX.2-klein-base-4B",
|
||
local_dir_use_symlinks=False,
|
||
)
|
||
print("Modell-Download abgeschlossen")
|
||
PY
|
||
fi
|
||
|
||
# --- 5. TTS (XTTS-v2) ----------------------------------------------------------
|
||
# XTTS-Venv (Python 3.11 via uv + CPU-only torch + Coqui TTS)
|
||
if [ ! -x "$XTTS_VENV/bin/python" ]; then
|
||
echo "-- Erstelle XTTS-Venv in $XTTS_VENV (Python 3.11 via uv)"
|
||
mkdir -p "$XTTS_VENV"
|
||
# uv installieren (falls noch nicht vorhanden)
|
||
if ! command -v uv >/dev/null 2>&1; then
|
||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||
export PATH="$HOME/.local/bin:$PATH"
|
||
fi
|
||
uv venv --python 3.11 "$XTTS_VENV"
|
||
"$XTTS_VENV/bin/pip" install --quiet --upgrade pip
|
||
echo "-- Installiere CPU-only torch"
|
||
"$XTTS_VENV/bin/pip" install --quiet torch torchaudio \
|
||
--index-url https://download.pytorch.org/whl/cpu
|
||
echo "-- Installiere Coqui TTS + Abhängigkeiten"
|
||
"$XTTS_VENV/bin/pip" install --quiet \
|
||
TTS==0.22.0 transformers==4.40.2 tokenizers==0.19.1 \
|
||
huggingface-hub==0.36.2 librosa soundfile
|
||
# PyTorch 2.6+ weights_only-Patch für Coqui TTS
|
||
echo "-- Wende weights_only-Patch für Coqui TTS an"
|
||
"$XTTS_VENV/bin/python" - <<'PY'
|
||
import os
|
||
patch_file = os.path.expanduser("/opt/mike-ai/xtts/venv/lib/python3.11/site-packages/TTS/utils/io.py")
|
||
with open(patch_file, 'r') as f:
|
||
content = f.read()
|
||
if 'weights_only=False' not in content:
|
||
content = content.replace(
|
||
'return torch.load(f, map_location=map_location, **kwargs)',
|
||
'return torch.load(f, map_location=map_location, weights_only=False, **kwargs)'
|
||
)
|
||
with open(patch_file, 'w') as f:
|
||
f.write(content)
|
||
print("Patch angewendet")
|
||
else:
|
||
print("Patch bereits vorhanden")
|
||
PY
|
||
fi
|
||
|
||
# XTTS-v2-Modell (nur wenn noch nicht vorhanden)
|
||
if [ ! -d "$XTTS_CACHE/hub/models--coqui--tts_models--multilingual--multi-dataset--xtts_v2" ]; then
|
||
echo "-- Lade XTTS-v2-Modell (kann dauern, ~1.9 GB)"
|
||
"$XTTS_VENV/bin/python" - <<'PY'
|
||
import os
|
||
os.environ["HF_HOME"] = "/opt/mike-ai/xtts/.cache"
|
||
from TTS.api import TTS
|
||
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
|
||
print("Modell geladen")
|
||
PY
|
||
fi
|
||
|
||
# --- 6. Services aktivieren und starten ---------------------------------------
|
||
systemctl daemon-reload
|
||
systemctl enable "$SERVICE" "$XTTS_SERVICE" "$WHISPER_SERVICE"
|
||
systemctl restart "$XTTS_SERVICE"
|
||
systemctl restart "$WHISPER_SERVICE"
|
||
systemctl restart "$SERVICE"
|
||
|
||
# --- 7. Verifikation ----------------------------------------------------------
|
||
sleep 1
|
||
if ! systemctl is-active --quiet "$SERVICE"; then
|
||
echo "-- FEHLER: Router-Service läuft nicht" >&2
|
||
journalctl -u "$SERVICE" -n 20 --no-pager >&2
|
||
exit 1
|
||
fi
|
||
echo "-- Router-Service läuft"
|
||
if ! systemctl is-active --quiet "$XTTS_SERVICE"; then
|
||
echo "-- FEHLER: XTTS-Service läuft nicht" >&2
|
||
journalctl -u "$XTTS_SERVICE" -n 20 --no-pager >&2
|
||
exit 1
|
||
fi
|
||
echo "-- XTTS-Service läuft"
|
||
if ! systemctl is-active --quiet "$WHISPER_SERVICE"; then
|
||
echo "-- FEHLER: Whisper-Service läuft nicht" >&2
|
||
journalctl -u "$WHISPER_SERVICE" -n 20 --no-pager >&2
|
||
exit 1
|
||
fi
|
||
echo "-- Whisper-Service läuft"
|
||
curl -sf "http://127.0.0.1:8081/status" | python3 -m json.tool
|
||
echo "== Fertig =="
|