Files
kplam bdd30f0a88 fix: 修复会话鉴权「登录后 token 无效」并补齐 NAS 部署流程
- deps.py: _create_redis_client 增加同步 ping 校验,Redis 不可达时正确降级为内存模式
- main.py: lifespan 复用 deps 的 UserStore 单例,避免 admin 与 API 请求实例不一致
- 前端: 强制改密弹窗(must_change_password 用户)、兼容新旧登录返回格式、markPasswordChanged
- 新增 NAS SSH 部署脚本与批处理测试;gitignore 前端构建产物
2026-08-04 11:38:28 +08:00

116 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""运行时配置 APIGET/PUT /api/v1/settings、GET /api/v1/settings/schema、POST /api/v1/settings/reset
GET 任何登录用户可读;PUT/reset 需 admin。PUT 后会清空 LLM 客户端 / 解析插件 /
去重策略三处进程级缓存,使新配置立即对后续请求生效。
"""
from typing import Any
import structlog
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from app.api.response import ApiError, ok
from app.api.deps import get_current_user, require_admin
from app.core.users import UserRecord
from app.core.dedup import invalidate_dedup_strategy_cache
from app.core.file_parser import (
list_docx_plugins,
list_ocr_plugins,
list_pdf_plugins,
invalidate_parser_plugin_cache,
)
from app.core.runtime_settings import (
RuntimeSettings,
get_runtime_settings,
reset_runtime_settings,
update_runtime_settings,
)
from app.services.llm import invalidate_llm_client_cache
logger = structlog.get_logger()
router = APIRouter(prefix="/api/v1", tags=["settings"])
class SettingsUpdateRequest(BaseModel):
"""Settings PATCH body:任意子树可缺省,缺省字段保留原值
例:{"models": {"summarize": {"model": "qwen2.5:3b"}}}、
{"parsers": {"ocr": {"plugin": "tesseract"}}}、
{"dedup": {"strategy": "simhash", "simhash_threshold": 5}}
"""
models: dict[str, Any] | None = None
parsers: dict[str, Any] | None = None
dedup: dict[str, Any] | None = None
@router.get("/settings")
async def get_settings(user: UserRecord = Depends(get_current_user)) -> dict[str, Any]:
"""返回当前 RuntimeSettings(任何登录用户可读)"""
cfg = get_runtime_settings()
return ok(cfg.model_dump(mode="json"))
@router.put("/settings")
async def update_settings(
body: SettingsUpdateRequest,
user: UserRecord = Depends(require_admin),
) -> dict[str, Any]:
"""部分更新 RuntimeSettings(仅 admin
更新成功后清空 LLM 客户端 / 解析插件 / 去重策略三处进程级缓存,
使新配置立即对后续请求生效。
"""
patch = body.model_dump(exclude_none=True)
if not patch:
raise ApiError(1001, "请求体为空,未提供任何待更新字段")
try:
cfg = update_runtime_settings(patch)
except Exception as exc:
logger.error("RuntimeSettings 更新失败", error=str(exc), exc_info=True)
raise ApiError(2000, f"配置更新失败: {exc}") from exc
# 清缓存:让后续读取拿到新配置
invalidate_llm_client_cache()
invalidate_parser_plugin_cache()
invalidate_dedup_strategy_cache()
logger.info("RuntimeSettings 已更新并清理缓存", operator=user.username)
return ok(cfg.model_dump(mode="json"))
@router.get("/settings/schema")
async def get_settings_schema(
user: UserRecord = Depends(get_current_user),
) -> dict[str, Any]:
"""返回可选插件与策略列表(前端 Settings 页渲染选项用)"""
return ok(
{
"llm_providers": ["ollama", "openai_compatible"],
"pdf_plugins": list_pdf_plugins(),
"docx_plugins": list_docx_plugins(),
"ocr_plugins": list_ocr_plugins(),
"dedup_strategies": ["none", "sha256", "simhash"],
}
)
@router.post("/settings/reset")
async def reset_settings(
user: UserRecord = Depends(require_admin),
) -> dict[str, Any]:
"""重置 RuntimeSettings 为默认值(仅 admin),同时清缓存"""
try:
cfg = reset_runtime_settings()
except Exception as exc:
logger.error("RuntimeSettings 重置失败", error=str(exc), exc_info=True)
raise ApiError(2000, f"配置重置失败: {exc}") from exc
invalidate_llm_client_cache()
invalidate_parser_plugin_cache()
invalidate_dedup_strategy_cache()
logger.info("RuntimeSettings 已重置为默认值", operator=user.username)
return ok(cfg.model_dump(mode="json"))