85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
"""运行时 LLM 配置:可由业务后端(管理端 AI 配置)动态下发,覆盖 .env。"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from threading import RLock
|
|
from typing import Any
|
|
|
|
|
|
@dataclass
|
|
class RuntimeLlmConfig:
|
|
"""enabled=None 表示未由管理端覆盖,沿用 .env。"""
|
|
|
|
enabled: bool | None = None
|
|
api_base_url: str | None = None
|
|
api_key: str | None = None
|
|
model: str | None = None
|
|
temperature: float | None = None
|
|
source: str = "env"
|
|
|
|
|
|
_lock = RLock()
|
|
_runtime = RuntimeLlmConfig()
|
|
|
|
|
|
def get_runtime_llm() -> RuntimeLlmConfig:
|
|
with _lock:
|
|
return RuntimeLlmConfig(
|
|
enabled=_runtime.enabled,
|
|
api_base_url=_runtime.api_base_url,
|
|
api_key=_runtime.api_key,
|
|
model=_runtime.model,
|
|
temperature=_runtime.temperature,
|
|
source=_runtime.source,
|
|
)
|
|
|
|
|
|
def update_runtime_llm(
|
|
*,
|
|
enabled: bool | None = None,
|
|
api_base_url: str | None = None,
|
|
api_key: str | None = None,
|
|
model: str | None = None,
|
|
temperature: float | None = None,
|
|
) -> RuntimeLlmConfig:
|
|
"""
|
|
更新运行时配置。
|
|
- api_key 为 None:不改密钥
|
|
- api_key 为非空字符串:覆盖
|
|
- api_key 为 "":清空运行时密钥(回退 .env)
|
|
"""
|
|
with _lock:
|
|
if enabled is not None:
|
|
_runtime.enabled = bool(enabled)
|
|
if api_base_url is not None and api_base_url.strip():
|
|
_runtime.api_base_url = api_base_url.strip()
|
|
if api_key is not None:
|
|
_runtime.api_key = api_key.strip() if api_key.strip() else None
|
|
if model is not None and model.strip():
|
|
_runtime.model = model.strip()
|
|
if temperature is not None:
|
|
t = float(temperature)
|
|
_runtime.temperature = max(0.0, min(2.0, t))
|
|
_runtime.source = "runtime"
|
|
return get_runtime_llm()
|
|
|
|
|
|
def runtime_status(env_key_configured: bool, env_base: str, env_model: str) -> dict[str, Any]:
|
|
rt = get_runtime_llm()
|
|
key_ok = bool(rt.api_key) or env_key_configured
|
|
enabled = False
|
|
if key_ok:
|
|
if rt.enabled is None:
|
|
enabled = env_key_configured or bool(rt.api_key)
|
|
else:
|
|
enabled = bool(rt.enabled)
|
|
return {
|
|
"enabled": enabled,
|
|
"configured": key_ok,
|
|
"api_key_configured": key_ok,
|
|
"api_base_url": rt.api_base_url or env_base,
|
|
"model": rt.model or env_model,
|
|
"temperature": rt.temperature,
|
|
"source": rt.source if (rt.api_key or rt.enabled is not None or rt.api_base_url) else "env",
|
|
}
|