model_routes.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # -*- coding: utf-8 -*-
  2. """
  3. 模型管理 API —— 支持前端动态切换 LLM 模型版本
  4. 端点:
  5. - GET /api/model 获取当前模型和可用模型列表
  6. - POST /api/model/switch 切换运行时模型
  7. """
  8. from fastapi import APIRouter
  9. from pydantic import BaseModel, Field
  10. from api.model_config import (
  11. get_current_model,
  12. set_current_model,
  13. get_available_models,
  14. get_thinking_level,
  15. set_thinking_level,
  16. get_available_thinking_levels,
  17. invalidate_model_cache,
  18. )
  19. router = APIRouter(prefix="/model", tags=["模型管理"])
  20. # ── 请求模型 ──
  21. class ModelSwitchRequest(BaseModel):
  22. """模型切换请求"""
  23. model: str = Field(..., description="模型名称", examples=["deepseek-v4-pro", "deepseek-v4-flash"])
  24. class ThinkingSwitchRequest(BaseModel):
  25. """思考级别切换请求"""
  26. level: str = Field(..., description="思考级别", examples=["off", "high", "highest"])
  27. # ── GET /api/model ──
  28. @router.get("")
  29. async def get_model_info():
  30. """获取当前模型、思考级别和可用列表。"""
  31. return {
  32. "current": get_current_model(),
  33. "available": get_available_models(),
  34. "thinking_level": get_thinking_level(),
  35. "thinking_levels": get_available_thinking_levels(),
  36. }
  37. # ── POST /api/model/switch ──
  38. @router.post("/switch")
  39. async def switch_model(req: ModelSwitchRequest):
  40. """切换运行时模型。
  41. 切换后会自动失效所有 chat_routes 下智能体的 Agent 缓存,
  42. 下次请求时将使用新模型重新创建 Agent。
  43. 注意:仅影响对话解读 / 配风计划审查智能体,
  44. click_routes 下的点选解读智能体不受影响。
  45. """
  46. model_name = req.model.strip()
  47. if model_name not in get_available_models():
  48. return {
  49. "error": f"不支持的模型: {model_name}",
  50. "available": get_available_models(),
  51. }
  52. # 1. 更新运行时模型配置
  53. set_current_model(model_name)
  54. # 2. 失效模型实例缓存
  55. invalidate_model_cache()
  56. # 3. 失效所有受影响的 Agent 单例缓存
  57. try:
  58. from agents.vent_agent import invalidate_dialog_cache
  59. invalidate_dialog_cache()
  60. except Exception as e:
  61. print(f"[模型切换] 失效 dialog_agent 缓存失败: {e}")
  62. try:
  63. from agents.review_agent import invalidate_cache
  64. invalidate_cache()
  65. except Exception as e:
  66. print(f"[模型切换] 失效 review_agent 缓存失败: {e}")
  67. print(f"[模型切换] 已切换到 {model_name},所有受影响的 Agent 缓存已失效")
  68. return {
  69. "current": get_current_model(),
  70. "message": f"已切换到 {model_name},下次请求生效",
  71. }
  72. # ── POST /api/model/thinking ──
  73. @router.post("/thinking")
  74. async def switch_thinking(req: ThinkingSwitchRequest):
  75. """切换思考级别。
  76. 切换后会自动失效所有 chat_routes 下智能体的 Agent 缓存,
  77. 下次请求时将使用新思考级别重新创建模型实例。
  78. """
  79. level = req.level.strip().lower()
  80. if level not in get_available_thinking_levels():
  81. return {
  82. "error": f"不支持的思考级别: {level}",
  83. "available": get_available_thinking_levels(),
  84. }
  85. # 1. 更新思考级别(内部已清除模型实例缓存)
  86. try:
  87. set_thinking_level(level)
  88. except ValueError as e:
  89. return {"error": str(e), "available": get_available_thinking_levels()}
  90. # 2. 失效所有受影响的 Agent 单例缓存
  91. try:
  92. from agents.vent_agent import invalidate_dialog_cache
  93. invalidate_dialog_cache()
  94. except Exception as e:
  95. print(f"[思考切换] 失效 dialog_agent 缓存失败: {e}")
  96. try:
  97. from agents.review_agent import invalidate_cache
  98. invalidate_cache()
  99. except Exception as e:
  100. print(f"[思考切换] 失效 review_agent 缓存失败: {e}")
  101. print(f"[思考切换] 已切换到 {level},所有受影响的 Agent 缓存已失效")
  102. return {
  103. "thinking_level": get_thinking_level(),
  104. "message": f"思考级别已切换为「{level}」,下次请求生效",
  105. }