mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-07 21:00:21 +08:00
* ✨ feat!(llm): 重构并升级大语言模型服务为全新 AI 智能体框架 - 【重构】将原 services/llm 重构并迁移至全新的 services/ai 架构,提供向下兼容垫片 - 【新增】引入 Agent、Team、Workflow 三大智能体与工作流编排范式 - 【新增】引入基于 RAG 的长期向量记忆与中期槽位记忆系统 - 【新增】引入基于 Docker 的安全代码执行沙箱环境 - 【新增】支持 MCP 协议,允许动态管理和调用 MCP 服务 - 【新增】引入输入输出安全合规护栏与自愈反思机制 - 【优化】重构并优化多厂商 API 适配器 (Gemini, OpenAI, DeepSeek, GLM 等) - 【优化】优化日志脱敏与 Token 预估机制 - 【移除】移除旧版 llm default 和 llm reset-key 命令,新增 llm mcp 管理命令 * 🔧 chore(deps): 更新项目依赖与配置 - 添加 mcp、jieba 和 aiodocker 依赖到配置文件及 requirements.txt - 在 pyright 配置中设置 reportMissingImports 为 none - 调整 .gitignore 中 resources 目录的忽略规则 * ♻️ refactor(tools): 重构工具终止机制并清理知识库日志输出 - 统一使用 `context.state["__end_run__"]` 替代 `EndRunResult` 控制任务结束 - 移除文件系统和向量知识库检索工具中 `ToolResult` 的 `.with_log` 调用 - 调整指令处理器(Directive)的返回值为 `tool_res.output` - 修复部分类型检查警告并优化联合类型判断语法 * ♻️ refactor(tools): 重构工具副作用指令与控制流熔断机制 - 引入 `DirectivePayload` 及 `ToolResult` 的子类以结构化表达工具副作用 - 移除通过 `context.state` 传递魔术变量的隐式控制流设计 - 重构 `DirectiveManager` 处理器接口,直接在处理器中修改 `AgentState` 并构建 `AgentRunResult` - 在 `StandardAgentExecutor` 中统一通过 `directive_manager` 调度工具返回的副作用指令 - 补全 `MessageBuilder` 中部分核心方法的文档注释 * 🐛 fix(sandbox): 修复 Docker 沙箱容器状态检测与会话清理逻辑 -【修复】修正 `is_alive` 中直接读取私有属性的问题,改用 `show()` 返回值 -【修复】解决 `execute_code` 中缓存的执行器与当前会话不一致的问题 -【优化】在清理工作区前增加容器存活检测,避免向已死容器发送请求 -【优化】创建容器时增加运行状态校验,若已停止则自动从缓存中移除并重建 -【优化】优化容器销毁和清理逻辑,静默处理容器不存在 (404) 的异常 * 📝 docs(core): 补充核心模块初始化方法的文档注释 * 🚨 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>
409 lines
14 KiB
Python
409 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 DeepSeekOptions(BaseProviderOption):
|
|
"""DeepSeek 专属特权参数"""
|
|
|
|
thinking: bool | None = Field(default=None)
|
|
"""是否强制开启或关闭 R1 模型的思维链过程"""
|
|
|
|
|
|
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)
|
|
gemini_options: GeminiTTSOptions = Field(default_factory=GeminiTTSOptions)
|
|
minimax_options: MiniMaxTTSOptions = Field(default_factory=MiniMaxTTSOptions)
|
|
mimo_options: MiMoTTSOptions = Field(default_factory=MiMoTTSOptions)
|
|
|
|
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)
|
|
gemini_options: GeminiOptions = Field(default_factory=GeminiOptions)
|
|
deepseek_options: DeepSeekOptions = Field(default_factory=DeepSeekOptions)
|
|
|
|
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",
|
|
]
|