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
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", ""),
|
|
)
|