From b2576fd465c6afbed634a900094daddf9788a98e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dieter=20Schl=C3=BCter?= Date: Sat, 20 Jun 2026 18:46:33 +0200 Subject: [PATCH] =?UTF-8?q?feat(llm):=20Live-Parameter=20top=5Fp=20+=20Liv?= =?UTF-8?q?e/Restart-Kennzeichnung=20=E2=80=94=20Plan-Schritt=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - local_llm_top_p (Default 0.9) durch Config -> runtime_config (RUNTIME_SETTABLE, live ohne Neustart) -> local-openai-compatible Payload (top_p). - Admin-Einstellungen: top_p als Slider (0–1); Hints "wirkt sofort (kein Neustart)" für temperature/top_p. - Doku: top_p + Klarstellung Live-Parameter (temp/top_p/max_tokens) vs. Startup-Wert Kontextfenster (OLLAMA_CONTEXT_LENGTH / llama.cpp -c). Verifiziert: top_p im Payload, Live-Config-Round-Trip (PUT/DELETE). 165 grün. Co-Authored-By: Claude Opus 4.8 --- BEDIENUNGSANLEITUNG.md | 6 ++++++ app/config.py | 1 + app/dependencies.py | 1 + app/providers/llm/local_openai_compatible.py | 3 +++ app/runtime_config.py | 3 ++- app/web/app.js | 3 ++- app/web/index.html | 2 +- 7 files changed, 16 insertions(+), 3 deletions(-) diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index 89cdf38..78f03a6 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -1027,6 +1027,12 @@ Diese Settings gelten nur für den Provider `local-openai-compatible`. | `LOCAL_LLM_SYSTEM_PROMPT` | Sprach-Prompt | Kurze, vorlesbare Antworten | | `LOCAL_LLM_MAX_TOKENS` | `0` (Server-Limit) | Optionaler Deckel, z. B. `256` | | `LOCAL_LLM_TEMPERATURE` | `0.3` | Sampling-Temperatur | +| `LOCAL_LLM_TOP_P` | `0.9` | Nucleus-Sampling (0.0–1.0) | + +> Temperatur, Top-p und Max-Tokens sind **Live-Parameter**: im Admin-Panel → +> Einstellungen änderbar und **ohne Neustart** sofort wirksam (pro Anfrage gesendet). +> Das **Kontextfenster** ist dagegen ein Startup-Wert (Ollama: `OLLAMA_CONTEXT_LENGTH`, +> llama.cpp: `-c`) und erfordert einen Backend-Neustart. Messung (Qwen3-35B, `va_llm`): Reasoning an → **5,5 s / 1433 Zeichen**; Reasoning aus + Sprach-Prompt → **0,7 s / ~190 Zeichen**. diff --git a/app/config.py b/app/config.py index 3070375..14ce23f 100644 --- a/app/config.py +++ b/app/config.py @@ -131,6 +131,7 @@ class Settings(BaseSettings): local_llm_disable_reasoning: bool = True # Qwen3 /no_think: spart die Denkphase local_llm_max_tokens: int = 0 # 0 = serverseitiges Limit (-n) local_llm_temperature: float = 0.3 + local_llm_top_p: float = 0.9 # Nucleus-Sampling (0.0–1.0) faster_whisper_model: str = "base" # tiny|base|small|medium|large-v3 faster_whisper_device: str = "auto" # auto|cpu|cuda faster_whisper_compute_type: str = "default" # default|int8|float16|int8_float16 diff --git a/app/dependencies.py b/app/dependencies.py index f8cc8a7..9179ae5 100644 --- a/app/dependencies.py +++ b/app/dependencies.py @@ -63,6 +63,7 @@ LLM_REGISTRY = { disable_reasoning=s.local_llm_disable_reasoning, max_tokens=s.local_llm_max_tokens, temperature=s.local_llm_temperature, + top_p=s.local_llm_top_p, ), } diff --git a/app/providers/llm/local_openai_compatible.py b/app/providers/llm/local_openai_compatible.py index cef4352..bb6e15d 100644 --- a/app/providers/llm/local_openai_compatible.py +++ b/app/providers/llm/local_openai_compatible.py @@ -20,6 +20,7 @@ class LocalOpenAICompatibleLLM(LLMProvider): disable_reasoning: bool = True, max_tokens: int = 0, temperature: float = 0.3, + top_p: float = 0.9, ): self.base_url = base_url.rstrip("/") self.api_key = api_key @@ -28,6 +29,7 @@ class LocalOpenAICompatibleLLM(LLMProvider): self.disable_reasoning = disable_reasoning self.max_tokens = max_tokens self.temperature = temperature + self.top_p = top_p def _build_messages( self, text: str, history: list[dict] | None, language: str | None = None @@ -66,6 +68,7 @@ class LocalOpenAICompatibleLLM(LLMProvider): "model": self.model, "messages": self._build_messages(text, history, language=language), "temperature": self.temperature, + "top_p": self.top_p, } if stream: payload["stream"] = True diff --git a/app/runtime_config.py b/app/runtime_config.py index 712472d..231e413 100644 --- a/app/runtime_config.py +++ b/app/runtime_config.py @@ -26,7 +26,8 @@ RUNTIME_SETTABLE: dict[str, tuple[str, str, str]] = { "openrouter_tts_voice": ("TTS-Stimme (OpenRouter)", "str", "z.B. Zephyr, Puck, Kore"), "piper_voice": ("TTS-Stimme (piper)", "str", "z.B. de_DE-thorsten-high"), "local_llm_system_prompt": ("Systemprompt (lokal)", "str", "Freier Text"), - "local_llm_temperature": ("Temperatur (lokal)", "float", "0.0–2.0"), + "local_llm_temperature": ("Temperatur (lokal)", "float", "0.0–2.0 — wirkt sofort (kein Neustart)"), + "local_llm_top_p": ("Top-p (lokal)", "float", "0.0–1.0 — wirkt sofort (kein Neustart)"), "local_llm_max_tokens": ("Max. Tokens (lokal)", "int", "0 = kein Limit"), "tts_normalize_level": ("TTS-Normalisierung", "str", "auto | full | light | off"), "audio_stream_default": ("Audio-Streaming Standard", "bool", "true | false"), diff --git a/app/web/app.js b/app/web/app.js index 3807454..56dbeb3 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -1384,6 +1384,7 @@ const FIELD_META = { piper_voice: { ui: "combo", opts: ["de_DE-thorsten-high","en_US-ryan-high","en_US-lessac-high","en_GB-cori-high","es_ES-sharvard-medium","fr_FR-siwis-medium","it_IT-paola-medium","nl_NL-mls-medium","ru_RU-irina-medium","zh_CN-huayan-medium"], test: "tts", testProvider: "piper" }, local_llm_system_prompt: { ui: "textarea", test: "llm" }, local_llm_temperature: { ui: "range", min: 0, max: 2, step: 0.1, test: "llm" }, + local_llm_top_p: { ui: "range", min: 0, max: 1, step: 0.05, test: "llm" }, local_llm_max_tokens: { ui: "number", min: 0, test: "llm" }, tts_normalize_level: { ui: "select", opts: ["auto","full","light","off"], test: "tts" }, audio_stream_default: { ui: "select", opts: ["true","false"], @@ -1398,7 +1399,7 @@ const FIELD_GROUPS = [ { label: "Provider & Sprache", keys: ["default_stt_provider","default_llm_provider","default_tts_provider","default_language"] }, { label: "OpenRouter-Modelle & Stimmen", keys: ["openrouter_llm_model","openrouter_tts_model","openrouter_tts_voice"] }, { label: "Piper TTS", keys: ["piper_voice"] }, - { label: "Lokales LLM", keys: ["local_llm_system_prompt","local_llm_temperature","local_llm_max_tokens"] }, + { label: "Lokales LLM", keys: ["local_llm_system_prompt","local_llm_temperature","local_llm_top_p","local_llm_max_tokens"] }, { label: "TTS-Verarbeitung", keys: ["tts_normalize_level","audio_stream_default"] }, { label: "Gedächtnis", keys: ["memory_extraction_enabled","memory_extraction_every_n_turns"] }, { label: "Limits", keys: ["daily_request_limit"] }, diff --git a/app/web/index.html b/app/web/index.html index 5a86973..6f0601c 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -250,6 +250,6 @@
- +