my_voice_assistant/BEDIENUNGSANLEITUNG.md

513 lines
14 KiB
Markdown
Raw Normal View History

# Bedienungsanleitung — Voice Assistant
## Inhaltsverzeichnis
1. [Voraussetzungen](#1-voraussetzungen)
2. [Installation der Abhängigkeiten](#2-installation-der-abhängigkeiten)
3. [Schnellstart](#3-schnellstart)
4. [Die fünf Zustände](#4-die-fünf-zustände)
5. [Steuer-Wörter](#5-steuer-wörter)
6. [Alle Kommandozeilenoptionen](#6-alle-kommandozeilenoptionen)
7. [Mikrofon wählen](#7-mikrofon-wählen)
8. [Audio-Ausgang wählen](#8-audio-ausgang-wählen)
9. [LLM-Backend konfigurieren](#9-llm-backend-konfigurieren)
10. [Sprache und Stimme](#10-sprache-und-stimme)
11. [Standalone-Werkzeuge](#11-standalone-werkzeuge)
12. [Tipps und Fehlerbehebung](#12-tipps-und-fehlerbehebung)
---
## 1. Voraussetzungen
### Hardware
| Komponente | Empfehlung |
|---|---|
| Mikrofon | ReSpeaker XVF3800 (Hardware-AEC, 4 Mikrofone, 48 kHz) |
| GPU | NVIDIA RTX (CUDA) für Whisper-Transkription |
| Audio-System | PipeWire mit `paplay` |
Jedes USB-Mikrofon funktioniert. Das ReSpeaker XVF3800 ist empfohlen, weil es
Hardware-seitig Echo cancellation (AEC) und Beamforming bietet — das verhindert,
dass die TTS-Ausgabe als Spracheingabe erkannt wird.
### Software
- Python 3.12+
- PipeWire als Audio-Server (`pactl`, `paplay` müssen verfügbar sein)
- CUDA-Treiber für NVIDIA-GPU
---
## 2. Installation der Abhängigkeiten
```bash
pip install faster-whisper openwakeword piper-tts sounddevice scipy langdetect openai
```
Das Whisper-Modell (`large-v3`) wird beim ersten Start automatisch heruntergeladen (~3 GB).
Piper-Stimmen werden bei Bedarf automatisch heruntergeladen (~60120 MB pro Sprache).
---
## 3. Schnellstart
```bash
# Standard: ReSpeaker-Mikrofon, llama.cpp auf localhost:8001, Deutsch
python3 assistant.py
# Ohne Wake-Word — sofort aufnahmebereit (gut zum Testen)
python3 assistant.py --no-wakeword
# Mit Ollama
python3 assistant.py --backend ollama --model llama3.2
# Mit OpenAI
export OPENAI_API_KEY=sk-...
python3 assistant.py --backend openai --model gpt-4o-mini
```
Beim ersten Start werden Modelle geladen (ca. 1030 Sekunden). Danach erscheint:
```
Warte auf "Hey Jarvis" …
[LAUSCH] Warte auf "Hey Jarvis" …
```
---
## 4. Die fünf Zustände
Der Assistent durchläuft folgende Zustände. Der aktuelle Zustand wird in der
Statuszeile links in eckigen Klammern angezeigt: `[ZUSTAND] Info`
```
"Hey Jarvis"
LAUSCH ─────────────► AUFNAHME
▲ │
│ Timeout/Stopp Stille ≥5s
│ oder "over"
│ │
│ Stopp ▼
DIALOG ◄──────────── VORLESE ◄── GENERATOR
│ Vorlesen fertig Transkription
│ + LLM-Antwort
└── Sprache erkannt ──► AUFNAHME
```
### LAUSCH
Wartet auf das Wake-Word **„Hey Jarvis"**. Kein Quittungston, kein Feedback bis
das Wake-Word erkannt wird. Ein kurzer Piepton signalisiert den Übergang zu AUFNAHME.
### AUFNAHME
Nimmt die Sprache auf. Die Statuszeile zeigt die bisherige Aufnahmedauer und die
aktuelle Stille-Dauer:
```
[AUFNAHME] 3.2s (Stille 1.1s)
```
Die Aufnahme endet wenn:
- Stille ≥ `--silence-sec` (Standard: 5 Sekunden)
- Das Stop-Wort gesagt wird (Standard: „over")
- „Stopp" gesagt wird → direkt zurück zu LAUSCH (ohne Antwort)
- Maximaldauer von 60 Sekunden erreicht ist
### GENERATOR
Der Assistent sagt den Quittungssatz (Standard: „Moment, ich antworte gleich."),
während er die Transkription und den LLM-Aufruf durchführt. Auch hier ist „Stopp"
aktiv und bricht den Vorgang ab.
### VORLESE
Die Antwort wird vorgelesen. Alle **Steuer-Wörter** sind aktiv (→ Abschnitt 5).
Mehrere Sätze werden parallel synthetisiert und nahtlos abgespielt.
### DIALOG
Nach dem Vorlesen öffnet sich ein Zeitfenster (Standard: 5 Sekunden). Wird in
dieser Zeit gesprochen, geht der Assistent direkt in AUFNAHME — **ohne Wake-Word**.
So sind Rückfragen flüssig möglich. Nach Ablauf des Zeitfensters oder bei „Stopp"
kehrt der Assistent zu LAUSCH zurück.
---
## 5. Steuer-Wörter
Das Wort **„bitte"** wird vor dem Abgleich immer ignoriert (z. B. „Stopp bitte" = „Stopp").
### Während VORLESE
| Gesprochener Befehl | Wirkung |
|---|---|
| **„Stopp"** | Wiedergabe sofort abbrechen → DIALOG |
| **„Pause"** | Wiedergabe anhalten (bleibt pausiert) |
| **„Weiter"** | Nach Pause: aktuellen Satz von vorne abspielen |
| **„Noch einmal"** | Letzten Satz wiederholen |
| **„Absatz noch einmal"** | Zum Anfang des letzten Absatzes springen |
| **„Alles von vorn"** | Gesamte Antwort von Anfang an wiederholen |
### In allen anderen aktiven Zuständen
| Zustand | Befehl | Wirkung |
|---|---|---|
| AUFNAHME | **„Stopp"** | Aufnahme abbrechen → LAUSCH |
| GENERATOR | **„Stopp"** | Verarbeitung abbrechen → LAUSCH |
| DIALOG | **„Stopp"** | Dialogfenster schließen → LAUSCH |
---
## 6. Alle Kommandozeilenoptionen
```
python3 assistant.py [OPTIONEN]
```
### Eingabe
| Option | Standard | Beschreibung |
|---|---|---|
| `--mic NAME` | `respeaker` | Mikrofon: `respeaker` \| `motu` \| `camera` \| `default` \| `bluetooth` \| `<Index>` \| `<Substring>` |
| `--list-mics` | — | Alle verfügbaren Mikrofone anzeigen und beenden |
| `--silence-sec N` | `5.0` | Stille-Dauer in Sekunden bis die Aufnahme endet |
| `--stop-word WORT` | `over` | Codewort zum manuellen Beenden der Aufnahme |
| `--no-wakeword` | — | Wake-Word deaktivieren, sofort in AUFNAHME starten |
| `--wakeword-threshold N` | `0.5` | Empfindlichkeit Wake-Word-Erkennung (0.01.0) |
### LLM-Backend
| Option | Standard | Beschreibung |
|---|---|---|
| `--backend NAME` | `llama` | Backend: `llama` \| `ollama` \| `openai` |
| `--model NAME` | auto | Modellname (bei llama.cpp: automatisch vom Server) |
2026-06-16 02:21:26 +02:00
| `--api-url URL` | — | Überschreibt die Backend-URL (beliebiger OpenAI-kompatibler Endpunkt) |
| `--api-key KEY` | — | API-Key (überschreibt `OPENAI_API_KEY` / Backend-Default) |
| `--system TEXT` | (eingebaut) | System-Prompt für den Assistenten |
| `--history N` | `10` | Maximale Anzahl gespeicherter Gesprächsrunden |
### Spracherkennung (Whisper)
| Option | Standard | Beschreibung |
|---|---|---|
| `--whisper-model NAME` | `large-v3` | Whisper-Modell |
| `--gpu N` | `1` | CUDA-Index für Whisper (in `CUDA_VISIBLE_DEVICES`) |
| `--lang CODE` | `de` | Sprache der Benutzereingabe (`de`, `en`, `fr`, …) |
### Sprachausgabe (TTS)
| Option | Standard | Beschreibung |
|---|---|---|
| `--voice NAME` | `de_DE-thorsten-high` | Standard-Piper-Stimme (Fallback) |
| `--en-variant` | `us` | Englische Variante: `us` (Ryan) \| `gb` (Alan) |
| `--out NAME` | `default` | Ausgabe-Sink: `default` \| `respeaker` \| `hdmi` \| `motu` \| `bluetooth` \| `<Sink-Name>` |
| `--ack-text TEXT` | `Moment, ich antworte gleich.` | Quittungssatz im GENERATOR-Zustand |
| `--dialog-timeout N` | `5.0` | DIALOG-Fenster in Sekunden |
### Typische Kombinationen
```bash
# Entwicklung / Debugging (kein Wake-Word, kurze Stille)
python3 assistant.py --no-wakeword --silence-sec 2.0
# MOTU M2 als Mikrofon und Ausgang
python3 assistant.py --mic motu --out motu
# Englisch mit britischer Stimme
python3 assistant.py --lang en --voice en_GB-alan-medium --en-variant gb
# Empfindlicheres Wake-Word
python3 assistant.py --wakeword-threshold 0.3
# Längeres Dialogfenster
python3 assistant.py --dialog-timeout 10.0
```
---
## 7. Mikrofon wählen
```bash
# Alle verfügbaren Mikrofone anzeigen
python3 assistant.py --list-mics
# oder
python3 mic.py
```
**Vordefinierte Kurznamen:**
| Kurzname | Gerät |
|---|---|
| `respeaker` | ReSpeaker XVF3800 (Standard) |
| `motu` | MOTU M2 Mikrofon-Eingang |
| `camera` | USB-Kamera-Mikrofon (VF0680) |
| `default` | System-Standard-Eingabe (PipeWire) |
| `bluetooth` | Erstes verbundenes Bluetooth-Gerät |
Alternativ kann ein **numerischer Index** (`--mic 3`) oder ein **Substring** des
Gerätenamens (`--mic "USB Audio"`) angegeben werden.
---
## 8. Audio-Ausgang wählen
```bash
# Alle verfügbaren Ausgänge anzeigen
python3 speak.py --list
```
**Vordefinierte Kurznamen:**
| Kurzname | Gerät |
|---|---|
| `default` | PipeWire-Standard-Sink |
| `respeaker` | ReSpeaker XVF3800 3,5-mm-Klinke |
| `hdmi` | HDA NVidia HDMI |
| `motu` | MOTU M2 Ausgang |
| `bluetooth` | Erstes verbundenes Bluetooth-Gerät |
Vollständige Sink-Namen aus `pactl list sinks short` können direkt verwendet werden.
---
## 9. LLM-Backend konfigurieren
2026-06-16 02:21:26 +02:00
Der Assistent spricht mit jedem LLM, das die **OpenAI Chat-Completions API**
implementiert. Mit `--api-url` und `--api-key` kann der Endpunkt frei
überschrieben werden — das `--backend`-Flag wählt nur den Verbindungs-Default.
### llama.cpp (Standard)
```bash
# llama.cpp muss auf Port 8001 laufen
python3 assistant.py --backend llama
```
Der Modellname wird automatisch vom Server abgefragt.
2026-06-16 02:21:26 +02:00
Anderen Port oder Host angeben:
```bash
python3 assistant.py --backend llama --api-url http://192.168.1.10:8001/v1
```
2026-06-16 02:21:26 +02:00
### Ollama (lokal)
```bash
# Ollama muss laufen: ollama serve
python3 assistant.py --backend ollama --model llama3.2
python3 assistant.py --backend ollama --model mistral
```
2026-06-16 02:21:26 +02:00
### Ollama (remote / anderer Rechner)
```bash
python3 assistant.py --backend ollama \
--api-url http://mein-server:11434/v1 \
--model llama3.2
```
### OpenAI
```bash
export OPENAI_API_KEY=sk-...
python3 assistant.py --backend openai --model gpt-4o-mini
python3 assistant.py --backend openai --model gpt-4o
```
2026-06-16 02:21:26 +02:00
### OpenRouter (viele Modelle über eine API)
[OpenRouter](https://openrouter.ai) bietet Zugang zu hunderten Modellen
(Mistral, Llama, Gemma, Claude, GPT-4 u. v. m.) über eine einheitliche API.
```bash
export OPENROUTER_API_KEY=sk-or-...
python3 assistant.py \
--backend openai \
--api-url https://openrouter.ai/api/v1 \
--model mistralai/mistral-7b-instruct
```
Andere beliebte OpenRouter-Modelle:
- `meta-llama/llama-3.1-8b-instruct:free` (kostenlos)
- `google/gemma-3-27b-it`
- `anthropic/claude-3.5-haiku`
Den API-Key unter `https://openrouter.ai/keys` erstellen.
### Groq (sehr schnelle Inferenz)
```bash
export GROQ_API_KEY=gsk_...
python3 assistant.py \
--backend openai \
--api-url https://api.groq.com/openai/v1 \
--model llama-3.1-70b-versatile
```
### LM Studio
```bash
# LM Studio muss mit aktiviertem lokalen Server laufen (Port 1234)
python3 assistant.py --backend llama --api-url http://localhost:1234/v1
```
### Together AI
```bash
export TOGETHER_API_KEY=...
python3 assistant.py \
--backend openai \
--api-url https://api.together.xyz/v1 \
--model meta-llama/Llama-3-8b-chat-hf
```
### Allgemeines Prinzip
Jeder Provider, der `/v1/chat/completions` mit `stream=true` unterstützt,
funktioniert mit:
```bash
python3 assistant.py \
--backend openai \
--api-url https://<provider>/v1 \
--model <modellname> \
--api-key <api-key>
```
---
## 10. Sprache und Stimme
### Automatische Spracherkennung
Der Assistent erkennt automatisch die Sprache der LLM-Antwort und wählt die
passende Piper-Stimme. Fehlende Stimmen werden beim ersten Bedarf automatisch
heruntergeladen.
| Sprache | Stimme |
|---|---|
| Deutsch | `de_DE-thorsten-high` |
| Englisch (US) | `en_US-ryan-high` |
| Englisch (GB) | `en_GB-alan-medium` |
| Französisch | `fr_FR-upmc-medium` |
| Spanisch | `es_ES-davefx-medium` |
| Italienisch | `it_IT-paola-medium` |
| Niederländisch | `nl_NL-mls-medium` |
| Portugiesisch | `pt_BR-faber-medium` |
| Russisch | `ru_RU-ruslan-medium` |
| Polnisch | `pl_PL-bass-high` |
| Ukrainisch | `uk_UA-lada-x_low` |
| Tschechisch | `cs_CZ-jirka-medium` |
### Englische Variante wählen
Da automatische Erkennung nicht zwischen en-US und en-GB unterscheiden kann,
wird die Variante beim Start festgelegt:
```bash
python3 assistant.py --en-variant us # Standard: amerikanisches Englisch
python3 assistant.py --en-variant gb # britisches Englisch
```
### Eigene Standardstimme
Die `--voice`-Option setzt die Fallback-Stimme (wenn Spracherkennung fehlschlägt
oder die erkannte Sprache nicht in der Tabelle ist):
```bash
python3 assistant.py --voice de_DE-kerstin-low
```
---
## 11. Standalone-Werkzeuge
### speak.py — Sprachausgabe testen
```bash
# Text vorlesen
python3 speak.py --text "Hallo, ich bin dein Assistent."
# Mit bestimmter Stimme und Ausgang
python3 speak.py --text "Hello World" --voice en_US-ryan-high --out respeaker
# Text aus stdin
echo "Test" | python3 speak.py
# Alle Ausgänge anzeigen
python3 speak.py --list
# Alle verfügbaren Piper-Stimmen (Deutsch)
python3 speak.py --list-voices --voice-lang de
# Alle Stimmen aller Sprachen
python3 speak.py --list-voices --voice-lang ""
```
### transcribe.py — Transkription testen
```bash
# Live-Transkription mit ReSpeaker
python3 transcribe.py
# Mit anderem Mikrofon
python3 transcribe.py --mic motu
# Alle Mikrofone anzeigen
python3 transcribe.py --list-mics
```
### mic.py — Mikrofone anzeigen
```bash
python3 mic.py
```
---
## 12. Tipps und Fehlerbehebung
### Wake-Word wird nicht erkannt
- Lautstärke des Mikrofons erhöhen: `pactl set-source-volume <Gerät> 150%`
- Schwellenwert senken: `--wakeword-threshold 0.3`
- Zum Testen `--no-wakeword` verwenden
### Transkription ist ungenau
- Lautstärke erhöhen
- Hintergrundgeräusche reduzieren
- ReSpeaker XVF3800 verwenden (Hardware-AEC unterdrückt Lautsprecher-Echo)
- `--lang` korrekt setzen (z. B. `--lang de` für Deutsch)
### „Stopp" wird nicht erkannt
- Deutlich und mit normaler Lautstärke sprechen
- Latenz: ca. 0,51 Sekunde bis zur Reaktion (Whisper muss verarbeiten)
- In AUFNAHME: `--stop-word` ist ein anderes Wort; „Stopp" wird separat erkannt
### TTS-Stimme klingt falsch für die Sprache
- Stimme wurde mit falscher Sprache verwendet (z. B. Download fehlgeschlagen)
- Fehlermeldung erscheint im Terminal; nochmals versuchen (automatischer Retry 3×)
- Netzwerkverbindung prüfen (Stimmen werden von HuggingFace geladen)
### Piper-Stimme fehlt / Download schlägt fehl
```bash
# Verfügbare Stimmen anzeigen
python3 speak.py --list-voices --voice-lang de
# Stimme manuell laden (wird dann gecacht)
python3 speak.py --text "Test" --voice ru_RU-ruslan-medium
```
### audio: input overflow
Diese Meldung wird bewusst unterdrückt. Sie tritt auf wenn Whisper die
Verarbeitung verzögert und der PortAudio-Puffer überläuft. Das ist normal
und beeinflusst die Qualität nicht wesentlich.
### llama.cpp antwortet nicht
```bash
# Prüfen ob der Server läuft
curl http://localhost:8001/v1/models
# Modell und Port in llama.cpp-Konfiguration prüfen
```