Files
zhenxun_bot/zhenxun/services/ai/flow/base.py
T
80fc5b86a7 ✨ feat!(llm): 重构并升级大语言模型服务为全新 AI 智能体框架 (#2146)
* ✨ 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>
2026-07-03 08:53:56 +08:00

150 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from abc import ABC, abstractmethod
import asyncio
from collections.abc import AsyncIterator
import contextlib
from enum import Enum
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
from pydantic import BaseModel, Field
from zhenxun.services.ai.run.context import RunContext
from zhenxun.services.ai.run.ui import UIController
if TYPE_CHECKING:
from zhenxun.services.ai.flow.agent.models import Persona
from zhenxun.services.ai.run.models import StreamedRunResult
from zhenxun.services.ai.core.messages import PromptInput
T_RunResult = TypeVar("T_RunResult")
class ConcurrencyPolicy(str, Enum):
"""并发执行策略枚举"""
ALLOW = "allow"
"""允许并发:不做任何限制(适用于无状态或绝对独立任务)"""
REJECT = "reject"
"""拒绝新请求:当前有任务在执行时,直接丢弃新任务并提醒"""
QUEUE = "queue"
"""排队等待:当前有任务在执行时,新任务排队等待(先进先出)"""
INTERRUPT = "interrupt"
"""中断旧任务:新任务到达时,立即强制取消并覆盖正在执行的旧任务"""
class ConcurrencyScope(str, Enum):
"""并发作用域枚举(决定锁的粒度,解耦于会话隔离)"""
GLOBAL = "global"
"""全局互斥:整个系统同一时间只能执行一个该任务"""
GROUP = "group"
"""群组互斥:同一群组内串行排队(私聊退化为用户级),防止抢话刷屏"""
USER = "user"
"""用户互斥:同一用户发起的任务串行排队(允许同群不同人并行)"""
SESSION = "session"
"""会话互斥:跟随记忆 SessionID 进行物理锁隔离"""
class InterventionPolicy(str, Enum):
"""运行时消息干预策略枚举"""
IGNORE = "ignore"
"""忽略干预:丢弃在任务执行期间收到的额外消息(默认)"""
STEER = "steer"
"""动态转向:将额外消息立即注入到下一轮大模型推理历史中,影响其思考方向"""
FOLLOW_UP = "follow_up"
"""追加执行:将额外消息放入队列,在当前大模型意图(所有工具等)执行完毕后追加推理"""
class BaseRuntimeConfig(BaseModel):
"""所有可执行实体(Agent/Team/Workflow)的通用基础运行时配置"""
stateless: bool = Field(default=True)
"""是否使用临时会话,不持久化历史记录"""
concurrency_policy: ConcurrencyPolicy | None = Field(default=None)
"""并发执行策略。如果未显式指定,无状态(stateless=True)默认为ALLOW,有状态(stateless=False)默认为QUEUE。"""
concurrency_scope: ConcurrencyScope | None = Field(default=None)
"""并发作用域,决定锁的粒度。如果未显式指定,默认为 GROUP 级排队。"""
intervention_policy: InterventionPolicy | None = Field(default=None)
"""运行时干预策略,决定在大模型执行期间接收到新消息时该如何处理数据流合并。"""
class BaseRunnable(ABC, Generic[T_RunResult]):
"""
所有可执行 AI 编排实体的统一基类 (Composite Pattern)。
统一了 Agent, Team, Workflow 的核心契约,支持物理上的任意嵌套。
"""
name: str
"""可执行实体的名称标识"""
description: str
"""可执行实体的详细描述。用于外部路由(Router)或上层智能体(DelegateTool)决定是否调用它"""
persona: "Persona | dict | None" = None
"""(可选) 实体的角色设定 (Persona)。包含 role 和 goal,
在多智能体路由移交时优先级最高"""
runtime_config: BaseRuntimeConfig
"""运行时配置,如是否无状态、UI输出模式等"""
def bind(self, **kwargs: Any) -> Any:
"""DI 注入语法糖:返回 Depends,自动绑定当前上下文"""
from nonebot.params import Depends
from zhenxun.services.ai.flow.agent.bridge import AgentRunner
async def _dependency() -> AgentRunner[Any]:
return AgentRunner[Any](self, **kwargs)
return Depends(_dependency)
async def reply(
self,
prompt: PromptInput | None = None,
reply_to: bool = False,
*,
context: RunContext | None = None,
**kwargs: Any,
) -> T_RunResult:
"""交互执行语法糖,自动渲染流式进度并最终将结果回复给终端用户"""
from zhenxun.services.ai.flow.agent.bridge import AgentRunner
runner = AgentRunner(self, context=context, **kwargs)
return cast(T_RunResult, await runner.reply(prompt=prompt, reply_to=reply_to))
async def run(
self,
prompt: PromptInput | None = None,
*,
context: RunContext | None = None,
**kwargs: Any,
) -> T_RunResult:
"""阻塞式核心运行入口,安全捕获内部抛出的静默退出信号"""
from zhenxun.services.ai.core.exceptions import ControlFlowExit
from zhenxun.services.log import logger
try:
async with self.run_stream(
prompt=prompt, context=context, **kwargs
) as stream_result:
return cast(T_RunResult, await stream_result.get_run_result())
except ControlFlowExit as e:
logger.info(f"[{self.name}] 触发底层控制流,已安全退出: {e}")
await UIController.handle_control_flow_exit_display(e, context)
raise asyncio.CancelledError()
@abstractmethod
@contextlib.asynccontextmanager
async def run_stream(
self,
prompt: PromptInput | None = None,
*,
context: RunContext | None = None,
**kwargs: Any,
) -> "AsyncIterator[StreamedRunResult[Any]]":
"""流式运行入口,返回上下文管理器,用于消费底层执行流事件 (StreamedRunResult)"""
yield cast(Any, None)