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

209 lines
8.7 KiB
Markdown
Raw 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 Mac-Worker
Stateless FastAPI-Service auf dem Mac. Macht die schwere Arbeit: Whisper-Transkription und Ollama-Zusammenfassung. Wird vom LXC-Frontend per HTTP angesprochen.
## Voraussetzungen
- Apple Silicon (M1/M2/M3/M4), 16 GB RAM minimum
- macOS mit Xcode-CLI-Tools (`xcode-select --install`)
- Homebrew
- Python 3.11+ (`brew install python@3.11` — falls nicht vorhanden)
## Schritt 1 — Ollama vorbereiten
```bash
# Ollama installieren, falls noch nicht geschehen
brew install ollama
# Modell ziehen (Default — siehe unten für Alternativen)
ollama pull llama3.1:8b
# Ollama netzwerkweit erreichbar machen (LaunchAgent)
launchctl setenv OLLAMA_HOST "0.0.0.0:11434"
brew services restart ollama
```
## Schritt 2 — Repo + LaunchAgent installieren
```bash
# Repo holen
git clone https://git.cynfo.net/christian/voice-agent.git ~/voice-agent
cd ~/voice-agent/mac-worker
# Vollständige Installation in einem Befehl:
./deploy/install-launchagent.sh
```
Das Skript macht **alles in einem Rutsch**, idempotent:
1. legt `.venv` an (wenn fehlt) und installiert `requirements.txt`
2. legt `.env` aus Vorlage an (wenn fehlt)
3. generiert `~/Library/LaunchAgents/com.voiceagent.worker.plist` mit den richtigen Pfaden
4. registriert den Agent via modernem `launchctl bootstrap`
5. wartet auf `http://127.0.0.1:8080/health` und gibt die Status-Antwort aus
**Verwaltung:**
| Aktion | Befehl |
|---|---|
| Status + letzte Logs | `./deploy/install-launchagent.sh status` |
| Worker neu starten (kein Reinstall) | `./deploy/install-launchagent.sh restart` |
| **Update** (git-pull + pip + restart + Health) | `./deploy/update.sh` |
| Vollständige Neuinstallation | `./deploy/install-launchagent.sh` |
| Entfernen | `./deploy/install-launchagent.sh uninstall` |
| Live-Logs | `tail -f ~/Library/Logs/voice-agent-worker.{out,err}.log` |
> **Hinweis (modernes macOS):** `launchctl unload -w …` wirft auf neueren Versionen
> oft `Input/output error 5`. Die Skripte nutzen daher `launchctl bootout` /
> `bootstrap` / `kickstart -k` — das funktioniert zuverlässig.
**Eigenschaften des Agents:**
- `RunAtLoad` — startet beim Login
- `KeepAlive` mit `Crashed=true`, `SuccessfulExit=false` — Restart nach Crash, kein Loop bei sauberem Exit
- `ThrottleInterval=10` — frühestens 10 s nach Restart erneut starten
- Logs in `~/Library/Logs/voice-agent-worker.{out,err}.log`
**Wichtig:** der Agent läuft nur, wenn der Mac-User eingeloggt ist. Für headless-Server-Betrieb (Mac Mini ohne Login) entweder:
- Auto-Login aktivieren (System-Settings → Users), oder
- in einen LaunchDaemon umbauen — dann fällt allerdings die Apple-Neural-Engine-Beschleunigung weg, MLX läuft nur auf der CPU.
## Worker im Vordergrund starten (für Entwicklung)
```bash
cd ~/voice-agent/mac-worker
source .venv/bin/activate
uvicorn app.main:app --host 0.0.0.0 --port 8080
```
## API-Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
| GET | `/health` | Status + Ollama-Reachability |
| GET | `/api/profiles` | Verfügbare YAML-Profile auflisten |
| POST | `/api/transcribe` | multipart: `audio`, `language` → Transkript-JSON |
| POST | `/api/summarize` | JSON: `transcript`, `title`, `profile` → Summary-JSON |
| POST | `/api/protocol` | JSON: `transcript`, `summary`, `title`, `profile` → Protokoll-JSON |
| POST | `/api/export/docx` | JSON: `data`, `profile` → DOCX-Binary |
| POST | `/api/export/pdf` | JSON: `data`, `profile` → PDF-Binary |
| POST | `/api/preload` | JSON: `profile` → forciert Ollama-Modell-Load (`keep_alive 30 m`) |
| GET | `/api/jobs/{id}/log` | Letzte 200 Logzeilen für genau diesen Job |
Alle relevanten Calls dürfen einen Header `X-Job-Id: <int>` mitschicken — der
Mac-Worker schreibt dann jede Logzeile dieses Requests in einen per-Job
Ringbuffer, den `/api/jobs/{id}/log` für die LXC-UI ausliefert.
## Firewall am Mac
```bash
# Eingehende Verbindungen auf Port 8080 erlauben (System-Settings > Network > Firewall)
# oder via pf — siehe Apple-Doku.
```
Der Worker hat **keine Authentifizierung** — Betrieb nur im internen Netz.
---
## Whisper-Engine wählen
In `.env`:
```
WHISPER_ENGINE=mlx # mlx | faster | mock
WHISPER_MODEL=large-v3 # Modellname (siehe Tabellen unten)
WHISPER_BATCH_SIZE=12 # MLX: höher = schneller + mehr RAM
WHISPER_LANGUAGE=de
```
| `WHISPER_ENGINE` | Wann nutzen |
|---|---|
| `mlx` (Default) | Apple Silicon — nutzt Apple Neural Engine via [`lightning-whisper-mlx`](https://github.com/mustafaaljadery/lightning-whisper-mlx) |
| `faster` | Intel-Mac, Linux oder CUDA — [`faster-whisper`](https://github.com/SYSTRAN/faster-whisper) (CTranslate2) |
| `mock` | Testbetrieb ohne Modell-Download |
### MLX-Modelle (`WHISPER_ENGINE=mlx`)
| `WHISPER_MODEL` | Größe | Geschwindigkeit (M2) | Qualität (Deutsch) |
|---|---|---|---|
| `tiny` | 75 MB | ~20× Realzeit | Niedrig — nur für Voice-Commands |
| `base` | 145 MB | ~15× Realzeit | Niedrig |
| `small` | 466 MB | ~6× Realzeit | Mittel |
| `medium` | 1.5 GB | ~2× Realzeit | Gut, schwächelt bei Fachbegriffen |
| `large-v3` (Default) | 3 GB | ~0.3× Realzeit | **Sehr gut** — Standard für Sitzungsprotokolle |
| `distil-large-v3` | 1.5 GB | ~1.5× Realzeit | Fast wie `large-v3`, ~5× schneller |
| `large-v3-turbo` | 1.6 GB | ~3× Realzeit | Wie `large-v3` für lange Inhalte, schwächer bei kurzen |
Empfehlung: `large-v3` für maximale Qualität, `distil-large-v3` wenn Geschwindigkeit wichtiger ist.
Modelle werden beim ersten Aufruf automatisch von HuggingFace gezogen (`mlx-community/whisper-...`).
### Alternative Transkriptions-Engines
Diese sind im Standard-Setup **nicht** aktiviert, lassen sich aber statt `lightning-whisper-mlx` einbauen:
- **`whisper.cpp` mit CoreML** — pure C++, sehr ressourceneffizient, kann das Whisper-Modell auf der Apple Neural Engine ausführen. Eigener Subprozess statt Python-Bindings.
- **WhisperX** ([github.com/m-bain/whisperX](https://github.com/m-bain/whisperX)) — basiert auf `faster-whisper`, fügt **Wort-genaue Timestamps** und **Sprecher-Diarization** (via pyannote) hinzu. Erfordert HuggingFace-Token. Sinnvoll, sobald „Wer hat was gesagt?" wichtiger wird.
- **Voxtral** (Mistral, 2025) — multimodales Sprach-LLM, kann Audio direkt zusammenfassen ohne separaten Whisper-Schritt. Reduziert die Pipeline auf einen einzigen Modell-Call, braucht aber andere Library und höheren VRAM.
- **NVIDIA Parakeet TDT** — extrem schnell, aber primär englisch. Für deutsche Sitzungen nicht empfehlenswert.
Für reinen Geschwindigkeits-Boost ohne Architektur-Änderung: einfach `WHISPER_MODEL=distil-large-v3` setzen.
---
## Ollama-Modell wählen
In `.env`:
```
OLLAMA_MODEL=llama3.1:8b
OLLAMA_TIMEOUT=600
```
Anschließend nur noch:
```bash
ollama pull <neues-modell>
# Worker neu starten
```
### Empfehlung nach Mac-RAM
| Mac-RAM | Empfohlenes Modell | Begründung |
|---|---|---|
| 16 GB | `llama3.1:8b` oder `qwen2.5:7b` | Genug Spielraum neben Whisper-large-v3 |
| 24 GB | `qwen2.5:14b` oder `gemma3:12b` | Großer Qualitätssprung bei deutscher JSON-Ausgabe |
| 32 GB | `mistral-small:24b` (Q4) oder `gpt-oss:20b` | Beste Kompromiss-Wahl |
| 64 GB+ | `llama3.3:70b` oder `qwen2.5:72b` | Top-Qualität, aber langsamer (~2060 s pro Summary) |
### Detailbewertung der Kandidaten
| Modell | Größe | Deutsch | JSON-Stabilität | Geschwindigkeit | Notizen |
|---|---|---|---|---|---|
| `llama3.1:8b` (Default) | 8 B | Gut | Mittel — gelegentlich Codefences | Schnell (~5 s) | Ausreichend für die meisten Sitzungen |
| `qwen2.5:7b` | 7 B | Sehr gut | Hoch | Schnell | Beste 7B-Wahl für Deutsch |
| `qwen2.5:14b` | 14 B | Sehr gut | Sehr hoch | Mittel (~10 s) | **Empfehlung für 2432 GB Macs** |
| `gemma3:12b` | 12 B | Gut | Hoch | Mittel | Google, gute Strukturierung |
| `mistral-small:24b` | 24 B | Sehr gut | Sehr hoch | Mittel (~15 s) | Europäisch trainiert, sehr stark bei Fachsprache |
| `gpt-oss:20b` | 20 B | Gut | Sehr hoch | Mittel | OpenAI Open-Weight (2025), explizit auf Tool-Use trainiert |
| `phi4:14b` | 14 B | Mittel | Hoch | Mittel | Microsoft, stark im Reasoning, schwächer im Deutschen |
| `llama3.3:70b` | 70 B | Exzellent | Sehr hoch | Langsam (~3060 s) | Top-Qualität, nur mit 48 GB+ RAM sinnvoll |
### Modell wechseln
```bash
# 1. Modell ziehen
ollama pull qwen2.5:14b
# 2. .env anpassen
sed -i '' 's/^OLLAMA_MODEL=.*/OLLAMA_MODEL=qwen2.5:14b/' .env
# 3. Worker neu starten
# (z.B. Ctrl-C im Terminal und uvicorn erneut)
```
### Tipp: JSON-Modus erzwingen
Der aktuelle Worker parst die Antwort manuell und greift bei Fehlern auf einen Text-Fallback zurück. Mit Ollama lässt sich JSON-Output erzwingen, indem im Generate-Call `format: "json"` gesetzt wird — das senkt Parse-Fehler bei kleineren Modellen drastisch. Bei Bedarf in `app/core/ollama_client.py` ergänzen.