Compare commits

...

2 commits

Author SHA1 Message Date
15d8714105 chore(tts-de): Aussprache "circa" -> "zirka"
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:11:40 +02:00
eea25455cb docs: Weg-2 (Web-Suche) dokumentiert + Version 0.3.0
Web-Such-/Tool-Calling-Funktion in der Doku nachgezogen: CHANGELOG (0.3.0),
README, CLAUDE.md (Querschnitt), Architektur-Doc (§6.1), Bedienungsanleitung
(§5.5 Nutzer/Admin) und DEPLOYMENT (Tool-Faehigkeit des Modells).
Version 0.2.0 -> 0.3.0 (pyproject.toml).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:11:40 +02:00
8 changed files with 80 additions and 1 deletions

View file

@ -926,6 +926,31 @@ curl -s -X POST "$URL/api/chat?debug=true" \
-d '{"text":"Wie wird das Wetter?"}' | jq
```
### 5.5 Aktuelle Informationen aus dem Web (Web-Suche)
Das Wissen des Sprachmodells endet zu einem bestimmten Zeitpunkt. Für **tagesaktuelle
Fragen** (z. B. „Wer ist Bundeskanzler?", „Wie ist das Wetter in Paris?", „Hat die
Apotheke heute geöffnet?", „Lebt … noch?") holt Alexis daher selbsttätig frische
Fakten aus dem Web (über das Modell `perplexity/sonar`) und antwortet damit — das
aktuelle Faktum hat Vorrang vor dem Trainingswissen. **Quellen** stehen als Links
unter der Antwort.
Damit niemand auf eine stumme Pause wartet, sagt Alexis während der Recherche einen
kurzen Beruhigungssatz (z. B. *„Einen Moment, ich schaue das für Sie nach."*) —
gesprochen und in der Statuszeile; bei längerer Suche folgen Geduldssätze.
Heikle Kategorien (aktuelle Amtsträger, Wohnort lebender Personen, „lebt X noch",
Öffnungszeiten/Fahrpläne) lösen die Suche **immer** aus, damit es bei der ersten
Antwort keine veralteten Angaben gibt.
- **Standard:** an. **Pro Nutzer/Profil abschaltbar** über das Setting
`web_search_enabled` (Nutzer-Prefs/Profil-Override; siehe § 6) — dann antwortet
Alexis nur aus dem Modellwissen.
- **Voraussetzung:** ein **tool-fähiges** zentrales Modell (Standard
`mistralai/mistral-small-3.2-24b-instruct`). Ältere Modelle ohne Tool-Endpoint
(z. B. `…-2501`) können die Web-Suche nicht; Alexis erkennt das und antwortet dann
ohne Suche (geloggt). Ausführliche Technik: `Docs/weg2-tool-calling.md`.
---
## 6. Einstellungen und Konfiguration

View file

@ -3,6 +3,33 @@
Alle nennenswerten Änderungen an **Alexis**. Format lose nach [Keep a Changelog](https://keepachangelog.com/de/);
Versionierung nach [SemVer](https://semver.org/lang/de/) (prä-1.0: `0.x`).
## [0.3.0] — 2026-06-30
### Hinzugefügt
- **Web-Suche per Tool-Calling („Weg 2"):** Das zentrale Modell entscheidet selbst,
ob eine Frage tagesaktuelle Fakten braucht, holt sie über `perplexity/sonar` und
formuliert die Antwort in Persona (Vorrang fürs frische Faktum). Standard **an**,
pro Nutzer/Profil abschaltbar (`web_search_enabled`). **Quellen-Links** unter der
Antwort. Ausführliche Referenz: `Docs/weg2-tool-calling.md`.
- **Deterministischer Such-Backstop** für heikle Kategorien (aktuelle Amtsträger,
Wohnort lebender Personen, „lebt X noch", Öffnungszeiten/Fahrpläne): diese suchen
*immer* — auch auf einem tool-unfähigen Modell (Fakten als System-Kontext).
- **Beruhigungssätze während der Recherche:** zufällige, in die Zielsprache
übersetzte „Sie"-Sätze (sofort gesprochen — Server- *und* Geräte-TTS, sowie in der
Status-Zeile); bei langer Recherche Geduldssätze (Abstand ≥ 10 s). Eine Pflege-
Stelle (`app/pipeline/fillers.py`, Englisch).
- **Zentrale Datum-/Uhrzeit-Auskunft** (`app/core/clock.py`): in alle LLM-System-
Prompts injiziert → relative Zeitangaben („heute", „morgen", „nächsten Montag",
„in 3 Stunden") werden aufgelöst.
- **Koreferenz-Vorstufe** (Pronomen-Folgefragen) + Metriken `tool_calls_total`,
`sonar_calls_total`, `search_forced_total`, `tool_unsupported_total`.
### Geändert
- **Standard-LLM:** `mistralai/mistral-small-3.2-24b-instruct` (tool-fähig; im
Tool-Calling-Eval einziger Recall-Gate-Passer). Die frühere Baseline
`mistralai/mistral-small-24b-instruct-2501` kann **kein** Tool-Calling — nicht
mehr dorthin zurückstellen, solange die Web-Suche aktiv ist.
## [0.2.0] — 2026-06-27
### Geändert

View file

@ -54,6 +54,7 @@ Der Orchestrator schreibt synthetisiertes Audio **zusätzlich** in den Output-En
- **Resilienz** (`app/providers/fallback.py`): Fallback-Ketten je Modul (`*_FALLBACK`). Metriken in `app/metrics.py` (`/api/metrics`, JSON + Prometheus). Tageskontingent `app/quota.py` (429).
- **Sicherheit** (`app/safety/`): zweistufige Notfall-Eskalation — schnelle Stichwort-Heuristik im Hot-Path (`emergency.py`) + LLM-Klassifikation als nicht-blockierender Hintergrund-Task (`llm_classifier.py`).
- **Auto-Erinnerungen** (`app/core/memory_extractor.py`): nach N Turns destilliert ein LLM dauerhafte Fakten als Hintergrund-Task.
- **Web-Suche / Tool-Calling („Weg 2")** (`app/providers/llm/tool_calling.py`, `app/tools/web_search.py`): `ToolCallingLLM` wickelt als LLMProvider eine Tool-Schleife ab — das Modell entscheidet selbst, ob es `web_search` (perplexity/sonar) ruft, und formuliert die Antwort in Persona (Vorrang fürs Tool-Ergebnis). Registry-Eintrag `openrouter-tools`; `web_search_enabled` (global an, pro Nutzer abschaltbar) wählt in `build_orchestrator` tool-fähig vs. plain. Deterministischer **Backstop** (`app/pipeline/search_backstop.py`) erzwingt die Suche für heikle Kategorien (Amtsträger/Wohnort/„lebt X noch"/Öffnungszeiten). Beruhigungssätze (`app/pipeline/fillers.py`, ephemer) + Koreferenz-Vorstufe (`decontextualizer.py`) + Citations. Zentrale Datum/Uhrzeit: `app/core/clock.py` (`now_context()` in alle LLM-Prompts). **Referenz: `Docs/weg2-tool-calling.md`.**
- **Echtzeit** (`app/api/ws.py`): `/ws/chat` (Token-/Audio-Streaming) und `/ws/voice` (Audio→STT→Pipeline, VAD, Barge-in via `interrupt`).
- **Admin** (`app/api/admin.py`, `app/admin_llm.py`, `app/audit.py`, `app/runtime_config.py`): Live-Config, Backend-Wechsel, Gateway-Neustart, Lexika, Live-Log — schreibende Aktionen werden ins Audit-Log geschrieben.
- **Frontend** (`app/web/`): Tailwind ohne Build-Schritt, mobiltauglich. Geräte-TTS (Browser-SpeechSynthesis) mit Fallback auf Server-Audio.

View file

@ -1641,3 +1641,11 @@ openrouter_llm_model = "mistralai/mistral-small-3.2-24b-instruct"
Free-Tier-Modelle (`:free`-Suffix) sind für Produktion ungeeignet — hohe
Wartezeiten durch geteilte Kapazität (z.B. Venice-Backend: 8 req/min).
> **Tool-Fähigkeit (für die Web-Suche, `web_search_enabled`):** Das zentrale Modell
> muss Tool-Calling über OpenRouter unterstützen. `mistral-small-3.2-24b-instruct`
> tut das; die alte Baseline `mistral-small-24b-instruct-2501` **nicht** (404 „No
> endpoints found that support tool use"). Ein tool-unfähiges Modell wird zur Laufzeit
> erkannt (antwortet dann ohne Suche, geloggt), aber nicht jede Volatil-Frage wird
> dann frisch beantwortet — also kein tool-unfähiges Modell wählen, solange die
> Web-Suche aktiv ist.

View file

@ -159,6 +159,21 @@ geschrieben (`open → write_chunk → flush → close`) und **gleichzeitig** al
HTTP-Stream zurückgegeben (additiv). Bei lokalen Geräten ist `write_chunk` heute
ein No-op; `LoopbackOutput` sammelt die Chunks (testbar ohne Hardware).
### 6.1 Web-Suche / Tool-Calling („Weg 2")
`ToolCallingLLM` (`app/providers/llm/tool_calling.py`) ist ein LLMProvider, der
eine Agenten-Schleife abwickelt: das Modell entscheidet selbst, ob es das
`web_search`-Tool (`app/tools/web_search.py`, perplexity/sonar) ruft, und
formuliert die Antwort in Persona (Tool-Ergebnis hat Vorrang). Eingehängt als
Registry-Eintrag `openrouter-tools`; das geschichtete Flag `web_search_enabled`
(global an, pro Nutzer/Profil abschaltbar) wählt in `build_orchestrator`
tool-fähig vs. plain — selbe Präzedenz wie die Route. Ein deterministischer
**Backstop** (`app/pipeline/search_backstop.py`) erzwingt die Suche für heikle
Kategorien. Querschnitt: ephemere Beruhigungssätze (`fillers.py`),
Koreferenz-Vorstufe (`decontextualizer.py`), Citations im Trace, zentrale
Datum/Uhrzeit (`app/core/clock.py`). **Ausführliche Referenz:
[`weg2-tool-calling.md`](weg2-tool-calling.md).**
## 7. FastAPI-Endpunkte (umgesetzt)
| Methode & Pfad | Zweck |

View file

@ -16,6 +16,7 @@ Jede Achse — Hardware, Betrieb, Software — ist frei konfigurierbar, ohne Cod
- **Resilienz:** Fallback-Ketten je Modul + In-Memory-Metriken (JSON + Prometheus)
- **Gesprächsgedächtnis** pro Session (Verlauf) + Langzeit-Erinnerungen pro Nutzer (manuell + automatisch)
- **WebSocket-Streaming:** Token-Streaming (LLM), Audio-Streaming (satzweises TTS), Sprach-Eingang, VAD, Barge-in
- **Web-Suche (Tool-Calling, „Weg 2"):** das Modell holt bei tagesaktuellen Fragen frische Fakten über `perplexity/sonar` (Standard an, pro Nutzer abschaltbar), mit Quellen-Links, deterministischem Backstop für heikle Kategorien und gesprochenen Beruhigungssätzen während der Recherche — siehe [`Docs/weg2-tool-calling.md`](Docs/weg2-tool-calling.md)
- **Notfall-Eskalation:** zweistufig (Stichwörter + LLM-Klassifikation im Hintergrund)
- **Web-Interface** unter `/` (Tailwind, kein Build, mobiltauglich) mit Geräte-TTS (Browser-Sprachausgabe) und Ton-Presets (Schnell/Hohe Qualität/Cloud)
- **Admin-Panel** (5 Bereiche + Übersicht-Dashboard): Nutzer/Sessions, LLM-/GPU-Status, Backend-Wechsel + Gateway-Neustart, Live-Config, Aussprache-Lexika, Live-Log, Audit-Logging

View file

@ -4,6 +4,7 @@ terms:
bläst: blähst
büßt: bühßt
Chat: Tschätt
circa: zirka
Dornröschen: Dornröhß-chen
Glycerin: Glüzeriehn
grüßt: grühßt
@ -11,6 +12,7 @@ terms:
löst: löhst
Mond: Mohnd
Piotr: Pjottr
Saint: Sähnt
strömt: ströhmt
strömte: ströhmte
Stück: Styck

View file

@ -1,6 +1,6 @@
[project]
name = "voice-assistant-gateway"
version = "0.2.0"
version = "0.3.0"
description = "Modular voice assistant gateway with pluggable audio endpoints and provider adapters"
readme = "README.md"
requires-python = ">=3.11"