feat(llm): Make-Targets zum Wechseln des LLM-Backends (Ollama <-> llama.cpp)
- scripts/llm-server/switch-llm.sh: gibt GPU des anderen Backends frei (llama.cpp-Container stoppen bzw. Ollama-Modelle entladen, Dienst bleibt), startet das gewünschte Backend, passt LOCAL_LLM_* in .env an und startet das Gateway (als Dienst) neu bzw. weist auf manuellen Neustart hin. - Makefile: Targets `llm-ollama` / `llm-llamacpp` (Modell via OLLAMA_MODEL=...). - Doku §4.7 + Schnellbefehle §4.0: Make-Targets als empfohlener Weg, inkl. Erklärung warum der Gateway-Neustart nötig ist (Makefile exportiert .env als Env-Variablen -> Vorrang vor .env-Datei). Getestet: Round-Trip ollama -> llamacpp -> ollama; llama.cpp 2,3s, gemma3 warm. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
878bf785dd
commit
317ad2ff97
3 changed files with 131 additions and 9 deletions
|
|
@ -379,6 +379,8 @@ Die wichtigsten Kommandos auf einen Blick — Details in den Abschnitten darunte
|
||||||
| Profil `cloud` — nur Gateway | `make run` |
|
| Profil `cloud` — nur Gateway | `make run` |
|
||||||
| Profil `hybrid` / `local-dev` — llama.cpp + Gateway | `make start` |
|
| Profil `hybrid` / `local-dev` — llama.cpp + Gateway | `make start` |
|
||||||
| Profil `hybrid` / `local-dev` — Ollama + Gateway | `sudo systemctl start ollama && make run` |
|
| Profil `hybrid` / `local-dev` — Ollama + Gateway | `sudo systemctl start ollama && make run` |
|
||||||
|
| LLM-Backend → Ollama wechseln | `make llm-ollama` (→ § 4.7) |
|
||||||
|
| LLM-Backend → llama.cpp wechseln | `make llm-llamacpp` (→ § 4.7) |
|
||||||
| systemd-Dienst starten | `systemctl --user start voice-assistant` |
|
| systemd-Dienst starten | `systemctl --user start voice-assistant` |
|
||||||
|
|
||||||
**Stoppen:**
|
**Stoppen:**
|
||||||
|
|
@ -571,18 +573,37 @@ VA_PROFILE=local-dev make run # alles lokal (STT/TTS in-process, LLM via Ollam
|
||||||
### 4.7 Zwischen llama.cpp und Ollama wechseln
|
### 4.7 Zwischen llama.cpp und Ollama wechseln
|
||||||
|
|
||||||
Beide nutzen denselben Gateway-Provider `local-openai-compatible` (OpenAI-kompatible
|
Beide nutzen denselben Gateway-Provider `local-openai-compatible` (OpenAI-kompatible
|
||||||
API). Der Wechsel besteht daher aus drei Dingen: **(A)** den jeweils anderen
|
API). `DEFAULT_LLM_PROVIDER` bleibt beim Wechsel unverändert.
|
||||||
Backend-Prozess stoppen (beide teilen sich den GPU-Speicher), **(B)** das gewünschte
|
|
||||||
Backend starten, **(C)** die drei `LOCAL_LLM_*`-Zeilen in `.env` umstellen und das
|
#### Schnellster Weg: Make-Targets (empfohlen)
|
||||||
Gateway neu starten. `DEFAULT_LLM_PROVIDER` bleibt unverändert.
|
|
||||||
|
```bash
|
||||||
|
make llm-ollama # -> Ollama (Default-Modell gemma3:latest)
|
||||||
|
make llm-llamacpp # -> llama.cpp (Alias va_llm)
|
||||||
|
|
||||||
|
# Anderes Ollama-Modell:
|
||||||
|
OLLAMA_MODEL=qwen2.5:latest make llm-ollama
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Target erledigt automatisch alle Schritte: es gibt den GPU-Speicher des anderen
|
||||||
|
Backends frei (llama.cpp-Container stoppen bzw. geladene Ollama-Modelle entladen — der
|
||||||
|
Ollama-*Dienst* bleibt für andere Nutzungen laufen), startet das gewünschte Backend,
|
||||||
|
passt die `LOCAL_LLM_*`-Zeilen in `.env` an und startet das Gateway neu (als Dienst)
|
||||||
|
bzw. weist auf den manuellen Neustart hin. Skript: `scripts/llm-server/switch-llm.sh`.
|
||||||
|
|
||||||
|
> **Warum der Gateway-Neustart nötig ist:** Das `Makefile` exportiert die `.env`-Werte
|
||||||
|
> als echte Umgebungsvariablen an `uvicorn` — und Env-Variablen haben **Vorrang vor der
|
||||||
|
> `.env`-Datei**. Eine reine `.env`-Änderung wirkt daher erst, wenn das Gateway neu
|
||||||
|
> gestartet wird (uvicorn `--reload` reagiert nur auf Code-, nicht auf `.env`-Änderungen).
|
||||||
|
> Starte es **in einer frischen Shell** neu (`make run`) bzw. als Dienst:
|
||||||
|
> `systemctl --user restart voice-assistant.service`.
|
||||||
|
|
||||||
|
#### Manuell (was die Targets im Hintergrund tun)
|
||||||
|
|
||||||
**Merkhilfe:**
|
**Merkhilfe:**
|
||||||
- llama.cpp = Docker-Container `va_llm` → `make llm-up` / `make llm-down` (Port 8001)
|
- llama.cpp = Docker-Container `va_llm` → `make llm-up` / `make llm-down` (Port 8001)
|
||||||
- Ollama = systemd-Dienst → `sudo systemctl start/stop ollama` (Port 11434)
|
- Ollama = systemd-Dienst → `sudo systemctl start/stop ollama` (Port 11434)
|
||||||
|
GPU freigeben ohne Dienst-Stopp: `ollama stop <modell>`
|
||||||
> **Wichtig:** `.env`-Änderungen werden erst bei einem **Gateway-Neustart** wirksam
|
|
||||||
> (uvicorn `--reload` lädt nur bei Code-Änderungen neu, nicht bei `.env`). Als Dienst:
|
|
||||||
> `systemctl --user restart voice-assistant.service`.
|
|
||||||
|
|
||||||
#### Von llama.cpp → Ollama wechseln
|
#### Von llama.cpp → Ollama wechseln
|
||||||
|
|
||||||
|
|
|
||||||
12
Makefile
12
Makefile
|
|
@ -8,7 +8,7 @@ HOST ?= 0.0.0.0
|
||||||
|
|
||||||
CONTAINER_NAME ?= va_llm
|
CONTAINER_NAME ?= va_llm
|
||||||
|
|
||||||
.PHONY: ensure-env install run start stop restart test smoke docker-build llm-up llm-down llm-status
|
.PHONY: ensure-env install run start stop restart test smoke docker-build llm-up llm-down llm-status llm-ollama llm-llamacpp
|
||||||
|
|
||||||
ensure-env:
|
ensure-env:
|
||||||
@if [ ! -f .env ] && [ -f .env.example ]; then \
|
@if [ ! -f .env ] && [ -f .env.example ]; then \
|
||||||
|
|
@ -63,3 +63,13 @@ llm-down:
|
||||||
|
|
||||||
llm-status:
|
llm-status:
|
||||||
bash scripts/llm-server/status-llm-server.sh
|
bash scripts/llm-server/status-llm-server.sh
|
||||||
|
|
||||||
|
# --- LLM-Backend wechseln (Ollama <-> llama.cpp) -----------------------------
|
||||||
|
# Passt die LOCAL_LLM_*-Zeilen in .env an, gibt den GPU-Speicher des anderen
|
||||||
|
# Backends frei, startet das gewuenschte und startet das Gateway (falls Dienst) neu.
|
||||||
|
# Modell ueberschreibbar: OLLAMA_MODEL=qwen2.5:latest make llm-ollama
|
||||||
|
llm-ollama:
|
||||||
|
bash scripts/llm-server/switch-llm.sh ollama
|
||||||
|
|
||||||
|
llm-llamacpp:
|
||||||
|
bash scripts/llm-server/switch-llm.sh llamacpp
|
||||||
|
|
|
||||||
91
scripts/llm-server/switch-llm.sh
Executable file
91
scripts/llm-server/switch-llm.sh
Executable file
|
|
@ -0,0 +1,91 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Wechselt das lokale LLM-Backend zwischen Ollama und llama.cpp.
|
||||||
|
# Aufruf: switch-llm.sh ollama | llamacpp
|
||||||
|
#
|
||||||
|
# Das Skript (1) gibt den GPU-Speicher des jeweils anderen Backends frei,
|
||||||
|
# (2) startet das gewuenschte Backend, (3) passt die aktiven LOCAL_LLM_*-Zeilen
|
||||||
|
# in .env an und (4) sorgt dafuer, dass das Gateway die .env neu liest
|
||||||
|
# (Dienst-Neustart, sonst Hinweis). Provider bleibt 'local-openai-compatible'.
|
||||||
|
#
|
||||||
|
# Modelle/Ports ueber ENV ueberschreibbar, z. B.:
|
||||||
|
# OLLAMA_MODEL=qwen2.5:latest scripts/llm-server/switch-llm.sh ollama
|
||||||
|
|
||||||
|
TARGET="${1:-}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
ENV_FILE="$ROOT_DIR/.env"
|
||||||
|
|
||||||
|
OLLAMA_BASE_URL="${OLLAMA_BASE_URL:-http://127.0.0.1:11434/v1}"
|
||||||
|
OLLAMA_MODEL="${OLLAMA_MODEL:-gemma3:latest}"
|
||||||
|
LLAMACPP_BASE_URL="${LLAMACPP_BASE_URL:-http://127.0.0.1:8001/v1}"
|
||||||
|
LLAMACPP_MODEL="${LLAMACPP_MODEL:-va_llm}"
|
||||||
|
CONTAINER_NAME="${CONTAINER_NAME:-va_llm}"
|
||||||
|
|
||||||
|
# Setzt eine aktive (unkommentierte) KEY=VALUE-Zeile in .env (kommentierte # KEY bleiben unberuehrt).
|
||||||
|
set_env() {
|
||||||
|
local key="$1" val="$2"
|
||||||
|
if grep -qE "^${key}=" "$ENV_FILE" 2>/dev/null; then
|
||||||
|
sed -i "s|^${key}=.*|${key}=${val}|" "$ENV_FILE"
|
||||||
|
else
|
||||||
|
printf '%s=%s\n' "$key" "$val" >> "$ENV_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Entlaedt alle in Ollama geladenen Modelle (gibt GPU frei) -- der Dienst bleibt laufen.
|
||||||
|
unload_ollama_models() {
|
||||||
|
local loaded
|
||||||
|
loaded="$(ollama ps 2>/dev/null | awk 'NR>1 {print $1}')" || true
|
||||||
|
for m in $loaded; do
|
||||||
|
echo "[*] Entlade Ollama-Modell: $m"
|
||||||
|
ollama stop "$m" >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
restart_gateway() {
|
||||||
|
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||||
|
if systemctl --user is-active --quiet voice-assistant.service 2>/dev/null; then
|
||||||
|
echo "[*] Starte Gateway-Dienst neu (liest .env neu) ..."
|
||||||
|
systemctl --user restart voice-assistant.service
|
||||||
|
else
|
||||||
|
echo "[!] Gateway laeuft nicht als Dienst (vermutlich 'make run' im Vordergrund)."
|
||||||
|
echo " -> Dort neu starten, damit die neue .env greift:"
|
||||||
|
echo " Strg+C, dann in einer FRISCHEN Shell: make run"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$TARGET" in
|
||||||
|
ollama)
|
||||||
|
echo "[*] Wechsel auf OLLAMA (Modell: $OLLAMA_MODEL)"
|
||||||
|
if docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1; then
|
||||||
|
echo "[*] llama.cpp-Container '$CONTAINER_NAME' gestoppt (GPU frei)."
|
||||||
|
else
|
||||||
|
echo "[*] llama.cpp lief nicht."
|
||||||
|
fi
|
||||||
|
if ! curl -s -m 5 -o /dev/null "${OLLAMA_BASE_URL%/v1}/api/tags" 2>/dev/null; then
|
||||||
|
echo "[*] ollama-Dienst nicht erreichbar -> starte ihn ..."
|
||||||
|
sudo systemctl start ollama || true
|
||||||
|
fi
|
||||||
|
set_env LOCAL_LLM_BASE_URL "$OLLAMA_BASE_URL"
|
||||||
|
set_env LOCAL_LLM_API_KEY "ollama"
|
||||||
|
set_env LOCAL_LLM_MODEL "$OLLAMA_MODEL"
|
||||||
|
echo "[*] .env -> $OLLAMA_BASE_URL | Modell $OLLAMA_MODEL"
|
||||||
|
;;
|
||||||
|
llamacpp)
|
||||||
|
echo "[*] Wechsel auf LLAMA.CPP (Modell-Alias: $LLAMACPP_MODEL)"
|
||||||
|
unload_ollama_models
|
||||||
|
bash "$SCRIPT_DIR/start-llm-server.sh"
|
||||||
|
set_env LOCAL_LLM_BASE_URL "$LLAMACPP_BASE_URL"
|
||||||
|
set_env LOCAL_LLM_API_KEY "dummy"
|
||||||
|
set_env LOCAL_LLM_MODEL "$LLAMACPP_MODEL"
|
||||||
|
echo "[*] .env -> $LLAMACPP_BASE_URL | Modell $LLAMACPP_MODEL"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Aufruf: $0 ollama|llamacpp" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
restart_gateway
|
||||||
|
echo "[✓] LLM-Backend auf '$TARGET' umgestellt."
|
||||||
Loading…
Add table
Add a link
Reference in a new issue