diff --git a/Docs/voice-assistant-architecture.md b/Docs/voice-assistant-architecture.md index fd2c6dd..b987e4f 100644 --- a/Docs/voice-assistant-architecture.md +++ b/Docs/voice-assistant-architecture.md @@ -133,11 +133,13 @@ Stufen: `raw_transcript → cleaned_transcript → semantic_response → spoken_ - **Input Cleaner** (`pipeline/input_cleaner.py`) – konservative Bereinigung des STT-Texts (Füllwörter, Whitespace). Verändert die Nutzerintention nicht. - **Dialog-LLM** – semantische Antwort; Persona/Sicherheitsregeln im System-Prompt (`providers/llm/openrouter.py`). -- **Spoken Response Adapter** (`pipeline/spoken_response_adapter.py`) – macht die Antwort sprechbar/seniorengerecht (Markdown raus, Listen → Sätze, Uhrzeiten erhalten). -- **TTS Normalizer** (`pipeline/tts_normalizer.py`) – Zahlen/Abkürzungen/Einheiten verbal ausformulieren, sprachabhängig (de/en). +- **Spoken Response Adapter** (`pipeline/spoken_response_adapter.py`) – macht die Antwort sprechbar/seniorengerecht (Markdown raus, Aufzählungspunkte weg, **nummerierte Listen → Ordinalwörter** „1." → „erstens", Uhrzeiten/Verhältnisse erhalten). +- **Sentence Chunker** (`pipeline/sentence_chunker.py`) – inkrementelle Satzsegmentierung für satzweises Streaming-TTS. Trennt bewusst **nicht** nach Ziffer+Punkt („1. Mai"), Einzelbuchstabe+Punkt („z. B.", Initialen) oder bekannten Abkürzungen. +- **TTS Normalizer** (`pipeline/tts_normalizer.py`) – füllt gezielt die Lücken des Phonemizers (espeak-ng in piper), **ohne** zu duplizieren, was der schon gut kann (Kardinal-/Dezimalzahlen bleiben unangetastet): **Ordinalia** (Datum „1. Mai" → „erster Mai", Folgen „1. 2. 3." → „erstens, zweitens …"), **Einheiten nach Zahl** (kg/km/km-h/…), **Abkürzungen** (Dr./z. B./usw.) und ein **YAML-Aussprache-Lexikon** (`config/pronunciation..yaml`, erweitert die eingebauten Defaults; case-insensitive Wort-Umschreibungen wie „strömt" → „ströhmt"). Stufe **provider-abhängig** (`TTS_NORMALIZE_LEVEL=auto|full|light|off`): piper → `full`, Cloud-TTS → `light` (Cloud spricht Zahlen/Abkürzungen selbst gut). Ordinalzahlen 1.–31. in `pipeline/german_numbers.py`. -Empfehlung: nicht jede Zwischenstufe braucht ein großes LLM — Cleaner und +Empfehlung: nicht jede Zwischenstufe braucht ein großes LLM — Cleaner, Chunker und Normalizer überwiegend regelbasiert (so heute umgesetzt), Adapter promptbasiert. +Lexikon pflegen: `python scripts/add_pronunciation.py "wort:aussprache" [--verify]`. ## 6. Orchestrator @@ -195,15 +197,16 @@ erkennung und Barge-in (`interrupt`)**; **Resilienz (Fallback-Ketten je Modul, In-Memory-Metriken `/api/metrics`), Tageskontingent pro Nutzer und heuristische Notfall-Eskalation**; automatisierte Tests. -**Echtes lokales STT:** `faster-whisper` (optionale Dependency `.[local]`, -CTranslate2) transkribiert real — damit ist ein Hybrid „STT+LLM lokal, TTS remote" -möglich (live verifiziert). +**Echtes lokales STT & TTS:** `faster-whisper` (optionale Dependency `.[local]`, +CTranslate2) transkribiert real; `piper` (Binary + Stimmmodell, ffmpeg-Resampling +auf 24000 Hz) synthetisiert real. Damit ist sowohl ein Hybrid „STT+LLM lokal, TTS +remote" als auch eine **voll-lokale** Konstellation möglich (live verifiziert). **Platzhalter (Gerüst):** Audio-Endpunkte (`local-default`, `bluetooth`, `mobile-ws`, `mobile-webrtc`) liefern leere Chunks — nur Auswahl/Lifecycle sind -verdrahtet, kein echtes Hardware-I/O. Lokale TTS-Provider `piper`, `chatterbox` -sind noch Stubs. `transport_router.py` (Ebene 4) existiert, ist aber noch -nicht aktiv (lokal/remote trägt vorerst der Provider-Name). +verdrahtet, kein echtes Hardware-I/O. Der TTS-Provider `chatterbox` ist noch ein +Stub. `transport_router.py` (Ebene 4) existiert, ist aber noch nicht aktiv +(lokal/remote trägt vorerst der Provider-Name). ## 9. Roadmap / bewusste nächste Schritte @@ -240,7 +243,7 @@ voice-assistant-scaffold/ │ ├── api/ # health, chat, speak, transcribe, devices, sessions, config, admin, me, ws │ ├── core/ # orchestrator │ ├── audio/ # router, transport_router, vad, endpoints/input|output/* -│ ├── pipeline/ # input_cleaner, spoken_response_adapter, tts_normalizer, sentence_chunker +│ ├── pipeline/ # input_cleaner, spoken_response_adapter, tts_normalizer, sentence_chunker, german_numbers │ └── providers/ # stt/ llm/ tts/ (openrouter + lokale Stubs) + fallback.py ├── config/ # voice-assistant.example.toml (+ lokale .toml, gitignored) ├── data/ # SQLite-DB (gitignored) diff --git a/README.md b/README.md index f140c19..d9004d8 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Praktische Bedienung: [`BEDIENUNGSANLEITUNG.md`](BEDIENUNGSANLEITUNG.md). - **Pipeline mit getrennter Semantik/Sprache:** STT → Input-Cleaner → LLM → Spoken-Adapter → TTS-Normalizer → TTS - **Provider austauschbar** über Registry (OpenRouter remote; lokales STT via faster-whisper `.[local]`; **lokales TTS via piper**; chatterbox-TTS noch Stub) +- **Aussprache-Normalisierung** vor dem TTS (Ordinalia/Einheiten/Abkürzungen + YAML-Lexikon, provider-abhängig `TTS_NORMALIZE_LEVEL`); Pflege per `scripts/add_pronunciation.py` - **Geschichtete Konfiguration** mit Profilen (`local-dev` / `hybrid` / `cloud`) - **Routing auf jeder Ebene:** Default → Profil → Nutzer → Session → Request - **Authentifizierung** (Bearer-Token) + persistente Nutzer/Sessions (SQLite)