feat: Konversationsgedaechtnis - Kurzzeit-Gespraechsverlauf pro Session

- Store: messages-Tabelle + append_message/get_recent_messages (mit Mandanten-Schutz)
- LLMProvider.complete um history erweitert (openrouter + local bauen system+history+user)
- Orchestrator.chat_text reicht den Verlauf ans LLM weiter
- chat.py: bei session_id letzte HISTORY_MAX_MESSAGES laden, danach User-/Assistant-Turn speichern
- ohne session_id weiterhin zustandslos; ?debug zeigt history_len
- Config HISTORY_MAX_MESSAGES (Default 10)
- Tests: 32 gruen (3 neue Gedaechtnis-Tests)
- Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-17 04:16:35 +02:00
commit 16a964032e
12 changed files with 225 additions and 40 deletions

View file

@ -143,10 +143,15 @@ Normalizer überwiegend regelbasiert (so heute umgesetzt), Adapter promptbasiert
`app/core/orchestrator.py` verbindet Provider, Pipeline und Output-Endpunkt.
- `chat_text(text, language, voice, output)` → `(trace, audio_bytes)`
- `chat_text(text, language, voice, output, history)` → `(trace, audio_bytes)`
- `speak_only(text, voice, language, output)``audio_bytes`
- `transcribe_only(audio_bytes, fmt, language, input)``trace`
Bei `/api/chat` mit `session_id` lädt die API-Schicht den letzten Gesprächsverlauf
aus dem Store (`messages`-Tabelle, letzte `HISTORY_MAX_MESSAGES`), gibt ihn als
`history` an das LLM und speichert nach der Antwort User- und Assistant-Turn.
Ohne `session_id` bleibt der Aufruf zustandslos.
Das synthetisierte Audio wird **zusätzlich** durch den gewählten Output-Endpunkt
geschrieben (`open → write_chunk → flush → close`) und **gleichzeitig** als
HTTP-Stream zurückgegeben (additiv). Bei lokalen Geräten ist `write_chunk` heute
@ -177,7 +182,8 @@ STT (multipart), LLM und TTS; lokaler OpenAI-kompatibler LLM-Adapter; regelbasie
Pipeline; geschichtete Config + Profile; Registry + einheitliche Route-Auflösung;
Device Router (strikt, Singleton); Output-Lifecycle; **Authentifizierung
(Bearer-Token) + persistenter SQLite-Store für Nutzer/Sessions + Mandanten-Trennung
+ dauerhafte Nutzer-Präferenzen**; automatisierte Tests.
+ dauerhafte Nutzer-Präferenzen**; **Gesprächsgedächtnis pro Session (Verlauf im
Store, fließt ins LLM)**; automatisierte Tests.
**Platzhalter (Gerüst):** Audio-Endpunkte (`local-default`, `bluetooth`,
`mobile-ws`, `mobile-webrtc`) liefern leere Chunks — nur Auswahl/Lifecycle sind
@ -191,7 +197,7 @@ Reihenfolge der Weiterentwicklung:
1. **(erledigt)** Konfig- & Routing-Fundament: Profile, Device Router, Registry, Pro-Request-Override.
2. **(erledigt)** Cloud-Fundament: Bearer-Token-Auth, Mehrbenutzer, persistenter SQLite-Store, Mandanten-Trennung, dauerhafte Nutzer-Präferenzen. Offen: Skalierung auf gemeinsamen Store (Postgres/Redis) für mehrere Instanzen.
3. **Konversationsgedächtnis:** Verlauf + Langzeit-Erinnerungen (heute ist `llm.complete` zustandslos; Nutzer-Präferenzen sind als Basis vorhanden).
3. **(teilweise erledigt)** Konversationsgedächtnis: Kurzzeit-Gesprächsverlauf pro Session ist umgesetzt (Store + ans LLM). Offen: **Langzeit-Erinnerungen** über Sessions hinweg (Fakten/Vorlieben, ggf. LLM-gestützt extrahiert und zusammengefasst).
4. **Echtzeit:** Streaming-STT/TTS, WebSocket/WebRTC-Endpunkte real, Barge-in, Turn-Manager.
5. **Resilienz:** Fallback-Policy (remote KI fällt aus → lokaler/alternativer Provider), Metriken/Tracing.
6. **Betrieb:** Kosten-/Quota-Kontrolle pro Nutzer; Notfall-/Eskalationskonzept (Senioren-Kontext).
@ -209,7 +215,7 @@ voice-assistant-scaffold/
│ ├── main.py # FastAPI-App + Router-Registrierung
│ ├── config.py # Settings, TOML-Profile, Präzedenz
│ ├── dependencies.py # Registries, ResolvedRoute, resolve_route, Store-/Router-Singleton
│ ├── store.py # Persistenz: Store-Interface + SQLiteStore (Nutzer/Sessions)
│ ├── store.py # Persistenz: Store-Interface + SQLiteStore (Nutzer/Sessions/Verlauf)
│ ├── auth.py # Bearer-Token-Auth (require_user) + Admin-Schutz
│ ├── errors.py # RoutingError -> HTTP 422
│ ├── schemas.py # Pydantic-Modelle