fix(llm): LLM antwortet jetzt in der konfigurierten Systemsprache

Bisher wurde `language` zwar an STT/TTS übergeben, aber nie an den LLM.
Lokales Modell antwortete deshalb immer auf Englisch/Deutsch, egal ob
Französisch, Spanisch o.a. eingestellt war.

Lösung: `language`-Parameter durch die gesamte LLM-Schicht gezogen:
- base.py: `lang_instruction()` helper + Signatur erweitert
- local_openai_compatible.py: Sprachanweisung ("Respond in Français.")
  wird als letzter System-Part in den Message-Stack eingefügt
- openrouter.py: Explizite Sprachanweisung ergänzt den bestehenden
  "Answer in the same language as the user"-Prompt
- fallback.py: FallbackLLMProvider leitet `language` durch
- orchestrator.py: alle 3 LLM-Aufrufstellen übergeben `language`
- Tests: alle Stub-LLMs um `language=None` ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-19 14:12:16 +02:00
commit 81d4cf6fd8
14 changed files with 89 additions and 44 deletions

View file

@ -40,7 +40,7 @@ def test_sse_delta_parsing():
def test_base_stream_default_yields_full_completion():
class P(LLMProvider):
async def complete(self, text, history=None, session_id=None):
async def complete(self, text, history=None, session_id=None, language=None):
return "ganze Antwort"
async def run():
@ -51,10 +51,10 @@ def test_base_stream_default_yields_full_completion():
def _install_streaming(monkeypatch, tokens):
class StreamLLM:
async def complete(self, text, history=None, session_id=None):
async def complete(self, text, history=None, session_id=None, language=None):
return "".join(tokens)
async def stream(self, text, history=None, session_id=None):
async def stream(self, text, history=None, session_id=None, language=None):
for tok in tokens:
yield tok
@ -95,7 +95,7 @@ def test_ws_without_stream_flag_has_no_tokens(monkeypatch):
def test_ws_stream_fallback_for_nonstreaming_llm(monkeypatch):
class OnlyComplete:
async def complete(self, text, history=None, session_id=None):
async def complete(self, text, history=None, session_id=None, language=None):
return "komplett"
class StubTTS:
@ -118,10 +118,10 @@ def test_ws_audio_stream_sends_chunks_per_sentence(monkeypatch):
tts_calls = []
class StreamLLM:
async def complete(self, text, history=None, session_id=None):
async def complete(self, text, history=None, session_id=None, language=None):
return "Satz eins. Satz zwei."
async def stream(self, text, history=None, session_id=None):
async def stream(self, text, history=None, session_id=None, language=None):
for tok in ["Satz ", "eins. ", "Satz ", "zwei."]:
yield tok