# Voice Assistant Gateway Modulares FastAPI-Gateway für einen **seniorengerechten Sprachassistenten** — cloud-first, aber hybrid/lokal betreibbar, mit austauschbaren STT-/LLM-/TTS-Providern. Jede Achse — Hardware, Betrieb, Software — ist frei konfigurierbar, ohne Code zu ändern. --- ## Features - **Sprach-Pipeline:** STT → Input-Cleaner → LLM → Spoken-Adapter → TTS-Normalizer → TTS - **Provider austauschbar** über Registry: OpenRouter (Cloud), faster-whisper (STT lokal), piper (TTS lokal, schnell), chatterbox (TTS lokal, hohe Qualität + Voice-Cloning) - **Geschichtete Konfiguration** mit Profilen (`cloud` / `hybrid` / `local-dev`) - **Routing auf jeder Ebene:** Global → Profil → Nutzer → Session → Request - **Authentifizierung** (Bearer-Token) + persistente Nutzer/Sessions (SQLite) - **Resilienz:** Fallback-Ketten je Modul + In-Memory-Metriken (JSON + Prometheus) - **Gesprächsgedächtnis** pro Session (Verlauf) + Langzeit-Erinnerungen pro Nutzer (manuell + automatisch) - **WebSocket-Streaming:** Token-Streaming (LLM), Audio-Streaming (satzweises TTS), Sprach-Eingang, VAD, Barge-in - **Notfall-Eskalation:** zweistufig (Stichwörter + LLM-Klassifikation im Hintergrund) - **Web-Interface** unter `/` (Tailwind, kein Build, mobiltauglich) - **Keine Secrets im Code** — API-Keys nur über die Umgebung --- ## Schnellstart (30 Sekunden) ```bash python3 -m venv .venv && source .venv/bin/activate pip install -U pip && pip install -e .[test] cp config/voice-assistant.example.toml config/voice-assistant.toml export OPENROUTER_API_KEY=sk-or-v1-... # für Cloud/Hybrid; bei local-dev nicht nötig make run ``` Fehlt `.env`, wird sie aus `.env.example` erzeugt. Gateway läuft auf `http://localhost:8080` (oder dem in `.env` gesetzten `PORT`). ```bash curl http://localhost:8080/health # {"status":"ok"} curl http://localhost:8080/api/config # aktives Profil + aufgelöste Provider ``` Sprechen → Antwort hören (CLI-Loop): ```bash python scripts/voice_loop.py --session mein-gespraech ``` Web-Interface: Browser → `http://localhost:8080/` --- ## Starten — alle Szenarien ### Profil `cloud` (nur Gateway, alles via OpenRouter) ```bash make run # Gateway auf PORT aus .env (Standard: 8080) VA_PROFILE=cloud make run # Profil explizit setzen (überschreibt .env) PORT=8003 make run # anderen Port für diesen Start LOG_LEVEL=debug make run # ausführlichere Logs ``` ### Profil `hybrid` / `local-dev` mit llama.cpp (Docker + GPU) ```bash # 1) LLM-Server starten make llm-up # Default: GPU 1, Port 8001, Modell qwen3-35B-Uncensored make llm-status # warten bis „Modell bereit" + HTTP 200 erscheint make llm-down # stoppen # Mit anderen Parametern (via ENV): GPU_DEVICE=0 make llm-up HOST_PORT=8101 GPU_DEVICE=2 make llm-up GPU_DEVICE=0 MODEL_REL_PATH="models/qwen3/anderes-modell.gguf" make llm-up # Direkt (ohne make): bash scripts/llm-server/start-llm-server.sh GPU_DEVICE=0 bash scripts/llm-server/start-llm-server.sh # 2) Gateway starten VA_PROFILE=hybrid make run # STT/TTS cloud, LLM lokal VA_PROFILE=local-dev make run # alles lokal (STT/TTS in-process) ``` ENV-Optionen für `make llm-up` / `start-llm-server.sh`: | Variable | Default | Bedeutung | |----------|---------|-----------| | `GPU_DEVICE` | `1` | GPU-Index (0-basiert) | | `HOST_PORT` | `8001` | Host-Port des LLM-Servers | | `MODEL_REL_PATH` | `models/qwen3/Qwen3.6-35B-...Q4_K_M.gguf` | Modellpfad relativ zu `HF_HOME` | | `HF_HOME` | `~/nvme2n1p7_home/huggingface` | Modell-Basisverzeichnis | | `MODEL_ALIAS` | `va_llm` | OpenAI-API-Modellname (→ `LOCAL_LLM_MODEL` in `.env`) | | `CONTAINER_NAME` | `va_llm` | Docker-Containername | > Wird `HOST_PORT` oder `MODEL_ALIAS` geändert, müssen `LOCAL_LLM_BASE_URL` und > `LOCAL_LLM_MODEL` in `.env` entsprechend angepasst werden. ### Profil `hybrid` / `local-dev` mit Ollama ```bash # 1) Ollama-Dienst starten sudo systemctl start ollama # empfohlen (bei systemd-Installation) # oder im Vordergrund: ollama serve # 2) Modell herunterladen (einmalig, ~20 GB): ollama pull qwen3:30b-a3b # Thinking deaktiviert (empfohlen) # kleinere Alternative (CPU-tauglich, ~5 GB): ollama pull qwen3:8b # Status prüfen: ollama list # installierte Modelle ollama ps # gerade aktive Modelle (mit VRAM-Verbrauch) # 3) .env anpassen (einmalig): # LOCAL_LLM_BASE_URL=http://127.0.0.1:11434/v1 # LOCAL_LLM_API_KEY=ollama # LOCAL_LLM_MODEL=qwen3:30b-a3b ← exakter Name aus 'ollama list' # 4) Gateway starten: VA_PROFILE=hybrid make run VA_PROFILE=local-dev make run ``` ### Stoppen ```bash make stop # Gateway (alle Varianten) + llama.cpp-Container # Einzeln: Strg + C # Gateway im Vordergrund pkill -f "uvicorn app.main:app" # Gateway im Hintergrund systemctl --user stop voice-assistant # Gateway als systemd-Dienst make llm-down # nur llama.cpp sudo systemctl stop ollama # nur Ollama ``` ### Neu starten (alles) ```bash make restart # make stop + make start (llama.cpp + Gateway) # Nur Gateway neu (llama.cpp läuft weiter): systemctl --user restart voice-assistant ``` ### Backend wechseln (llama.cpp ↔ Ollama) Beide Server können nicht gleichzeitig laufen (geteilter GPU-Speicher). ```bash # → zu llama.cpp wechseln (Ollama vorher killen): sudo systemctl stop ollama && pkill -f "ollama serve" 2>/dev/null || true make llm-up && make llm-status # → zu Ollama wechseln (llama.cpp vorher killen): make llm-down # oder: docker rm -f va_llm sudo systemctl start ollama ``` ### Alle `make`-Targets im Überblick ```bash make install # venv anlegen + Abhängigkeiten installieren make run # Gateway starten (uvicorn --reload, Port aus .env) make start # llama.cpp + Gateway starten (hybrid/local-dev) make stop # alles stoppen (Gateway + llama.cpp) make restart # make stop + make start make test # Pytest-Suite (offline, kostenlos) make smoke # Live-End-to-End-Test gegen OpenRouter (geringe Kosten) make llm-up # llama.cpp-Docker-Container starten make llm-down # llama.cpp-Container stoppen make llm-status # Container- und HTTP-Status prüfen ``` --- ## Dokumentation | Dokument | Zielgruppe | Inhalt | |----------|-----------|--------| | **[BEDIENUNGSANLEITUNG.md](BEDIENUNGSANLEITUNG.md)** | alle | Installation, Betriebsprofile, Bedienung, Konfiguration, Admin, Deployment, Fehlerbehebung, Referenz | | **[Docs/voice-assistant-architecture.md](Docs/voice-assistant-architecture.md)** | Entwickler | Architekturprinzipien, Interfaces, Pipeline, Roadmap, Verzeichnisstruktur | | **[deploy/README.md](deploy/README.md)** | Admin | Remote-Betrieb: nginx, YunoHost-SSO, systemd, Firewall, Chatterbox | **Einstiegspunkte je Zielgruppe:** - 👤 **Endnutzer** → BEDIENUNGSANLEITUNG § 5 (Bedienung) - 🔧 **Admin/Betreiber** → BEDIENUNGSANLEITUNG § 2–4 (Installation + Profile), § 7–11 (Betrieb) - 💻 **Entwickler** → BEDIENUNGSANLEITUNG § 2 + Architektur-Dokument --- ## Projektstruktur (Kurzform) ```text app/ Gateway: config, api/, core/, audio/, pipeline/, providers/ config/ voice-assistant.example.toml (lokale .toml ist gitignored) deploy/ systemd-Unit, nginx-Vorlage, env-Beispiel scripts/ voice_loop.py, chat_client.py, smoke_e2e.py, add_pronunciation.py scripts/llm-server/ start/stop/status-llm-server.sh (llama.cpp-Docker) tests/ Pytest-Suite (offline + smoke) Docs/ Architektur-Dokument ``` --- ## Lizenz **Proprietär — alle Rechte vorbehalten.** Siehe [LICENSE.md](LICENSE.md).