diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index 3942272..252dc05 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index d7aca91..b2e688f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/CLAUDE.md b/CLAUDE.md index 4eb982d..127f34d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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. diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 03d1ff9..fa0e603 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -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. diff --git a/Docs/voice-assistant-architecture.md b/Docs/voice-assistant-architecture.md index 15b3e49..8dcf6bb 100644 --- a/Docs/voice-assistant-architecture.md +++ b/Docs/voice-assistant-architecture.md @@ -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 | diff --git a/README.md b/README.md index d397c09..0f21f1e 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/pyproject.toml b/pyproject.toml index 219b88f..51bb559 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"