mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-03 19:00:00 +08:00
* ♻️ 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>
411 lines
14 KiB
Python
411 lines
14 KiB
Python
"""
|
|
AI 模块配置数据域类型定义
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from enum import Enum
|
|
from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
from zhenxun.utils.pydantic_compat import model_copy, model_dump, model_validate
|
|
|
|
if TYPE_CHECKING:
|
|
from zhenxun.services.ai.llm.builder import IntentBuilder
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class ResponseFormat(Enum):
|
|
"""响应格式枚举"""
|
|
|
|
TEXT = "text"
|
|
JSON = "json"
|
|
MULTIMODAL = "multimodal"
|
|
|
|
|
|
class StructuredOutputStrategy(str, Enum):
|
|
"""结构化输出策略"""
|
|
|
|
NATIVE = "native"
|
|
"""使用原生 API (如 OpenAI json_object/json_schema, Gemini mime_type)"""
|
|
|
|
TOOL_CALL = "tool_call"
|
|
"""构造虚假工具调用来强制输出结构化数据 (适用于指令跟随弱但工具调用强的模型)"""
|
|
PROMPT = "prompt"
|
|
"""仅在 Prompt 中追加 Schema 说明,依赖文本补全"""
|
|
|
|
|
|
class EmbeddingTaskType(str, Enum):
|
|
"""
|
|
文本嵌入任务类型 (对应 Gemini embedding 模型的 task_type 参数)
|
|
"""
|
|
|
|
RETRIEVAL_QUERY = "RETRIEVAL_QUERY"
|
|
"""指定给定的文本是搜索/检索设置中的查询 (Query)。"""
|
|
RETRIEVAL_DOCUMENT = "RETRIEVAL_DOCUMENT"
|
|
"""指定给定的文本是被搜索语料库中的文档 (Document)。"""
|
|
SEMANTIC_SIMILARITY = "SEMANTIC_SIMILARITY"
|
|
"""指定文本将用于语义文本相似度 (STS) 计算。"""
|
|
CLASSIFICATION = "CLASSIFICATION"
|
|
"""指定嵌入向量将用于文本分类任务。"""
|
|
CLUSTERING = "CLUSTERING"
|
|
"""指定嵌入向量将用于聚类任务。"""
|
|
QUESTION_ANSWERING = "QUESTION_ANSWERING"
|
|
"""指定文本将用于问答任务。"""
|
|
FACT_VERIFICATION = "FACT_VERIFICATION"
|
|
"""指定文本将用于事实核查任务。"""
|
|
|
|
|
|
class BaseOutputDefinition(Generic[T]):
|
|
"""声明式结构化输出基类"""
|
|
|
|
type_: type[T]
|
|
|
|
|
|
class ToolOutput(BaseOutputDefinition[T]):
|
|
"""工具输出标记:使用强制工具调用 (Tool Call) 结束任务并返回指定结构"""
|
|
|
|
name: str | None = None
|
|
description: str | None = None
|
|
strict: bool | None = None
|
|
|
|
def __init__(
|
|
self,
|
|
type_: type[T],
|
|
name: str | None = None,
|
|
description: str | None = None,
|
|
strict: bool | None = None,
|
|
):
|
|
self.type_ = type_
|
|
self.name = name
|
|
self.description = description
|
|
self.strict = strict
|
|
|
|
|
|
class ReasoningEffort(str, Enum):
|
|
"""推理努力程度枚举"""
|
|
|
|
NONE = "NONE"
|
|
"""不开启推理思考"""
|
|
MINIMAL = "MINIMAL"
|
|
"""极低推理努力,追求最快响应"""
|
|
LOW = "LOW"
|
|
"""较低推理努力"""
|
|
MEDIUM = "MEDIUM"
|
|
"""中等推理努力(通常是默认值)"""
|
|
HIGH = "HIGH"
|
|
"""高推理努力"""
|
|
XHIGH = "XHIGH"
|
|
"""极高推理努力"""
|
|
MAX = "MAX"
|
|
"""最大推理努力 (如 GLM / DeepSeek)"""
|
|
|
|
|
|
class ImageAspectRatio(str, Enum):
|
|
"""图像宽高比枚举"""
|
|
|
|
SQUARE = "1:1"
|
|
"""正方形"""
|
|
LANDSCAPE_16_9 = "16:9"
|
|
"""横向宽屏 16:9"""
|
|
PORTRAIT_9_16 = "9:16"
|
|
"""竖向全屏 9:16"""
|
|
LANDSCAPE_4_3 = "4:3"
|
|
"""横向标准 4:3"""
|
|
PORTRAIT_3_4 = "3:4"
|
|
"""竖向标准 3:4"""
|
|
LANDSCAPE_3_2 = "3:2"
|
|
"""横向 3:2"""
|
|
PORTRAIT_2_3 = "2:3"
|
|
"""竖向 2:3"""
|
|
|
|
|
|
class ImageResolution(str, Enum):
|
|
"""图像分辨率/质量枚举"""
|
|
|
|
STANDARD = "STANDARD"
|
|
"""标准分辨率"""
|
|
HD = "HD"
|
|
"""高清分辨率"""
|
|
|
|
|
|
class CommonLLMConfig(BaseModel):
|
|
"""三大厂商通用基础生成参数"""
|
|
|
|
temperature: float | None = Field(default=None, ge=0.0, le=2.0)
|
|
"""采样温度。较高的值会使输出更加随机,较低的值会使其更加集中和确定。"""
|
|
max_tokens: int | None = Field(default=None, gt=0)
|
|
"""聊天完成时生成的最大 Token 数。"""
|
|
top_p: float | None = Field(default=None, ge=0.0, le=1.0)
|
|
"""核采样 (Nucleus sampling) 概率阈值。"""
|
|
top_k: int | None = Field(default=None, gt=0)
|
|
"""仅从概率最高的前 K 个 Token 中采样 (并非所有模型支持)。"""
|
|
frequency_penalty: float | None = Field(default=None, ge=-2.0, le=2.0)
|
|
"""频率惩罚。正值根据新 Token 在文本中的现有频率对其进行惩罚,
|
|
降低模型逐字重复同一行的可能性。"""
|
|
presence_penalty: float | None = Field(default=None, ge=-2.0, le=2.0)
|
|
"""存在惩罚。正值根据新 Token 到目前为止是否出现在文本中对其进行惩罚,
|
|
增加模型谈论新主题的可能性。"""
|
|
repetition_penalty: float | None = Field(default=None, ge=0.0, le=2.0)
|
|
"""重复惩罚系数 (部分非 OpenAI 兼容模型独有)。"""
|
|
stop: list[str] | str | None = Field(default=None)
|
|
"""API 停止生成后续 Token 的停止词序列。"""
|
|
reasoning_effort: ReasoningEffort | str | None = Field(default=None)
|
|
"""跨厂商统一的思考/推理等级意图(如 'low', 'high', 'max')。
|
|
具体映射由底层的 Adapter 执行。"""
|
|
|
|
|
|
class OutputFormatConfig(BaseModel):
|
|
"""输出格式与结构化控制"""
|
|
|
|
response_format: ResponseFormat | dict[str, Any] | None = Field(default=None)
|
|
"""响应格式类型 (枚举或字典形式的 json_schema 对象)。"""
|
|
response_mime_type: str | None = Field(default=None)
|
|
"""指定 MIME 类型 (如 application/json),主要用于 Gemini。"""
|
|
response_schema: dict[str, Any] | None = Field(default=None)
|
|
"""JSON Schema 字典,用于强制约束模型返回的 JSON 结构。"""
|
|
response_modalities: list[str] | None = Field(default=None)
|
|
"""允许的响应模态 (如 ["TEXT", "IMAGE"]),主要用于 Gemini。"""
|
|
structured_output_strategy: StructuredOutputStrategy | str | None = Field(
|
|
default=None
|
|
)
|
|
"""结构化输出所采用的内部策略。"""
|
|
|
|
|
|
class ToolCallConfig(BaseModel):
|
|
"""工具调用统一策略配置"""
|
|
|
|
mode: Literal["AUTO", "ANY", "NONE"] = Field(default="AUTO")
|
|
"""工具调用模式 (AUTO: 自动, ANY: 强制至少调一个, NONE: 禁用)。"""
|
|
allowed_function_names: list[str] | None = Field(default=None)
|
|
"""允许被调用的特定函数名称白名单。"""
|
|
include_server_side_tool_invocations: bool | None = Field(default=None)
|
|
"""是否包含服务端侧的工具调用日志流转 (主要用于 Gemini)。"""
|
|
|
|
|
|
class BaseProviderOption(BaseModel):
|
|
"""厂商配置逃生舱基类"""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow") # type: ignore
|
|
|
|
|
|
class OpenAIOptions(BaseProviderOption):
|
|
"""OpenAI 专属特权参数 (适配 Responses API)"""
|
|
|
|
store: bool | None = Field(default=None)
|
|
"""是否允许服务端留存本次请求的选项记录"""
|
|
metadata: dict[str, str] | None = Field(default=None)
|
|
"""附加在请求上的自定义元数据"""
|
|
|
|
|
|
class GeminiOptions(BaseProviderOption):
|
|
"""Gemini 专属特权参数"""
|
|
|
|
include_thoughts: bool | None = Field(default=None)
|
|
"""是否在最终响应中包含模型的内部思考过程 (Thoughts)"""
|
|
safety_settings: dict[str, str] | None = Field(default=None)
|
|
"""Gemini 专有的各个维度的安全过滤阈值配置"""
|
|
retrieval_config: dict[str, Any] | None = Field(default=None)
|
|
"""检索定位配置,如 LBS 经纬度信息,配合 Google Maps 工具使用"""
|
|
|
|
|
|
class OpenAITTSOptions(BaseProviderOption):
|
|
"""OpenAI TTS 专属特权参数"""
|
|
|
|
voice_id: str | None = Field(default=None)
|
|
"""专属的音色 ID 配置"""
|
|
|
|
|
|
class GeminiTTSOptions(BaseProviderOption):
|
|
"""Gemini TTS 专属特权参数"""
|
|
|
|
voice_id: str | None = Field(default=None)
|
|
"""专属的音色 ID 配置"""
|
|
multi_speaker: bool | None = Field(default=None)
|
|
"""是否开启多说话人模式"""
|
|
second_voice: str | None = Field(default=None)
|
|
"""多说话人模式下的第二音色名称"""
|
|
|
|
|
|
class MiniMaxTTSOptions(BaseProviderOption):
|
|
"""MiniMax TTS 专属特权参数 (控制极度精细)"""
|
|
|
|
voice_id: str | None = Field(default=None)
|
|
"""专属的音色 ID 配置"""
|
|
vol: float | None = Field(default=None, gt=0.0, le=10.0)
|
|
"""音量,范围 (0, 10]"""
|
|
pitch: int | None = Field(default=None, ge=-12, le=12)
|
|
"""语调,范围 [-12, 12]"""
|
|
emotion: (
|
|
Literal[
|
|
"happy",
|
|
"sad",
|
|
"angry",
|
|
"fearful",
|
|
"disgusted",
|
|
"surprised",
|
|
"calm",
|
|
"fluent",
|
|
"whisper",
|
|
]
|
|
| None
|
|
) = Field(default=None)
|
|
"""情感控制"""
|
|
timbre_weights: list[dict[str, Any]] | None = Field(default=None)
|
|
"""音色混合权重 (最多4种)"""
|
|
pronunciation_dict: dict[str, list[str]] | None = Field(default=None)
|
|
"""自定义发音字典 (如: {"tone": ["处理/(chu3)(li3)"]})"""
|
|
|
|
|
|
class MiMoTTSOptions(BaseProviderOption):
|
|
"""MiMo TTS 专属特权参数"""
|
|
|
|
voice_id: str | None = Field(default=None)
|
|
"""专属的音色 ID 配置"""
|
|
|
|
|
|
class MediaGenerationConfig(BaseModel):
|
|
"""多模态媒体生成/优化的全局配置"""
|
|
|
|
aspect_ratio: ImageAspectRatio | str | None = Field(default=None)
|
|
"""生成的图像/视频宽高比 (如 '16:9')"""
|
|
resolution: str | None = Field(default=None)
|
|
"""生成的图像/视频分辨率 (如 '1K', '4K' 或 '1024x1024')"""
|
|
quality: Literal["low", "medium", "high", "standard", "hd"] | None = Field(
|
|
default=None
|
|
)
|
|
"""渲染质量及细节丰富水平"""
|
|
|
|
|
|
class TTSConfig(BaseModel):
|
|
"""文本转语音 (TTS) 全局配置"""
|
|
|
|
response_format: Literal["mp3", "wav", "pcm", "flac", "opus", "aac"] = Field(
|
|
default="mp3"
|
|
)
|
|
"""输出音频格式"""
|
|
speed: float = Field(default=1.0, ge=0.25, le=4.0)
|
|
"""语速 (通用映射)"""
|
|
|
|
openai_options: OpenAITTSOptions = Field(default_factory=OpenAITTSOptions)
|
|
"""OpenAI 厂商专属请求参数集"""
|
|
gemini_options: GeminiTTSOptions = Field(default_factory=GeminiTTSOptions)
|
|
"""Gemini 厂商专属请求参数集"""
|
|
minimax_options: MiniMaxTTSOptions = Field(default_factory=MiniMaxTTSOptions)
|
|
"""MiniMax 厂商专属请求参数集"""
|
|
mimo_options: MiMoTTSOptions = Field(default_factory=MiMoTTSOptions)
|
|
"""MiMo 厂商专属请求参数集"""
|
|
|
|
custom_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
"""兜底逃生舱,包含的键值对将直接透传至顶层请求体中 (可用于缓存 TTL)"""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
|
|
class GenerationConfig(BaseModel):
|
|
"""
|
|
现代化 LLM 生成基座 (Intent-Driven Base)。
|
|
隔离通用参数与厂商私有参数,彻底终结"上帝类"。
|
|
"""
|
|
|
|
common: CommonLLMConfig = Field(default_factory=CommonLLMConfig)
|
|
"""大模型生成核心通用配置项"""
|
|
output: OutputFormatConfig = Field(default_factory=OutputFormatConfig)
|
|
"""输出格式与约束控制配置项"""
|
|
tools: ToolCallConfig = Field(default_factory=ToolCallConfig)
|
|
"""工具调用策略与函数声明配置项"""
|
|
media: MediaGenerationConfig = Field(default_factory=MediaGenerationConfig)
|
|
"""多媒体生成相关配置项"""
|
|
|
|
openai_options: OpenAIOptions = Field(default_factory=OpenAIOptions)
|
|
"""OpenAI 厂商专属请求参数集"""
|
|
gemini_options: GeminiOptions = Field(default_factory=GeminiOptions)
|
|
"""Gemini 厂商专属请求参数集"""
|
|
|
|
enable_caching: bool | None = Field(default=None)
|
|
"""是否在此次生成中开启上下文缓存 (Context Caching)"""
|
|
custom_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
"""兜底逃生舱,包含的键值对将直接透传至顶层请求体中"""
|
|
validation_policy: dict[str, Any] | None = Field(default=None)
|
|
"""自定义验证策略字典"""
|
|
response_validator: Callable[[Any], None] | None = Field(default=None)
|
|
"""针对原始返回对象的自定义回调验证器"""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
@classmethod
|
|
def builder(cls) -> "IntentBuilder":
|
|
from zhenxun.services.ai.llm.builder import IntentBuilder
|
|
|
|
return IntentBuilder()
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return model_dump(self, exclude_none=True)
|
|
|
|
def merge_with(self, other: "GenerationConfig | None") -> "GenerationConfig":
|
|
"""深度合并两个配置,实现配置的无损叠加"""
|
|
if not other:
|
|
return model_copy(self, deep=True)
|
|
|
|
base_dump = model_dump(self, exclude_none=True)
|
|
other_dump = model_dump(other, exclude_none=True)
|
|
|
|
def deep_merge(d1: dict, d2: dict) -> dict:
|
|
res = d1.copy()
|
|
for k, v in d2.items():
|
|
if isinstance(v, dict) and k in res and isinstance(res[k], dict):
|
|
res[k] = deep_merge(res[k], v)
|
|
else:
|
|
res[k] = v
|
|
return res
|
|
|
|
merged_dump = deep_merge(base_dump, other_dump)
|
|
return model_validate(GenerationConfig, merged_dump)
|
|
|
|
|
|
class LLMEmbeddingConfig(BaseModel):
|
|
"""Embedding 专用配置"""
|
|
|
|
task_type: str | None = Field(default=None)
|
|
"""生成意图的任务类型,参考 EmbeddingTaskType (主要用于 Gemini 和 Jina)"""
|
|
output_dimensionality: int | None = Field(default=None)
|
|
"""请求模型强制输出(或截断)的较低维度数,实现维度压缩"""
|
|
title: str | None = Field(default=None)
|
|
"""提供该文档的标题以供底层优化。仅在 task_type 为 RETRIEVAL_DOCUMENT 时有效。"""
|
|
encoding_format: str | None = Field(default="float")
|
|
"""向量数据在响应中的编码格式 (通常为 float 或 base64)"""
|
|
multimodal: bool | list[str] = Field(default=False)
|
|
"""是否允许多模态向量化。False 表示纯文本(极速安全);True 表示全部放行;
|
|
也可传入 ['image', 'text'] 细粒度控制。"""
|
|
custom_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
"""兜底逃生舱,包含的键值对将直接透传至顶层请求体中 (可用于缓存 TTL)"""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
|
|
__all__ = [
|
|
"BaseProviderOption",
|
|
"CommonLLMConfig",
|
|
"EmbeddingTaskType",
|
|
"GeminiOptions",
|
|
"GeminiTTSOptions",
|
|
"GenerationConfig",
|
|
"ImageAspectRatio",
|
|
"ImageResolution",
|
|
"LLMEmbeddingConfig",
|
|
"MiMoTTSOptions",
|
|
"MiniMaxTTSOptions",
|
|
"OpenAIOptions",
|
|
"OpenAITTSOptions",
|
|
"OutputFormatConfig",
|
|
"ReasoningEffort",
|
|
"ResponseFormat",
|
|
"StructuredOutputStrategy",
|
|
"TTSConfig",
|
|
"ToolCallConfig",
|
|
"ToolOutput",
|
|
]
|