feat(admin): Dropdown „Zentrales KI-Modell" — erprobte Presets ruck-zuck umstellen
Neue Karte in Admin › System › Status: ein Dropdown kuratierter, erprobter
Modelle, das Provider + Modell in einem Klick als Laufzeit-Override umstellt
(wirkt sofort, kein Neustart).
- Presets in config/models.yaml (Label, optional note, set:{key:value} aus
RUNTIME_SETTABLE, default:true = Config-Standard). Loader app/model_presets.py
(nur erlaubte LLM-Keys: default_llm_provider, openrouter_llm_model,
local_llm_model).
- Endpunkte: GET /api/admin/models (Presets + aktuell aktives LLM + active_index),
POST /api/admin/models/select (Default -> Overrides löschen, sonst Override-Keys
setzen) — nutzt set_/delete_config_override + invalidate_cache, mit Audit-Log.
- Frontend: Karte zeigt Dropdown + „Aktiv: <provider> · <modell>"; Auswahl wirkt
sofort und lädt den Status neu. Bump app.js v=52 -> v=53.
- Startliste: Mistral Small 24B (Standard), DeepSeek V4 Flash/Pro, Ollama Gemma 3.
Tests: Laden/Default-aktiv/Select-setzt-Override/Default-löscht/404/Auth.
263 Offline-Tests grün. Live via Headless-Chrome verifiziert (Auswahl ->
Override gesetzt, Provider-Karte spiegelt das Modell).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2ccfd7f6d6
commit
18ad442c94
6 changed files with 243 additions and 2 deletions
43
app/model_presets.py
Normal file
43
app/model_presets.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
"""Kuratierte „erprobte" KI-Modell-Presets fürs Admin-Dropdown (System › Status).
|
||||
|
||||
Geladen aus ``config/models.yaml``. Jede Auswahl stellt Provider + Modell als
|
||||
Laufzeit-Override um (siehe RUNTIME_SETTABLE) — ohne Neustart. Ein Preset mit
|
||||
``default: true`` steht für den Config-Standard: seine Auswahl ENTFERNT die
|
||||
LLM-Overrides, sodass wieder Profil/TOML greift.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from app.runtime_config import RUNTIME_SETTABLE
|
||||
|
||||
_PATH = Path(__file__).resolve().parent.parent / "config" / "models.yaml"
|
||||
|
||||
# LLM-Schlüssel, die ein Preset/Reset berührt (Schnittmenge mit RUNTIME_SETTABLE).
|
||||
LLM_KEYS = ("default_llm_provider", "openrouter_llm_model", "local_llm_model")
|
||||
|
||||
|
||||
def load_presets() -> list[dict]:
|
||||
"""Liest die Presets aus der YAML. Unbekannte/leere Datei -> leere Liste.
|
||||
Nur Keys aus RUNTIME_SETTABLE werden im `set` übernommen (Sicherheit)."""
|
||||
try:
|
||||
data = yaml.safe_load(_PATH.read_text(encoding="utf-8")) or {}
|
||||
except (OSError, yaml.YAMLError):
|
||||
return []
|
||||
out: list[dict] = []
|
||||
for i, p in enumerate(data.get("presets", []) or []):
|
||||
if not isinstance(p, dict):
|
||||
continue
|
||||
sets = {
|
||||
k: str(v)
|
||||
for k, v in (p.get("set") or {}).items()
|
||||
if k in RUNTIME_SETTABLE
|
||||
}
|
||||
out.append({
|
||||
"index": i,
|
||||
"label": str(p.get("label") or f"Preset {i}"),
|
||||
"note": str(p.get("note") or ""),
|
||||
"is_default": bool(p.get("default")),
|
||||
"set": sets,
|
||||
})
|
||||
return out
|
||||
Loading…
Add table
Add a link
Reference in a new issue