my_voice_assistant_v3/BEDIENUNGSANLEITUNG.md
Dieter Schlüter 531b57e08d feat: Langzeit-Erinnerungen (#3b) und WebSocket-Streaming-Chat (#4, erster Increment)
#3b Langzeit-Erinnerungen:
- Store: memories-Tabelle + add/get/delete_memory (pro Nutzer)
- API: GET/POST/DELETE /api/me/memories
- chat.py injiziert Nutzer-Erinnerungen als System-Kontext ins LLM (sessionunabhaengig)
- ?debug zeigt memories_len

#4 Echtzeit (erster Increment):
- WS /ws/chat: dauerhafter Kanal, Event-Folge ack -> semantic -> audio (binaer) -> done
- Auth (Token-Query), Session-Gedaechtnis und Erinnerungen wie bei POST /api/chat
- Fehler als error-Event (422/403/502)

- Tests: 38 gruen (Erinnerungs-CRUD/Injektion, WebSocket-Streaming/Auth)
- Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 04:26:55 +02:00

310 lines
9.4 KiB
Markdown

# Bedienungsanleitung — Voice Assistant Gateway
Diese Anleitung führt Schritt für Schritt durch Installation, Start, Konfiguration
und Fehlerbehebung. Technische Hintergründe stehen im
[Architektur-Dokument](Docs/voice-assistant-architecture.md), eine kompakte
Übersicht im [README](README.md).
---
## 1. Voraussetzungen
- **Python 3.11 oder neuer** (`python3 --version`)
- Ein **OpenRouter-API-Key** — nur nötig, wenn ein Profil entfernte KI nutzt
(`hybrid`, `cloud`). Für rein lokalen Betrieb (`local-dev`) nicht erforderlich.
- Optional: Docker, falls im Container betrieben.
---
## 2. Installation
```bash
cd voice-assistant-scaffold
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .[test]
```
Danach die zentrale Konfigurationsdatei anlegen:
```bash
cp config/voice-assistant.example.toml config/voice-assistant.toml
```
---
## 3. API-Key hinterlegen (für Cloud/Hybrid)
Der Schlüssel wird **aus der Umgebung** gelesen und gehört **nicht** in eine Datei.
Dauerhaft am besten in `~/.bashrc`:
```bash
echo 'export OPENROUTER_API_KEY=sk-or-v1-DEIN_KEY' >> ~/.bashrc
chmod 600 ~/.bashrc
source ~/.bashrc
```
Prüfen, ob er ankommt:
```bash
echo ${OPENROUTER_API_KEY:0:8} # zeigt nur den Anfang
```
> **Sicherheit:** Den Key niemals in `.env` oder `config/*.toml` schreiben. Wird ein
> Key versehentlich öffentlich, im OpenRouter-Dashboard löschen (= widerrufen) und
> neu erzeugen.
---
## 4. Betriebsart (Profil) wählen
Profile bestimmen, welche KI-Module genutzt werden:
| Profil | Bedeutung | Key nötig? |
|-------------|--------------------------------------------|------------|
| `local-dev` | alles lokal (eigene KI/Hardware) | nein |
| `hybrid` | STT/TTS über Cloud, Haupt-LLM lokal | ja |
| `cloud` | alles über OpenRouter (Standardbetrieb) | ja |
Profil **einmalig** für einen Start:
```bash
VA_PROFILE=cloud make run
```
Profil **dauerhaft** — in `.env` eintragen:
```
VA_PROFILE=cloud
```
> Hinweis: Stehen in `.env` noch `DEFAULT_STT_PROVIDER` / `DEFAULT_LLM_PROVIDER` /
> `DEFAULT_TTS_PROVIDER`, überschreiben diese das Profil. Für profilbasiertes
> Umschalten sollten sie auskommentiert sein.
---
## 5. Starten und Stoppen
```bash
make run
```
Standard-Adresse: `http://localhost:8080` (Port änderbar, siehe Abschnitt 8).
Beenden mit **Strg + C**.
Schnelltest in einem zweiten Terminal:
```bash
curl http://localhost:8080/health
# {"status":"ok"}
curl http://localhost:8080/api/config
# zeigt aktives Profil und die aufgelöste Standard-Route
```
---
## 6. Tägliche Bedienung — typische Aufgaben
### a) Text sprechen lassen (`/api/speak`)
```bash
curl -X POST http://localhost:8080/api/speak \
-H 'Content-Type: application/json' \
-d '{"text":"Guten Morgen, wie geht es Ihnen?"}' \
--output antwort.pcm
```
### b) Chatten (Text rein, gesprochene Antwort raus) (`/api/chat`)
Nur den Trace als JSON ansehen (ohne Audio):
```bash
curl -X POST "http://localhost:8080/api/chat?debug=true" \
-H 'Content-Type: application/json' \
-d '{"text":"Wie wird das Wetter morgen?"}'
```
Komfortabler mit dem mitgelieferten Client (spielt die Antwort ab):
```bash
python chat_client.py "Erzähl mir einen guten Morgen-Spruch"
```
> `chat_client.py` erwartet den Dienst auf Port **8003** — bei Bedarf im Skript
> `GATEWAY_URL` anpassen oder den Dienst mit `PORT=8003 make run` starten.
**Fortlaufendes Gespräch (Gedächtnis):** Wird eine `session_id` mitgegeben, merkt
sich der Assistent den Verlauf und bezieht ihn in die nächste Antwort ein:
```bash
curl -X POST "http://localhost:8080/api/chat?session_id=oma-anna&debug=true" \
-H 'Content-Type: application/json' -d '{"text":"Ich heiße Anna."}'
curl -X POST "http://localhost:8080/api/chat?session_id=oma-anna&debug=true" \
-H 'Content-Type: application/json' -d '{"text":"Wie war noch mein Name?"}'
```
Ohne `session_id` ist jeder Aufruf eigenständig (kein Gedächtnis). Wie viele
zurückliegende Nachrichten einfließen, steuert `HISTORY_MAX_MESSAGES` (Standard 10).
### c) Audio transkribieren (`/api/transcribe`)
```bash
curl -X POST http://localhost:8080/api/transcribe \
-F "file=@aufnahme.wav" -F "language=de"
```
### d) Gerät oder Provider einmalig umstellen (pro Aufruf)
```bash
curl -X POST http://localhost:8080/api/speak \
-H 'Content-Type: application/json' \
-d '{"text":"Test","tts_provider":"piper","output_endpoint":"loopback"}'
```
### e) Präferenzen für eine Session festlegen
```bash
# einmal setzen
curl -X POST http://localhost:8080/api/sessions/oma-anna/route \
-H 'Content-Type: application/json' \
-d '{"llm_provider":"openrouter","language":"de"}'
# danach mit dieser Session nutzen
curl -X POST "http://localhost:8080/api/chat?session_id=oma-anna&debug=true" \
-H 'Content-Type: application/json' -d '{"text":"Hallo!"}'
```
---
## 7. Verfügbare Geräte und Bausteine ansehen
```bash
curl http://localhost:8080/api/devices # Audio-Endpunkte mit Fähigkeiten
curl http://localhost:8080/api/config # Profil, Route, Provider, Endpunkte
```
---
## 8. Port ändern
```bash
PORT=8003 make run # einmalig
sed -i 's/^PORT=.*/PORT=8003/' .env # dauerhaft
```
---
## 9. Mit Docker betreiben
```bash
export OPENROUTER_API_KEY=sk-or-v1-...
docker compose up --build
```
Der Key wird aus der Shell in den Container durchgereicht; fehlt er, bricht der
Start mit klarer Meldung ab.
---
## 10. Authentifizierung & Mehrbenutzer
Im Produktivbetrieb ist `AUTH_ENABLED=true` (Standard). Dann brauchen
`chat`/`speak`/`transcribe`/`sessions`/`me` ein **Bearer-Token pro Nutzer**.
Nutzer und Sessions werden in einer SQLite-Datei gespeichert (`DB_PATH`, Standard
`data/voice-assistant.db`).
**Schritt 1 — Admin-Schlüssel setzen** (nur über die Umgebung):
```bash
export ADMIN_API_KEY=ein-langes-geheimnis
```
**Schritt 2 — Nutzer anlegen** (Token erscheint **nur einmal**, sicher notieren):
```bash
curl -X POST http://localhost:8080/api/admin/users \
-H "X-Admin-Key: $ADMIN_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"display_name":"Oma Anna"}'
```
**Schritt 3 — mit Token nutzen:**
```bash
TOKEN=<das-token-von-oben>
curl http://localhost:8080/api/me -H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:8080/api/speak \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"text":"Guten Morgen!"}'
```
**Dauerhafte Vorlieben** eines Nutzers (Gerät/Provider/Sprache) setzen:
```bash
curl -X PUT http://localhost:8080/api/me/prefs \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"language":"de","llm_provider":"openrouter"}'
```
Diese Vorlieben gelten automatisch für alle Aufrufe dieses Nutzers (Ebene zwischen
Profil und Session). Eine fremde Session zu nutzen, wird mit `403` abgelehnt.
**Langzeit-Erinnerungen** (dauerhafte Fakten/Vorlieben, gelten über alle Gespräche):
```bash
# anlegen
curl -X POST http://localhost:8080/api/me/memories \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"content":"Mag morgens Kamillentee."}'
# auflisten / löschen
curl http://localhost:8080/api/me/memories -H "Authorization: Bearer $TOKEN"
curl -X DELETE http://localhost:8080/api/me/memories/1 -H "Authorization: Bearer $TOKEN"
```
Diese Erinnerungen gibt der Assistent bei jedem Chat als Kontext mit — auch ohne
`session_id`.
**Echtzeit-Chat über WebSocket** (`/ws/chat`): dauerhafter Kanal, pro Nachricht
`{"text": "..."}`; Antwort kommt als Event-Folge (`ack`, `semantic`, Audio, `done`).
Token per Query (`?token=…`), Gedächtnis per `?session_id=…`.
> **Für lokale Entwicklung** ist in der mitgelieferten `.env` `AUTH_ENABLED=false`
> gesetzt — dann ist kein Token nötig (anonymer Nutzer).
---
## 11. Fehlerbehebung
| Symptom | Ursache | Lösung |
|---|---|---|
| `OPENROUTER_API_KEY is empty` | Key nicht in der Umgebung | `export OPENROUTER_API_KEY=…`, neues Terminal / `source ~/.bashrc` |
| HTTP **401** „Bearer token required/Invalid token" | Auth an, Token fehlt/falsch | gültiges Token im Header `Authorization: Bearer …`, oder `AUTH_ENABLED=false` für dev |
| HTTP **401** bei `/api/admin/users` | falscher/fehlender Admin-Key | `X-Admin-Key` mit `ADMIN_API_KEY` abgleichen |
| HTTP **403** bei `?session_id=…` | Session gehört anderem Nutzer | eigene `session_id` verwenden |
| HTTP **503** bei `/api/admin/users` | `ADMIN_API_KEY` nicht gesetzt | Admin-Key in der Umgebung setzen |
| HTTP **422** „Unbekannter …-Provider/Endpunkt" | Tippfehler in `*_provider` / `*_endpoint` | gültige Werte via `GET /api/config` prüfen |
| `VA_PROFILE` wirkt nicht | `DEFAULT_*_PROVIDER` in `.env` überschreibt es | diese Zeilen in `.env` auskommentieren |
| LLM-Timeout / Connection refused (lokal) | lokaler LLM-Server (Port 11434) läuft nicht | LLM-Server starten oder Profil `cloud` wählen |
| `Address already in use` | Port belegt | anderen `PORT` setzen (Abschnitt 8) |
| `chat_client.py` bekommt keine Antwort | Client nutzt Port 8003 | Dienst mit `PORT=8003` starten oder `GATEWAY_URL` anpassen |
| Profil greift nicht / Standardwerte | `config/voice-assistant.toml` fehlt | Datei aus `*.example.toml` kopieren (Abschnitt 2) |
Logs erscheinen im Terminal, in dem `make run` läuft. Für mehr Details
`LOG_LEVEL=debug` in `.env` setzen.
---
## 12. Tests ausführen
```bash
make test
```
Alle Tests sollten grün sein. Schlägt etwas fehl, gibt die Ausgabe den genauen
Testnamen und die Ursache an.