"""模型信息与运行时配置路由。""" from __future__ import annotations import asyncio from fastapi import APIRouter, HTTPException import config from agents import agent_factory, agent_registry, model_factory from api.models import ThinkingUpdateRequest from obs import get_logger logger = get_logger(__name__) router = APIRouter(tags=["模型"]) @router.get("/model") async def get_model_info(): """当前模型配置、工具清单与组装摘要。""" return { **model_factory.describe(), "agent": agent_factory.describe(), "generation": agent_registry.generation(), } @router.get("/model/tools") async def get_tools(): """工具清单(按分组),用于前端展示「agent 会什么」。""" from tools import registry registry.load_builtin_tools() return registry.describe() @router.post("/model/thinking") async def set_thinking(payload: ThinkingUpdateRequest): """切换思考级别。 思考级别烧在模型实例里,改它必须**重建 agent**——所以这里调 ``invalidate()`` 让下次请求重新编译,而不是原地改配置。重建期间 (百毫秒级) 的在途请求继续用旧实例,不受影响。 """ level = payload.level.strip().lower() if level not in model_factory.VALID_THINKING_LEVELS: raise HTTPException( status_code=400, detail={ "code": "invalid_level", "message": f"level 只能是 {' | '.join(model_factory.VALID_THINKING_LEVELS)}", }, ) if level == model_factory.normalize_thinking(None): return {"changed": False, "thinking": level, "message": "级别未变化"} # 级别来自环境变量,运行时改只能改进程内状态 + 失效重建 config.THINKING_LEVEL = level generation = await asyncio.to_thread(agent_registry.invalidate) logger.info("思考级别切换为 %s,agent 将于下次请求重建(generation=%d)", level, generation) return { "changed": True, "thinking": level, "generation": generation, "message": "已生效,下一个请求会使用新的模型实例", } @router.post("/model/reload") async def reload_agent(): """强制重建 agent。改完 .env 里的模型/窗口配置后用这个让改动生效。""" generation = await asyncio.to_thread(agent_registry.invalidate) return {"reloaded": True, "generation": generation}