+35
-20
@@ -1,22 +1,37 @@
|
||||
#!/usr/bin/env sh
|
||||
set -u
|
||||
ok=1
|
||||
check_bin(){ if command -v "$1" >/dev/null 2>&1; then printf '[OK] %s\n' "$1"; else printf '[MISS] %s\n' "$1"; ok=0; fi; }
|
||||
check_file(){ if [ -f "$1" ]; then printf '[OK] %s\n' "$1"; else printf '[MISS] %s\n' "$1"; ok=0; fi; }
|
||||
check_bin go
|
||||
check_bin ollama
|
||||
check_bin "${VOICE_FFMPEG_BIN:-ffmpeg}"
|
||||
check_bin "${VOICE_WHISPER_BIN:-whisper-cli}"
|
||||
check_bin "${VOICE_PIPER_BIN:-piper}"
|
||||
check_file "${VOICE_WHISPER_MODEL:-./models/ggml-small.bin}"
|
||||
check_file "${VOICE_PIPER_MODEL:-./models/de_DE-thorsten-medium.onnx}"
|
||||
printf '\nOllama models:\n'
|
||||
if command -v ollama >/dev/null 2>&1; then
|
||||
ollama list 2>/dev/null || printf '[WARN] Ollama daemon nicht erreichbar.\n'
|
||||
printf '\nJARVIS nutzt OLLAMA_MODEL=%s und OLLAMA_EMBED_MODEL=%s.\n' "${OLLAMA_MODEL:-auto}" "${OLLAMA_EMBED_MODEL:-auto}"
|
||||
printf 'Bei "auto" werden vorhandene Modelle selbständig erkannt.\n'
|
||||
printf 'Context: num_ctx=%s · output=%s · planner_ctx=%s · history=%s · RAG=%s\n' "${OLLAMA_NUM_CTX:-16384}" "${OLLAMA_NUM_PREDICT:-1200}" "${OLLAMA_PLANNER_NUM_CTX:-8192}" "${JARVIS_HISTORY_TOKENS:-3200}" "${JARVIS_RAG_TOKENS:-4200}"
|
||||
fi
|
||||
printf '\nDebug trace: enabled=%s · dir=%s · max=%sMB · keep=%s\n' "${JARVIS_DEBUG_TRACE:-true}" "${JARVIS_DEBUG_DIR:-./data/debug}" "${JARVIS_DEBUG_MAX_MB:-25}" "${JARVIS_DEBUG_KEEP_FILES:-4}"
|
||||
if [ "$ok" -eq 1 ]; then printf '\nJARVIS local stack ready.\n'; else printf '\nEinige Voice-Abhängigkeiten fehlen. Text/Home-Core kann trotzdem laufen.\n'; fi
|
||||
exit 0
|
||||
|
||||
ok(){ printf '[OK] %s\n' "$*"; }
|
||||
warn(){ printf '[!!] %s\n' "$*"; }
|
||||
|
||||
check_bin(){
|
||||
label="$1"; bin="$2"
|
||||
if command -v "$bin" >/dev/null 2>&1; then
|
||||
resolved="$(command -v "$bin")"
|
||||
ok "$label binary: $resolved"
|
||||
ls -l "$resolved" 2>/dev/null || true
|
||||
elif [ -x "$bin" ]; then
|
||||
ok "$label binary: $bin"
|
||||
ls -l "$bin" 2>/dev/null || true
|
||||
else
|
||||
warn "$label binary fehlt/nicht ausführbar: $bin"
|
||||
fi
|
||||
}
|
||||
check_file(){
|
||||
label="$1"; f="$2"
|
||||
if [ -f "$f" ]; then
|
||||
ok "$label: $f ($(wc -c < "$f" 2>/dev/null || echo '?') bytes)"
|
||||
else
|
||||
warn "$label fehlt: $f"
|
||||
fi
|
||||
}
|
||||
|
||||
printf '%s\n' '--- JARVIS Voice Doctor ---'
|
||||
check_bin "FFmpeg" "${VOICE_FFMPEG_BIN:-ffmpeg}"
|
||||
check_bin "Whisper" "${VOICE_WHISPER_BIN:-/usr/local/bin/whisper-cli}"
|
||||
check_file "Whisper model" "${VOICE_WHISPER_MODEL:-/models/ggml-small.bin}"
|
||||
check_bin "Piper" "${VOICE_PIPER_BIN:-/tools/piper}"
|
||||
check_file "Piper model" "${VOICE_PIPER_MODEL:-/models/de_DE-thorsten-medium.onnx}"
|
||||
check_file "Piper model config" "${VOICE_PIPER_MODEL:-/models/de_DE-thorsten-medium.onnx}.json"
|
||||
printf 'LD_LIBRARY_PATH=%s\n' "${LD_LIBRARY_PATH:-}"
|
||||
printf 'PATH=%s\n' "$PATH"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
MODELS="$ROOT/models"
|
||||
TOOLS="$ROOT/local-tools"
|
||||
mkdir -p "$MODELS" "$TOOLS"
|
||||
|
||||
download() {
|
||||
local url="$1" out="$2"
|
||||
if [[ -f "$out" && -s "$out" ]]; then
|
||||
echo "[ok] vorhanden: $out"
|
||||
return
|
||||
fi
|
||||
echo "[download] $url"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fL --retry 3 --progress-bar "$url" -o "$out"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -O "$out" "$url"
|
||||
else
|
||||
echo "Fehler: curl oder wget wird benötigt." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Whisper model. whisper-cli itself is built into the Docker image since v7.6.
|
||||
download "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin" "$MODELS/ggml-small.bin"
|
||||
|
||||
# German Piper voice + sidecar config.
|
||||
download "https://huggingface.co/rhasspy/piper-voices/resolve/main/de/de_DE/thorsten/medium/de_DE-thorsten-medium.onnx" "$MODELS/de_DE-thorsten-medium.onnx"
|
||||
download "https://huggingface.co/rhasspy/piper-voices/resolve/main/de/de_DE/thorsten/medium/de_DE-thorsten-medium.onnx.json" "$MODELS/de_DE-thorsten-medium.onnx.json"
|
||||
|
||||
if [[ ! -x "$TOOLS/piper" ]]; then
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) asset="piper_linux_x86_64.tar.gz" ;;
|
||||
aarch64|arm64) asset="piper_linux_aarch64.tar.gz" ;;
|
||||
armv7l) asset="piper_linux_armv7l.tar.gz" ;;
|
||||
*) echo "Piper-Binary für Architektur $(uname -m) bitte manuell unter $TOOLS/piper ablegen." >&2; exit 1 ;;
|
||||
esac
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
archive="$tmp/piper.tar.gz"
|
||||
download "https://github.com/rhasspy/piper/releases/download/2023.11.14-2/$asset" "$archive"
|
||||
mkdir -p "$tmp/extract"
|
||||
tar -xzf "$archive" -C "$tmp/extract"
|
||||
piper_exec="$(find "$tmp/extract" -type f -name piper -perm -u+x | head -n 1 || true)"
|
||||
if [[ -z "$piper_exec" ]]; then
|
||||
echo "Piper konnte im Release-Archiv nicht gefunden werden." >&2
|
||||
exit 1
|
||||
fi
|
||||
piper_dir="$(dirname "$piper_exec")"
|
||||
cp -a "$piper_dir"/. "$TOOLS"/
|
||||
chmod +x "$TOOLS/piper"
|
||||
echo "[ok] Piper installiert: $TOOLS/piper"
|
||||
else
|
||||
echo "[ok] Piper vorhanden: $TOOLS/piper"
|
||||
fi
|
||||
|
||||
cat <<MSG
|
||||
|
||||
Voice-Dateien sind vorbereitet.
|
||||
Jetzt neu bauen/starten:
|
||||
docker compose build --no-cache jarvis
|
||||
docker compose up -d
|
||||
|
||||
Diagnose:
|
||||
docker compose exec jarvis /app/scripts/doctor.sh # falls Scripts gemountet/kopiert sind
|
||||
oder:
|
||||
docker compose exec jarvis sh -lc 'command -v whisper-cli; ls -lh /models/ggml-small.bin /tools/piper /models/de_DE-thorsten-medium.onnx'
|
||||
MSG
|
||||
Reference in New Issue
Block a user