Files
tliu93 70b0cf08ee
test / pytest (push) Successful in 1m20s
docker-image / build-and-push (push) Successful in 5m6s
Add AI search query expansion
2026-06-01 21:28:29 +02:00

94 lines
2.8 KiB
Python

"""Settings read/write helpers for the ``app_settings`` KV table.
Provides a typed ``LLMConfig`` dataclass and two helpers:
- ``get_app_settings(db) -> LLMConfig`` — reads KV rows (or returns defaults).
- ``save_app_settings(db, ...) -> None`` — writes KV rows; API key left blank
means "keep the old value".
"""
from __future__ import annotations
from dataclasses import dataclass
from sqlalchemy.orm import Session
from app.models import AppSetting
@dataclass
class LLMConfig:
"""All settings consumed by the LLM client and settings UI."""
enabled: bool = False
base_url: str = "https://api.openai.com/v1"
model: str = ""
api_key: str = ""
ai_search_enabled: bool = False
ai_search_extra_hints: str = ""
def _get_value(rows: dict[str, str], key: str, default: str) -> str:
return rows.get(key, default)
def _get_bool(rows: dict[str, str], key: str, default: bool) -> bool:
return rows.get(key, str(default).lower()) == "true"
def get_app_settings(db: Session) -> LLMConfig:
"""Read all settings from ``app_settings`` and return an ``LLMConfig``."""
rows: dict[str, str] = {}
for row in db.query(AppSetting).all():
if row.value is not None:
rows[row.key] = row.value
return LLMConfig(
enabled=_get_bool(rows, "llm_enabled", False),
base_url=_get_value(rows, "llm_base_url", "https://api.openai.com/v1"),
model=_get_value(rows, "llm_model", ""),
api_key=_get_value(rows, "llm_api_key", ""),
ai_search_enabled=_get_bool(rows, "ai_search_enabled", False),
ai_search_extra_hints=_get_value(rows, "ai_search_extra_hints", ""),
)
def save_app_settings(
db: Session,
*,
enabled: bool | None = None,
base_url: str | None = None,
model: str | None = None,
api_key: str | None = None,
ai_search_enabled: bool | None = None,
ai_search_extra_hints: str | None = None,
) -> None:
"""Write settings to ``app_settings``.
If ``api_key`` is ``None`` (form field left blank), the existing key is
preserved. All other fields are written as-is.
"""
updates: dict[str, str | None] = {}
if enabled is not None:
updates["llm_enabled"] = str(enabled).lower()
if base_url is not None:
updates["llm_base_url"] = base_url
if model is not None:
updates["llm_model"] = model
if api_key is not None:
updates["llm_api_key"] = api_key
if ai_search_enabled is not None:
updates["ai_search_enabled"] = str(ai_search_enabled).lower()
if ai_search_extra_hints is not None:
updates["ai_search_extra_hints"] = ai_search_extra_hints
for key, value in updates.items():
existing = db.get(AppSetting, key)
if existing is not None:
existing.value = value
else:
db.add(AppSetting(key=key, value=value))
db.commit()