feat(admin): Angel(Agnes) provider 凭据 DB 化 + 安全 key_set 字段

- llm_settings.agnes_api_key           TEXT   (DB key 优先,.env 兜底)
- llm_settings.agnes_base_url_override VARCHAR (留空 = 用 .env)
- alembic 0005_agnes_key 迁移
- LlmSettingOut.agnes_api_key_set (bool) 替代直接回传 key
- LlmSettingUpdate 加 agnes_api_key / agnes_base_url_override(可空可清空)
- providers.get_angel_client 改用 DB key 优先
- enrichment.py 改为 get_angel_client() 工厂调用(热改 key 不需重启)
- /admin/llm/settings/test 走 get_angel_client(测的是 DB 里的 key)
- 前端 AdminLlmSettings 在'总开关 + 模型'卡里加 Angel api_key 输入框 +
  base_url 覆盖 + 已配置/未配置指示灯 + 清空按钮
- 顶部'测连接'按钮复用(测的就是 Angel)
This commit is contained in:
xiaji
2026-06-12 20:43:54 +08:00
parent 785b63cfed
commit aaf728f3f4
8 changed files with 179 additions and 15 deletions

View File

@@ -92,13 +92,24 @@ class TestResponse(BaseModel):
@router.post("/settings/test", response_model=TestResponse)
async def test_connection():
"""最小测试:发一个 'hi' chat 请求,确认 key + 端点通。"""
"""最小测试:发一个 'hi' chat 请求,确认 key + 端点通。
优先用 llm_settings 表里的 agnes_api_key / agnes_base_url_override,
都没有再 fallback 到 .env 里的 agnes_api_key / agnes_base_url。
"""
from app.services.llm.providers import get_angel_client
async with AsyncSessionLocal() as session:
row = (await session.execute(select(LlmSetting).where(LlmSetting.id == 1))).scalar_one_or_none()
chat_model = row.chat_model if row else "agnes-2.0-flash"
client = LlmClient(chat_model=chat_model)
if row is None:
return TestResponse(ok=False, configured=False, detail="LLM 设置未初始化")
# 用工厂:DB key 优先,.env 兜底
client = get_angel_client(row)
if not client.is_configured():
return TestResponse(ok=False, configured=False, detail="AGNES_API_KEY 未配置")
return TestResponse(
ok=False, configured=False,
detail="Angel api_key 未配置(请在设置页填 key,或在 .env 配 AGNES_API_KEY)",
)
try:
reply = await client.chat(
system="你是测试助手,只用 1 个词回答 OK 或 FAIL。",