You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.3 KiB
Python

# backend/app/routers/settings.py — 설정: 시스템 스냅샷(읽기전용) + LLM 연결(편집/적용/테스트)
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session
from .. import runtime_config
from ..config import get_settings
from ..db import get_session
from ..llm.provider import LLMProvider, build_provider
from ..schemas import (
LLMConfigOut,
LLMTestIn,
LLMTestOut,
LLMUpdateIn,
SystemConfigOut,
)
from ..services import settings_service
router = APIRouter() # prefix 없음. main.py 에서 prefix="/api" 등록.
def _db_dialect(url: str) -> str:
return url.split(":", 1)[0].split("+", 1)[0] if url else "unknown"
@router.get("/settings/system", response_model=SystemConfigOut)
def get_system(s: Session = Depends(get_session)):
"""런타임/환경 구성 스냅샷(읽기전용 — .env 로 관리)."""
st = get_settings()
return SystemConfigOut(
env=st.ari_env,
auth_enabled=st.auth_enabled,
worker_enabled=st.worker_enabled,
database=_db_dialect(st.database_url),
sync_interval_minutes=st.sync_interval_minutes,
sync_page_size=st.sync_page_size,
connector_modes={
"calendar": st.connector_calendar,
"mail": st.connector_mail,
},
)
def _llm_config(s: Session) -> LLMConfigOut:
st = get_settings()
eff = runtime_config.effective_llm()
return LLMConfigOut(
provider=eff.provider,
model=eff.model,
host=eff.host,
timeout=eff.timeout,
provider_options=list(runtime_config._PROVIDERS),
overridden=settings_service.overlay_active(s),
api_key_set=bool(eff.api_key), # 값은 노출 금지 — 설정 여부만.
stt_provider=st.stt_provider,
vision_provider=st.vision_provider,
)
@router.get("/settings/llm", response_model=LLMConfigOut)
def get_llm(s: Session = Depends(get_session)):
return _llm_config(s)
@router.put("/settings/llm", response_model=LLMConfigOut)
def update_llm(body: LLMUpdateIn, s: Session = Depends(get_session)):
try:
settings_service.update_llm(
s,
provider=body.provider,
model=body.model,
host=body.host,
timeout=body.timeout,
api_key=body.api_key,
)
except ValueError as e:
raise HTTPException(400, str(e)) from e
return _llm_config(s)
@router.post("/settings/llm/test", response_model=LLMTestOut)
def test_llm(body: LLMTestIn):
"""저장 없이 연결만 테스트. provider/host/model/api_key 미지정 시 유효 설정값 사용.
api_key 미지정이면 저장된 키(eff.api_key)로 테스트(키 재입력 없이 모델 목록 조회 가능)."""
eff = runtime_config.effective_llm()
provider = body.provider or eff.provider
impl: LLMProvider = build_provider(
provider,
host=body.host or eff.host,
model=body.model or eff.model,
api_key=body.api_key if body.api_key is not None else eff.api_key,
)
h = impl.health()
return LLMTestOut(
reachable=bool(h.get("reachable")),
provider=h.get("provider", provider),
model=h.get("model", ""),
host=h.get("host"),
models=impl.list_models(),
detail=h.get("detail", ""),
)