docs: Aussprache-Pipeline aktualisieren (Normalizer/Chunker/Lexikon, piper echt)

- Architektur §5: Spoken-Adapter (Listen->Ordinalwoerter), Sentence-Chunker
  (keine Trennung nach Ziffer+Punkt/Abk.), TTS-Normalizer (Ordinalia/Einheiten/
  Abk./YAML-Lexikon, provider-abhaengige Stufen) + german_numbers im Baum.
- Architektur: piper als echtes lokales TTS (nicht mehr Stub); nur chatterbox Stub.
- README: Feature-Bullet Aussprache-Normalisierung + add_pronunciation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-17 23:28:52 +02:00
commit bef02a663a
2 changed files with 14 additions and 10 deletions

View file

@ -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. - **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`). - **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). - **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).
- **TTS Normalizer** (`pipeline/tts_normalizer.py`) Zahlen/Abkürzungen/Einheiten verbal ausformulieren, sprachabhängig (de/en). - **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.<lang>.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. Normalizer überwiegend regelbasiert (so heute umgesetzt), Adapter promptbasiert.
Lexikon pflegen: `python scripts/add_pronunciation.py "wort:aussprache" [--verify]`.
## 6. Orchestrator ## 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 In-Memory-Metriken `/api/metrics`), Tageskontingent pro Nutzer und heuristische
Notfall-Eskalation**; automatisierte Tests. Notfall-Eskalation**; automatisierte Tests.
**Echtes lokales STT:** `faster-whisper` (optionale Dependency `.[local]`, **Echtes lokales STT & TTS:** `faster-whisper` (optionale Dependency `.[local]`,
CTranslate2) transkribiert real — damit ist ein Hybrid „STT+LLM lokal, TTS remote" CTranslate2) transkribiert real; `piper` (Binary + Stimmmodell, ffmpeg-Resampling
möglich (live verifiziert). 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`, **Platzhalter (Gerüst):** Audio-Endpunkte (`local-default`, `bluetooth`,
`mobile-ws`, `mobile-webrtc`) liefern leere Chunks — nur Auswahl/Lifecycle sind `mobile-ws`, `mobile-webrtc`) liefern leere Chunks — nur Auswahl/Lifecycle sind
verdrahtet, kein echtes Hardware-I/O. Lokale TTS-Provider `piper`, `chatterbox` verdrahtet, kein echtes Hardware-I/O. Der TTS-Provider `chatterbox` ist noch ein
sind noch Stubs. `transport_router.py` (Ebene 4) existiert, ist aber noch Stub. `transport_router.py` (Ebene 4) existiert, ist aber noch nicht aktiv
nicht aktiv (lokal/remote trägt vorerst der Provider-Name). (lokal/remote trägt vorerst der Provider-Name).
## 9. Roadmap / bewusste nächste Schritte ## 9. Roadmap / bewusste nächste Schritte
@ -240,7 +243,7 @@ voice-assistant-scaffold/
│ ├── api/ # health, chat, speak, transcribe, devices, sessions, config, admin, me, ws │ ├── api/ # health, chat, speak, transcribe, devices, sessions, config, admin, me, ws
│ ├── core/ # orchestrator │ ├── core/ # orchestrator
│ ├── audio/ # router, transport_router, vad, endpoints/input|output/* │ ├── 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 │ └── providers/ # stt/ llm/ tts/ (openrouter + lokale Stubs) + fallback.py
├── config/ # voice-assistant.example.toml (+ lokale .toml, gitignored) ├── config/ # voice-assistant.example.toml (+ lokale .toml, gitignored)
├── data/ # SQLite-DB (gitignored) ├── data/ # SQLite-DB (gitignored)

View file

@ -13,6 +13,7 @@ Praktische Bedienung: [`BEDIENUNGSANLEITUNG.md`](BEDIENUNGSANLEITUNG.md).
- **Pipeline mit getrennter Semantik/Sprache:** STT → Input-Cleaner → LLM → Spoken-Adapter → TTS-Normalizer → TTS - **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) - **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`) - **Geschichtete Konfiguration** mit Profilen (`local-dev` / `hybrid` / `cloud`)
- **Routing auf jeder Ebene:** Default → Profil → Nutzer → Session → Request - **Routing auf jeder Ebene:** Default → Profil → Nutzer → Session → Request
- **Authentifizierung** (Bearer-Token) + persistente Nutzer/Sessions (SQLite) - **Authentifizierung** (Bearer-Token) + persistente Nutzer/Sessions (SQLite)