voice-agent/README.md
root bc497a1665 docs+install: vollständiger Installer + aktuelle README
Mac-Worker:
- install-launchagent.sh legt jetzt selbst venv + Dependencies an, statt
  das vorauszusetzen — ein Befehl reicht für komplette Erstinstallation
- modernes launchctl bootout/bootstrap/kickstart statt unload/load
  (alte Variante wirft auf neueren macOS-Versionen "Input/output error 5")
- neuer Sub-Befehl "restart" zum Neustarten ohne Reinstall
- neues update.sh: git pull + pip install + kickstart + Health in einem Schritt

LXC:
- install.sh ALLOWED_EXTS-Check verhindert wiederholtes ",webm"-Anhängen
- bessere Abschluss-Ausgabe mit echter Host-IP, Update-Anweisung, Diagnose-Hinweis

Docs:
- Haupt-README: aktueller Funktionsstand (Auth, PDF, Profile, Mobile/PWA,
  Diagnose, Retry alle als done markiert), Installation auf neuen Stand gebracht
- Profile-Tabelle mit allen 17 Profilen
- API-Listen vervollständigt (diag, preload, log, pdf, profiles)
- Datenfluss-Skizze mit Preload + Heartbeat + X-Job-Id beschrieben

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:36:35 +00:00

288 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Voice-Agent
Self-hosted Transkriptions- und Protokollsystem für Sprachaufzeichnungen — vollständig lokal, DSGVO-konform.
> Vollständiges Lastenheft: siehe [`need.md`](need.md)
## Architektur
```
Benutzer (Browser / Handy-PWA)
▼ HTTPS (selbst-signiert, Mikrofon-fähig)
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ LXC-Container (Linux) │ HTTP │ Mac (Apple Silicon) │
│ - FastAPI + HTML/JS UI │ ──────► │ - FastAPI Worker │
│ - SQLite Job-Store + Auth │ │ - lightning-whisper-mlx │
│ - Profile (YAML, ≥17) │ │ - Ollama (Standard 8B) │
│ - Result-/Upload-Verz. │ ◄────── │ - python-docx + reportlab │
│ - Nginx HTTPS-Reverse-Proxy │ │ - Per-Job Log-Ringbuffer │
└──────────────────────────────┘ └──────────────────────────────┘
```
- **LXC**: keine AI-Verarbeitung — nur Uploads, Job-Tracking, Login, Auslieferung.
- **Mac**: Stateless API. Erhält Audio/Text, gibt Transkripte / Zusammenfassungen / Protokolle / DOCX / PDF zurück.
## Funktionsumfang (aktueller Stand)
- [x] Audio-Upload (MP3, WAV, M4A, MP4, OGG, FLAC, WEBM — max. 500 MB)
- [x] Mobile-First-Layout + PWA mit Mikrofon-Aufnahme (Start / Pause / Stop)
- [x] Whisper-Transkription auf dem Mac (MLX, Apple Neural Engine)
- [x] Ollama-Zusammenfassung
- [x] Strukturiertes Protokoll je Profil
- [x] **17 Verarbeitungs-Profile** (Sitzung, Diktat, Pflegedoku, IT-Ticket, Sales-Call, …)
- [x] **DOCX- und PDF-Export**
- [x] **Benutzer-Verwaltung** (bcrypt, Cookie-Sessions, Per-User-Job-Isolation, Admin-Rolle)
- [x] **HTTPS via selbst-signiertem Zertifikat** (Mikrofon-Zugriff am Handy)
- [x] **Idempotente Pipeline + Retry** — bei „Server disconnected" automatischer 1× Retry, Transkript wird beim manuellen Erneut-Versuchen weiterverwendet
- [x] **Diagnose-Panel pro Job** — Live-Heartbeat während laufender Mac-Calls + Mac-Worker-Log direkt in der UI
- [ ] Speaker-Diarization (Prio 2 — siehe `mac-worker/README.md`)
---
## Installation — Schritt für Schritt
Voraussetzungen:
- **Mac** (Apple Silicon empfohlen, M1/M2/M3/M4) mit min. 16 GB RAM, besser 32 GB.
- **Proxmox-Host** (oder beliebiger Linux-Host) für den LXC-Container.
- **Netzwerk**: Mac und LXC im selben LAN, der LXC muss den Mac auf Port 8080 erreichen.
### Schritt 1 — LXC-Container provisionieren (Proxmox)
Container mit:
- Debian 13 (Trixie) oder Ubuntu 24.04
- 2 vCPU, 2 GB RAM, 20 GB Disk reichen
- Statische LAN-IP, SSH-Zugang als root
### Schritt 2 — App im LXC installieren
Im Container als `root` einloggen, dann **eine** der folgenden Optionen wählen:
**Option A — Auto-Install per Curl** (Repo wird selbst geklont):
```bash
bash <(curl -sSL https://git.cynfo.net/christian/voice-agent/raw/branch/main/deploy/install.sh)
```
**Option B — Manuell aus geklontem Repo:**
```bash
git clone https://git.cynfo.net/christian/voice-agent.git /var/www/voice-agent
cd /var/www/voice-agent
./deploy/install.sh
```
Das Skript installiert idempotent:
1. apt-Pakete (`git python3-venv nginx ffmpeg openssl …`)
2. Deploy-User `deploy`, klont/aktualisiert Repo nach `/var/www/voice-agent`
3. Python-venv + Dependencies in `lxc-frontend/.venv`
4. `.env` aus Vorlage anlegen, `SESSION_SECRET` automatisch erzeugen
5. Verzeichnisse `/var/lib/voice-agent/{uploads,results}` + SQLite-DB
6. systemd-Service `voice-agent.service` (autostart, restart-on-failure)
7. Selbst-signiertes TLS-Zertifikat mit SAN (Hostname + IP)
8. Nginx HTTPS-Reverse-Proxy + HTTP→HTTPS Redirect
9. CLI-Wrapper `/usr/local/bin/voice-agent-admin`
Erneutes Ausführen aktualisiert auf den neuesten `main` (idempotent, kein Datenverlust — die SQLite-DB liegt unter `/var/lib/voice-agent/`, nicht im App-Verzeichnis).
### Schritt 3 — Mac-Worker einrichten
Auf dem Mac (Details in [`mac-worker/README.md`](mac-worker/README.md)):
```bash
# Repo holen
git clone https://git.cynfo.net/christian/voice-agent.git ~/voice-agent
cd ~/voice-agent/mac-worker
# Ollama + Modell (einmalig)
brew install ollama
launchctl setenv OLLAMA_HOST "0.0.0.0:11434"
brew services restart ollama
ollama pull llama3.1:8b
# Worker als LaunchAgent installieren — macht venv + Dependencies + Autostart in einem Rutsch
./deploy/install-launchagent.sh
```
Test vom LXC aus:
```bash
curl http://<MAC-LAN-IP>:8080/health
# erwartet: {"status":"ok","whisper_engine":"mlx","ollama_reachable":true,...}
```
### Schritt 4 — LXC mit Mac verbinden
Im LXC `MAC_API_URL` auf die Mac-LAN-IP setzen:
```bash
sudo nano /var/www/voice-agent/lxc-frontend/.env
# MAC_API_URL=http://192.168.x.y:8080
sudo systemctl restart voice-agent
```
### Schritt 5 — Erst-Anmeldung + Benutzen
Browser auf `https://<LXC-IP>/` — beim allerersten Aufruf legt die UI den initialen Admin an (Username + Passwort wählen). Bestehende Jobs werden diesem Konto zugeordnet.
Audio hochladen oder direkt in der UI aufnehmen → fertig.
---
## Update / Neudeployment
**LXC** — einfach nochmal:
```bash
sudo /var/www/voice-agent/deploy/install.sh
```
**Mac** — ein Befehl macht git-pull + pip-install + Worker-Restart + Health-Check:
```bash
~/voice-agent/mac-worker/deploy/update.sh
```
(Falls `update.sh` aus irgendeinem Grund nicht läuft, ist `./deploy/install-launchagent.sh restart` der manuelle Fallback.)
---
## Benutzer-Verwaltung / Passwort zurücksetzen
Auf dem LXC steht nach dem Deploy `voice-agent-admin` als Befehl bereit:
```bash
# Passwort zurücksetzen (z. B. Admin-Login vergessen)
sudo voice-agent-admin reset admin 'NeuesPasswort123'
# User auflisten / anlegen / löschen
sudo voice-agent-admin list
sudo voice-agent-admin create maria 'StartPasswort123'
sudo voice-agent-admin create chefin 'Geheim12345' --admin
sudo voice-agent-admin delete maria
# Passwort prüfen ohne Browser (Debug)
sudo voice-agent-admin verify admin 'NeuesPasswort123'
```
Vollständige Befehlsreferenz: [`lxc-frontend/README.md`](lxc-frontend/README.md#benutzer--und-passwort-verwaltung-per-cli).
---
## Profile
Jeder Job läuft mit einem **Verarbeitungs-Profil**, das die Prompts für Summary, Protokoll und das Layout des Exports steuert. Standard ist `meeting`. Das Standard-Profil je User wird im Web-UI im Header gewählt und bleibt gespeichert.
Mitgelieferte Profile (alle in `mac-worker/profiles/*.yaml`):
| Profil | Zweck |
|---|---|
| `meeting` | Klassisches Sitzungsprotokoll |
| `phone-call` | Telefonat-Notiz mit Beteiligten/Verabredungen |
| `memo` | Kurze Sprachnotiz / Diktat |
| `interview` | Interview mit Sprecherspuren |
| `one-on-one` | 1:1-Gespräch (Mitarbeiter / Kunde) |
| `brainstorm` | Ideen-Sammlung mit Cluster-Vorschlägen |
| `service-ticket` | IT-Service-Ticket aus Anruf-Mitschnitt |
| `incident-report` | Incident-Doku (was, wann, Auswirkung, Status) |
| `postmortem` | Post-Mortem mit Lessons-Learned |
| `site-survey` | Vor-Ort-Aufnahme (Leitungsverlauf, Hardware, Zustand) |
| `sales-call` | Sales-Gespräch mit Pain-Points / Next-Steps |
| `schichtuebergabe` | Schichtübergabe Pflege |
| `pflegedoku` | Pflegedokumentations-Eintrag |
| `sturzbericht` | Sturzbericht (Pflege) |
| `visite` | Arzt-Visite |
| `angehoerigengespraech` | Angehörigen-Gespräch (Pflege) |
| `biografie` | Biografie-Eintrag (Pflege) |
Eigene Profile: einfach eine weitere YAML-Datei in `mac-worker/profiles/` ablegen (Beispiel siehe `meeting.yaml`) und Mac-Worker neu starten.
---
## Diagnose / Troubleshooting
Wenn ein Job hängt oder fehlschlägt:
- **In der UI**: bei FAILED-Jobs und langlaufenden Stages erscheint **„Diagnose ▾"**. Aufklappen zeigt:
- aktuelle Stage und wie lange sie schon läuft
- letzter Heartbeat (alle 3 s während Mac-Calls)
- die letzten 200 Mac-Worker-Log-Zeilen für genau diesen Job
- **Auf dem LXC**:
- `systemctl status voice-agent` / `journalctl -u voice-agent -f`
- `curl -sk https://localhost/api/mac/health`
- **Auf dem Mac**:
- `~/voice-agent/mac-worker/deploy/install-launchagent.sh status`
- `tail -f ~/Library/Logs/voice-agent-worker.{out,err}.log`
Wenn der Mac mitten in `summarize` die Verbindung abreissen lässt, retried der LXC einmal automatisch (3 s Backoff) — ein vorgelagerter Preload-Aufruf hat zudem das Ollama-Modell schon ins RAM geladen, damit es nicht in der eigentlichen Generierung neu lädt.
---
## Modelle
### Transkription (Mac, Whisper)
| `WHISPER_ENGINE` | `WHISPER_MODEL` | Wann nutzen |
|---|---|---|
| `mlx` | `large-v3` (Default) | Maximale Qualität, langsamer (~0.3× Realzeit auf M2) |
| `mlx` | `distil-large-v3` | ~5× schneller, minimal schlechtere Qualität |
| `mlx` | `medium` | Schneller, deutlich schlechter bei Fachbegriffen |
| `faster` | `large-v3` | Intel-Mac / Linux / CUDA |
| `mock` | | Tests ohne Modell-Download |
Standard ist `mlx` + `large-v3`. Für lange Sitzungen lohnt sich `distil-large-v3`. Alternativen (whisper.cpp + CoreML, WhisperX mit Diarization, Voxtral) sind in [`mac-worker/README.md`](mac-worker/README.md#alternative-transkriptions-engines) dokumentiert.
### Zusammenfassung (Ollama)
Standard: `llama3.1:8b` — solide Basisqualität bei deutschen Texten, ~8 GB Speicher.
Empfohlene Alternativen je nach Hardware (alle via `ollama pull <name>` und `OLLAMA_MODEL=<name>` in `.env`):
| Modell | Größe | RAM-Bedarf | Stärken |
|---|---|---|---|
| `llama3.1:8b` (Default) | 8 B | ~8 GB | Schnell, brauchbares Deutsch |
| `qwen2.5:14b` | 14 B | ~10 GB | Sehr zuverlässige JSON-Ausgabe, exzellentes Deutsch |
| `mistral-small:24b` | 24 B | ~16 GB | Europäisch trainiert, beste Kompromiss-Wahl |
| `gemma3:12b` | 12 B | ~10 GB | Stark multilingual, gute Strukturierung |
| `gpt-oss:20b` | 20 B | ~14 GB | Sehr gute strukturierte Ausgabe (OpenAI Open-Weight) |
| `llama3.3:70b` | 70 B | ~48 GB | Top-Qualität, nur auf Macs mit 64 GB+ |
Für deutsche Protokolle mit viel JSON-Struktur ist **`qwen2.5:14b`** oder **`mistral-small:24b`** der beste Sweet-Spot auf einem Mac mit 32 GB.
Detaillierte Bewertung siehe [`mac-worker/README.md`](mac-worker/README.md#ollama-modell-wählen).
---
## Verzeichnisstruktur
```
voice-agent/
├── lxc-frontend/ # FastAPI Web-App (läuft im LXC)
│ ├── app/
│ ├── requirements.txt
│ └── .env.example
├── mac-worker/ # FastAPI AI-Worker (läuft auf dem Mac)
│ ├── app/
│ ├── profiles/ # YAML-Profile (Prompts + Layout)
│ ├── deploy/ # install-launchagent.sh, update.sh, plist-Template
│ ├── requirements.txt
│ └── .env.example
├── deploy/ # systemd / nginx / install.sh (LXC)
├── config/ # Toolkit-Konfiguration (project.env)
├── .claude/ # KI-Agenten Skills
├── need.md # Lastenheft
└── README.md
```
## Sicherheit
- Vollständig lokaler Betrieb. Keine Cloud-Calls.
- HTTPS mit selbst-signiertem Cert (für Mikrofon-Zugriff am Handy zwingend nötig).
- Web-UI ist Cookie-Session-basiert (bcrypt cost 12, signiert mit `SESSION_SECRET`).
- Mac-Worker hat **keine** Auth — Betrieb nur im internen Netz.
- Uploads / Ergebnisse unter `/var/lib/voice-agent/` — bei Bedarf Backup einplanen.
- `.env`-Dateien (LXC + Mac) sind chmod 600, enthalten Session-Secret + ggf. Tokens.