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

8.7 KiB
Raw Permalink Blame History

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

# 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

# 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)

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

# 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
faster Intel-Mac, Linux oder CUDA — 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) — 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:

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

# 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.