Files
zhenxun_bot/zhenxun/services/ai/config/models.py
922d092650 ♻️ refactor(core): 重构 AI 能力与定时任务调度系统 (#2148)
* ♻️ refactor(core): 重构 AI 能力与定时任务调度系统

- 【AI 能力与工具】重构 Capability 注册与管理机制,引入 CapabilityManager 统一管理
- 移除全局能力注册表,改用声明式装饰器 `@capability` 进行解耦注册
- 重构工具解析器链,使用统一的 BaseToolResolver 代替原有的多个特定解析器
- 增强工具查询过滤,支持通配符匹配、工具箱过滤和排除标签
- 【定时任务调度】重构定时任务管理器,引入 SchedulerRegistry 统一管理任务元数据
- 引入 JobConfig 聚合定时任务配置,支持用户维度的定时任务调度
- 重构执行分发器,支持并发限制、串行间隔和随机延迟打散
- 【运行上下文】引入 ScheduledDeps 以支持后台和定时任务环境下的依赖注入
- 优化 RunContext,支持从定时任务上下文快速构造,并提供 emit 辅助方法
- 【日志与监控】引入 AILoggerProxy,实现 AI 各模块的专属日志输出
- 将各模块的全局 logger 替换为对应的模块专属日志代理
- 【其他优化】修复 Pydantic V1 兼容层中 model_validator 的装饰器兼容性问题
- 在非交互式环境(如定时任务)中自动隐藏 HITL 交互工具以节省 Token

* ♻️ refactor(core): 优化内部导入路径并提升 Pydantic 兼容性

- 【重构】将 `services/ai` 模块内的绝对导入重构为相对导入,优化包结构
- 【重构】移除不必要的 `if TYPE_CHECKING` 保护,通过 `from __future__ import annotations` 直接导入类型
- 【清理】清理 `core/messages/types.py` 中未使用的 `AssistantContentUnion` 等联合类型定义
- 【优化】在 `utils/pydantic_compat.py` 中新增 `model_rebuild` 兼容函数,统一 Pydantic V1/V2 的模型重建逻辑
- 【优化】将部分函数内部的延迟导入提升至模块顶部,规范代码结构

* ♻️ refactor(imports): 优化导入路径为相对导入并清理冗余导入

- 【重构】将 AI 服务相关模块中的绝对导入路径修改为相对导入,提升模块内聚性与可移植性
- 【清理】移除多处函数内部或类方法中未使用的冗余导入,避免循环引用和资源浪费
- 【格式化】微调部分工具装饰器和返回语句的格式与尾随逗号

* 🚨 auto fix by pre-commit hooks

---------

Co-authored-by: webjoin111 <455457521@qq.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-07-10 09:14:06 +08:00

212 lines
8.4 KiB
Python

from pydantic import BaseModel, Field
from zhenxun.services.ai.core.models import ModelDetail
class DebugLogOptions(BaseModel):
"""调试日志细粒度控制选项"""
show_tools: bool = True
"""是否在日志中显示工具定义 (JSON Schema)"""
show_schema: bool = True
"""是否在日志中显示结构化输出 Schema (response_format)"""
show_safety: bool = True
"""是否在日志中显示安全设置 (safetySettings)"""
def __bool__(self) -> bool:
return self.show_tools or self.show_schema or self.show_safety
class ClientSettings(BaseModel):
"""LLM 客户端底层网络与重试设置"""
timeout: int = 300
"""API 请求超时时间 (秒)"""
max_retries: int = 3
"""请求失败时的最大重试次数"""
retry_delay: int = 2
"""请求重试的基础延迟时间 (秒)"""
structured_retries: int = 2
"""结构化生成校验失败时的最大重试次数 (IVR)"""
class LLMSummaryConfig(BaseModel):
"""LLM 自然语言总结压缩策略配置"""
enable: bool = True
"""是否开启大模型对话总结以压缩上下文"""
trigger_threshold: float = 0.8
"""触发压缩的 Token 阈值。<=1.0 为比例,>1.0 为绝对 Token 数"""
max_history_turns: int = 0
"""触发压缩的最大历史对话轮数。设为 0 表示不限制轮数(仅受 Token 阈值控制)。"""
summarization_model: str | None = "DeepSeek/deepseek-v4-flash"
"""指定用于执行总结任务的大模型名称,为空则使用全局默认"""
summarization_prompt: str = (
"请以客观、精炼的语言概括以下对话内容。重点保留:"
"1. 核心讨论话题及重要决定;"
"2. 用户的个性特征、核心偏好、提及的生活背景或特殊设定;"
"3. 双方互动的温度与情感基调。无需保留寒暄等客套话。"
)
"""指导大模型进行总结的系统提示词"""
keep_recent_turns: int = 3
"""在总结之外,强制原样保留的最近对话轮数"""
class ToolPruningConfig(BaseModel):
"""工具结果修剪策略配置"""
enable: bool = False
"""是否开启长工具输出结果的自动修剪"""
trigger_threshold: float = 0.6
"""触发修剪的工具纯 Token 阈值。<=1.0 为比例,>1.0 为绝对 Token 数"""
max_history_turns: int = 15
"""触发修剪的最大工具消息轮数。设为 0 表示不限制轮数。"""
keep_recent_turns: int = 3
"""修剪时强制原样保留的最新的工具消息轮数,确保当下反思不受影响"""
class ContextManagementSettings(BaseModel):
"""智能上下文管理与压缩算法设置"""
llm_summary: LLMSummaryConfig = Field(default_factory=LLMSummaryConfig)
"""大模型自然语言总结策略"""
vision_window_size: int = Field(default=3)
"""多模态滑动窗口大小。0表示无限制,>0表示仅保留最近N轮包含多模态真实数据的消息,超龄则自动降级为占位符"""
tool_pruning: ToolPruningConfig = Field(default_factory=ToolPruningConfig)
"""工具结果过载修剪策略"""
class GeminiProviderSettings(BaseModel):
"""Gemini 厂商专属高级配置"""
safety_threshold: str = Field(default="BLOCK_NONE")
"""Gemini 安全过滤阈值 (BLOCK_LOW_AND_ABOVE, BLOCK_MEDIUM_AND_ABOVE,
BLOCK_ONLY_HIGH, BLOCK_NONE)"""
allow_mixed_tools: bool = Field(default=False)
"""是否允许同时混合使用本地自定义工具和厂商云端内置工具"""
class ProviderSettingsGroup(BaseModel):
"""按厂商划分的高级专属设置组"""
gemini: GeminiProviderSettings = Field(default_factory=GeminiProviderSettings)
"""Gemini 相关专属配置"""
class ProviderConfig(BaseModel):
"""LLM 服务提供商 (接口方) 配置模型"""
name: str
"""提供商唯一标识名称"""
api_key: str | list[str]
"""API 密钥或密钥列表 (支持轮询)"""
api_base: str | None = None
"""API 基础 URL 路径"""
api_type: str = "openai"
"""API 协议类型 (openai/gemini/zhipu/etc.)"""
temperature: float | None = None
"""该提供商下模型的默认温度"""
max_output_tokens: int | None = None
"""该提供商下模型的默认最大输出限制"""
models: list[ModelDetail]
"""该提供商提供的具体模型列表"""
timeout: int = 180
"""针对该提供商的特定超时时间"""
class DefaultModelsConfig(BaseModel):
"""按任务分类的默认模型配置"""
chat: str | None = Field(default="Gemini/gemini-3.5-flash")
embedding: str | None = Field(default="Gemini/gemini-embedding-2")
tts: str | None = Field(default="Gemini/gemini-3.1-flash-tts-preview")
image: str | None = Field(default="Gemini/gemini-2.5-flash-image")
rerank: str | None = Field(default="siliconflow/BAAI/bge-reranker-v2-m3")
class AgentEngineSettings(BaseModel):
"""全局默认的 Agent 推理引擎配置"""
max_cycles: int = 10
"""工具调用最大循环次数"""
global_max_cycles: int = 30
"""整个会话生命周期内(跨嵌套智能体)的大模型绝对循环次数上限,用于防死循环"""
enable_parallel_calls: bool = True
"""允许并行工具调用"""
reflexion_retries: int = 1
"""反思重试次数"""
enable_fallback_summary: bool = True
"""达到最大循环次数时,是否触发大模型兜底总结(而不是直接报错)"""
enable_hitl: bool = False
"""是否允许智能体主动挂起任务,向用户求助 (Human-in-the-Loop)"""
mcp_cleanup_timeout: int = 900
"""MCP 服务自动清理的闲置超时时间(秒)。0表示关闭自动清理机制(永久驻留)"""
class SandboxSettings(BaseModel):
"""沙箱底层基础设施环境配置"""
enable_sandbox: bool = Field(default=False)
"""全局沙箱功能硬开关。关闭后将彻底不加载沙箱底层驱动(如 Docker),
极大提升冷启动速度。"""
sandbox_type: str = Field(default="docker")
"""沙箱底层驱动类型: docker 等"""
docker_image: str = Field(default="zhenxun-sandbox:latest")
"""Docker 沙箱使用的镜像名称 (自定义 Jupyter 增强版)"""
cleanup_timeout: int = Field(default=1800)
"""沙箱自动清理的闲置超时时间(秒)。0表示关闭,不自动清理"""
enable_vfs_helper: bool = Field(default=True)
"""是否开启 VFS 路径逃逸防范探针,默认开启。遇到兼容性问题时可关闭"""
class LLMConfig(BaseModel):
"""AI 模块全局持久化配置总模型"""
default_models: DefaultModelsConfig = Field(default_factory=DefaultModelsConfig)
"""全局按任务分类的默认模型路由表"""
client_settings: ClientSettings = Field(default_factory=ClientSettings)
"""客户端通用连接配置"""
providers: list[ProviderConfig] = Field(default_factory=list)
"""已配置的提供商列表"""
debug_log: DebugLogOptions = Field(default_factory=DebugLogOptions)
"""日志调试开关配置"""
context_settings: ContextManagementSettings = Field(
default_factory=ContextManagementSettings
)
"""上下文管理相关配置"""
model_groups: dict[str, list[str]] = Field(
default_factory=lambda: {
"cheap_models": [
"Gemini/gemini-3.5-flash",
"Doubao/doubao-seed-1-6-250615",
],
}
)
"""虚拟模型路由组配置 (Virtual Router Groups)"""
agent_settings: AgentEngineSettings = Field(default_factory=AgentEngineSettings)
"""Agent 执行引擎层核心默认参数配置"""
sandbox: SandboxSettings = Field(default_factory=SandboxSettings)
"""沙箱基础设施环境相关配置"""
provider_settings: ProviderSettingsGroup = Field(
default_factory=ProviderSettingsGroup
)
"""按厂商划分的专属高级全局开关与策略"""
def validate_model_name(self, provider_model_name: str) -> bool:
"""验证模型名称在当前配置中是否存在"""
if "/" not in provider_model_name:
return provider_model_name.strip() in self.model_groups
if not provider_model_name or "/" not in provider_model_name:
return False
parts = provider_model_name.split("/", 1)
p_name, m_name = parts[0], parts[1]
for p in self.providers:
if p.name == p_name:
for m in p.models:
if m.model_name == m_name:
return True
return False