在近期,我畅想,希望能够开发一款真正通用型agent,但是由于没有充分的开发时间以及这个agent开发起来是有一定难度的,我现在先把我整理的有关这个agent的架构设计写在本篇博客中,以待后续开发。
MindHub 工程化实现方案
一、项目文件结构
MindHub 项目采用模块化设计,文件结构如下:
1 | MindHub/ |
二、核心组件及逻辑
-
DirectorCore (指挥核心)
-
职责:
- 接收来自 API Gateway 的用户请求。
- 将用户问题转换为内部任务表示,例如 MindTask 对象。
- 生成和维护任务图(Task Graph),表示任务之间的依赖关系。
- 在每次迭代中,评估是否需要更新任务图,以适应任务执行过程中的变化。
- 计算任务优先级,决定任务的执行顺序。
- 选择合适的 Agent (ExpertAgent、CriticAgent、ExecutorAgent、BrowserAgent),根据任务的类型和需求选择合适的 Agent。
- 维护所有任务和子任务的完整变量信息,包括变量名、变量值等。
- 通过 NetProtocol 向 AgentNode 的子角色发送任务请求 (TaskRequest, 内含需要用到的变量) 。
- 接收来自 AgentNode 子角色的任务执行结果 (TaskResult, 内含新生成的变量)。
- 与 MindStorage 交互, 存储和读取变量,实现变量的持久化存储和共享。
- 监控任务执行状态,例如任务是否完成、是否出错等。
- 调用 LLM 服务, 进行任务分解、策略制定、任务图生成与更新等。
- 管理快照,支持回滚到之前的状态,提供系统的容错能力。
-
关键模块:
director_core.py
: 实现 DirectorCore 的核心逻辑,包括任务调度、Agent 选择、优先级计算、变量管理、任务图生成与更新、快照管理和回滚等。task_graph.py
: 管理任务之间的依赖关系,形成任务图。提供任务图的创建、更新、查询等功能。包含 TaskOrchestrator,用于协调任务的执行。priority_engine.py
: 根据任务的属性和上下文计算任务的优先级。
-
-
AgentNode (智能体节点)
-
职责:
- 接收来自 DirectorCore 的任务请求和变量。
- 根据任务类型, 实例化相应的 Agent 子角色 (ExpertAgent、CriticAgent、ExecutorAgent、BrowserAgent)。
- Agent 子角色:
- 根据任务描述和提供的变量, 调用 LLM 服务或浏览器交互工具生成响应。
- 使用 NeuroParser 解析 LLM 的响应, 提取结构化数据 (非 BrowserAgent)。
- 将解析后的结果 (包括新生成的变量) 通过 NetProtocol (TaskResult 消息) 发送回 DirectorCore。
- 与 MindStorage 交互, 读取输入变量, 存储新生成的变量。
- AgentNode 本身不存储变量, 变量由其子角色在执行任务时使用, 并将结果返回给 DirectorCore。
-
关键模块:
agent_node.py
: 实现 AgentNode 的核心逻辑,包括 Agent 执行、与 LLM/浏览器交互工具交互、结果存储等。expert_agent.py
: 专业 Agent,用于处理特定领域的任务,使用configs/agent/prompts/expert_agent_prompt.txt
中的提示词模板。critic_agent.py
: 评论 Agent,用于评估其他 Agent 的结果,使用configs/agent/prompts/critic_agent_prompt.txt
中的提示词模板。executor_agent.py
: 执行 Agent,用于执行具体的操作,使用configs/agent/prompts/executor_agent_prompt.txt
中的提示词模板。browser_agent.py
: Browser Agent,用于处理需要与 Web 浏览器交互的任务,例如网页信息检索、数据抓取、Web 应用自动化等。使用configs/agent/prompts/browser_agent_prompt.txt
中的提示词模板。thought_template.py
: 定义 Agent 的思维模板,指导 Agent 的思考过程。neuro_parser.py
: 解析 LLM 的响应,提取关键信息 (非 BrowserAgent)。
-
-
NetProtocol (网络协议)
-
职责:
- 提供 DirectorCore 和 AgentNode 之间可靠的消息传递机制。
- 消息的序列化和反序列化 (使用 Avro)。
- 消息路由和传递 (通过 MessageBroker)。
- 消息中包含变量 (变量名, 实际数据存储在 MindStorage 中)。
-
关键模块:
message_broker.py
: 实现消息代理的抽象接口,支持多种消息队列 (例如 Redis [可选]、RabbitMQ、Kafka)。serializer.py
: 定义消息序列化器的基类。schema_registry.py
: 管理消息的 Avro schemas。avro_serializer.py
: 实现 Avro 序列化器。
-
-
MindStorage (思维存储)
-
职责:
- 存储所有任务和子任务的变量。
- 自动生成变量名。
- 提供变量的读取、写入和更新接口。
- 支持不同的存储后端 (例如内存存储、Redis)。
- 变量的实际内容以字符串形式存储, 并可与提示词结合使用。
-
关键模块:
mind_storage.py
: 实现 MindStorage 的核心逻辑,包括数据存储、发布/订阅、数据访问等。in_memory_storage.py
: 实现内存存储。interface.py
: 定义 MindStorage 的数据访问接口。models.py
: 定义存储的数据模型。
-
-
LLMGateway (LLM 网关)
-
职责:
- 提供与 LLM 服务交互的统一接口。
- 支持多种 LLM 服务 (例如 OpenAI、Hugging Face)。
- 处理 LLM 请求和响应。
- 支持自定义 LLM 模型。
-
关键模块:
llm_gateway.py
: 实现 LLM 网关的核心逻辑。openai_gateway.py
: 实现 OpenAI 接口规范的适配器 (可选)。huggingface_gateway.py
: 实现 Hugging Face 接口规范的适配器 (可选)。
-
-
MindMonitor (思维监视器)
-
职责:
- 提供思维链追踪可视化。
- 监控系统资源使用情况 (CPU、内存、网络等)。
- 监控系统性能指标 (任务处理时间、吞吐量等)。
- 记录和展示错误日志。
- 监控任务执行过程。
- 收集和展示任务状态、变量变化等信息。
- 提供任务图的可视化界面,实时显示任务图的结构、任务状态、任务之间的依赖关系等信息。
- 监控 DirectorCore 和 AgentNode 的运行状态。
-
关键模块:
mind_monitor.py
: 实现监控核心逻辑,包括数据收集、指标计算、可视化等。metrics.py
: 定义监控指标,例如任务执行时间、成功率、资源利用率等。visualizer.py
: 实现可视化工具,例如思维链追踪图、性能图表、任务图等。
-
三、DirectorCore 与 AgentNode 通信机制
MindHub 采用基于消息队列的通信机制, 通过 NetProtocol 实现 DirectorCore 和 AgentNode 之间的解耦和异步通信。
-
消息格式:
- NetProtocol 使用 Avro 作为消息的序列化格式。消息的 Schema 在
common/schemas.py
中定义, 并通过schema_registry.py
进行管理。 - 消息包含以下字段:
message_id
: 消息的唯一标识符。sender
: 消息发送者 (DirectorCore 或 AgentNode-ExpertAgent/CriticAgent/ExecutorAgent/BrowserAgent)。receiver
: 消息接收者 (DirectorCore 或 AgentNode-ExpertAgent/CriticAgent/ExecutorAgent/BrowserAgent)。message_type
: 消息类型 (例如 TaskRequest、TaskResult)。payload
: 消息负载, 根据消息类型的不同而不同。
- 常见的消息类型包括:
TaskRequest
: DirectorCore 向 AgentNode 子角色发送的任务请求。包含任务描述、Agent 类型和需要用到的变量(变量名, 实际数据在 MindStorage)。TaskResult
: AgentNode 子角色向 DirectorCore 发送的任务结果。包含新生成的变量 (变量名, 实际数据在 MindStorage)。
- NetProtocol 使用 Avro 作为消息的序列化格式。消息的 Schema 在
-
消息处理流程:
- DirectorCore 将用户问题转换为 MindTask, 并生成初始变量存储在 MindStorage。DirectorCore 调用 LLM 生成初始任务图。
- DirectorCore 根据任务图, 决定下一个要执行的任务, 并选择合适的 Agent (ExpertAgent、CriticAgent、ExecutorAgent 或 BrowserAgent)。DirectorCore 在每次迭代中评估是否需要更新任务图。
- DirectorCore 从 MindStorage 读取相关变量, 并将任务描述、Agent 类型、变量列表打包成 TaskRequest 消息, 通过 NetProtocol 发送给 AgentNode。
- AgentNode 接收到 TaskRequest 消息, 根据 Agent 类型实例化相应的 Agent 子角色 (ExpertAgent、CriticAgent、ExecutorAgent 或 BrowserAgent)。
- Agent 子角色:
- ExpertAgent、CriticAgent 或 ExecutorAgent 从 MindStorage 读取变量, 并结合自身的提示词模板 (
expert_agent_prompt.txt
、critic_agent_prompt.txt
或executor_agent_prompt.txt
), 向 LLM 服务发送请求。 - BrowserAgent 从 MindStorage 读取变量, 并结合自身的提示词模板 (
browser_agent_prompt.txt
), 调用浏览器交互工具执行相应的浏览器操作。
- ExpertAgent、CriticAgent 或 ExecutorAgent 从 MindStorage 读取变量, 并结合自身的提示词模板 (
- Agent 子角色:
- ExpertAgent、CriticAgent 或 ExecutorAgent 接收到 LLM 响应后, 使用 NeuroParser 解析响应, 提取结构化数据和新生成的变量, 并存储到 MindStorage。
- BrowserAgent 将浏览器交互工具的执行结果存储到 MindStorage。
- AgentNode 将新生成的变量打包成 TaskResult 消息, 通过 NetProtocol 发送给 DirectorCore。
- DirectorCore 接收到 TaskResult 消息, 更新任务状态, 并将新生成的变量存储到 MindStorage。
- 重复步骤 2-8, 直到任务图中所有任务完成。
四、配置文件详解
-
configs/director/config.yaml
(DirectorCore 通用配置)- 用途: 存放 DirectorCore 的通用配置项,例如 NetProtocol 相关配置。
- 示例配置项:
netprotocol
:message_broker
: 消息代理类型 (例如 redis)。broker_address
: 消息代理地址。serializer_type
: 序列化器类型 (例如 avro)。
-
configs/director/prompts/
(DirectorCore 提示词模板)- 用途: 存放 DirectorCore 使用的提示词模板。
- 示例文件:
task_decomposition.txt
: 任务分解提示词,用于将用户问题分解成更小的子任务。agent_selection.txt
: Agent 选择提示词,用于指导 DirectorCore 选择合适的 Agent 来执行任务。task_graph_generation.txt
: 任务图生成提示词,用于指导 DirectorCore 生成初始任务图。task_graph_update.txt
: 任务图更新提示词,用于指导 DirectorCore 在任务执行过程中更新任务图。
-
configs/director/llm_settings.yaml
(DirectorCore LLM 输出约束)- 用途: 定义用于约束 DirectorCore 中 LLM 输出的正则表达式。
- 示例配置项:
output_regex
:task_decomposition
: [正则表达式],用于约束任务分解的 LLM 输出。agent_selection
: [正则表达式],用于约束 Agent 选择的 LLM 输出。task_graph_generation
: [正则表达式],用于约束任务图生成的 LLM 输出。task_graph_update
: [正则表达式],用于约束任务图更新的 LLM 输出。
-
configs/agent/config.yaml
(AgentNode 通用配置)- 用途: 存放 AgentNode 的通用配置项,例如 NetProtocol 相关配置。
- 示例配置项:
netprotocol
:message_broker
: 消息代理类型 (例如 redis)。broker_address
: 消息代理地址。serializer_type
: 序列化器类型 (例如 avro)。
-
configs/agent/prompts/
(AgentNode 提示词模板)- 用途: 存放 AgentNode 中各 Agent 子角色使用的提示词模板。
- 示例文件:
expert_agent_prompt.txt
: ExpertAgent 提示词,用于指导 ExpertAgent 处理特定领域的任务。critic_agent_prompt.txt
: CriticAgent 提示词,用于指导 CriticAgent 评估其他 Agent 的结果。executor_agent_prompt.txt
: ExecutorAgent 提示词,用于指导 ExecutorAgent 执行具体的操作。browser_agent_prompt.txt
: BrowserAgent 提示词,用于指导 BrowserAgent 执行浏览器操作。
-
configs/agent/llm_settings.yaml
(AgentNode LLM 输出约束)- 用途: 定义用于约束 AgentNode 中 LLM 输出的正则表达式。
- 示例配置项:
output_regex
:expert_agent
: [正则表达式],用于约束 ExpertAgent 的 LLM 输出。critic_agent
: [正则表达式],用于约束 CriticAgent 的 LLM 输出。executor_agent
: [正则表达式],用于约束 ExecutorAgent 的 LLM 输出。- (BrowserAgent 不需要 LLM,此配置可忽略)
-
configs/llm_gateway_config.yaml
(全局 LLM Gateway 配置)- 用途: 配置 LLM 提供商、模型名称、API 密钥等,并可以针对 DirectorCore 和 AgentNode 分别配置。
- 配置优先级:
- 优先读取
director
或agent
部分的配置(如果存在)。 - 如果
director
或agent
部分未配置特定项,则使用default
部分的全局默认配置。
- 优先读取
- 示例配置项:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 全局默认配置
default:
provider: openai
model_name: gpt-3.5-turbo
api_key: YOUR_API_KEY
# DirectorCore 特定配置(可选)
director:
provider: huggingface # 覆盖全局默认配置
model_name: ...
api_key: ...
# AgentNode 特定配置(可选)
agent:
provider: ...
model_name: ...
api_key: ... -
configs/storage_config.yaml
(MindStorage 配置)- 用途: 配置 MindStorage 的行为,例如存储类型、连接参数等。
- 示例配置项:
storage_type
: 存储类型 (例如 in-memory)。redis
: # Redis 存储配置 (如果 storage_type 为 redis)host
: Redis 服务器地址。port
: Redis 服务器端口。db
: Redis 数据库编号。
-
configs/permissions.yaml
(权限控制矩阵)- 用途: 定义角色和权限,控制 DirectorCore 和 AgentNode 内部不同角色 (例如 ExpertAgent、CriticAgent、ExecutorAgent、BrowserAgent) 之间的访问权限。
- 示例配置项:
roles
: 定义角色,例如 ExpertAgent、CriticAgent、ExecutorAgent、BrowserAgent。permissions
: 定义每个角色的权限,例如mindstorage:read
、mindstorage:write
、llm:query
、browser:control
,其中browser:control
权限控制 BrowserAgent 的浏览器操作权限。matrix
: 定义角色和权限的对应关系,例如:1
2
3
4
5
6
7
8matrix:
expert_agent:
- mindstorage:read
- llm:query
browser_agent:
- mindstorage:read
- mindstorage:write
- browser:control
五、核心工作流程及架构图
graph TD A[用户终端] --> B{API Gateway} B -->|NetProtocol| C[DirectorCore] C -->|TaskRequest| D[AgentNode-Expert/Critic/Executor] C -->|TaskRequest| H[AgentNode-BrowserAgent] D -->|TaskResult| C H -->|TaskResult| C C <-->|读写变量| E[MindStorage] D <-->|读写变量| E[MindStorage] H <-->|读写变量| E[MindStorage] D -->|请求| F[LLM服务] H -->|请求| I[浏览器交互工具] I -->|控制| J[浏览器] C -->|请求| F[LLM服务] C -->|监控数据| G[MindMonitor] D -->|监控数据| G[MindMonitor] H -->|监控数据| G[MindMonitor] G <-->|任务图| C
-
任务提交:
sequenceDiagram User->>API_Gateway: 提交问题 API_Gateway->>DirectorCore: 生成MindTask DirectorCore->>MindStorage: 存储初始变量 DirectorCore->>LLM服务: 请求生成初始任务图 LLM服务->>DirectorCore: 返回初始任务图 DirectorCore->>MindMonitor: 更新任务图
-
任务调度与 Agent 选择:
DirectorCore 根据任务图依赖关系、优先级和任务类型,选择合适的 Agent(包括BrowserAgent
),并将任务、Agent 类型和相关变量分发给 AgentNode。Agent 选择过程可以由 LLM 驱动,也可以使用启发式规则。 -
任务执行:
sequenceDiagram DirectorCore->>AgentNode-Expert/Critic/Executor: TaskRequest(含任务描述、Agent类型、变量) AgentNode-Expert/Critic/Executor->>LLM服务: 发送渲染后的提示词(含变量) LLM服务->>AgentNode-Expert/Critic/Executor: 返回原始响应 AgentNode-Expert/Critic/Executor->>NeuroParser: 解析结构化数据 AgentNode-Expert/Critic/Executor->>MindStorage: 存储处理结果(含新变量) AgentNode-Expert/Critic/Executor->>DirectorCore: TaskResult(含新变量)
DirectorCore->>AgentNode-BrowserAgent: TaskRequest(含任务描述、Agent类型、变量) AgentNode-BrowserAgent->>浏览器交互工具: 调用API执行浏览器操作 浏览器交互工具->>AgentNode-BrowserAgent: 返回操作结果 AgentNode-BrowserAgent->>MindStorage: 存储处理结果(含新变量) AgentNode-BrowserAgent->>DirectorCore: TaskResult(含新变量)</pre>
-
任务图更新/执行:
sequenceDiagram DirectorCore->>LLM服务: 请求评估是否需要更新任务图 LLM服务->>DirectorCore: 返回评估结果(更新/不更新) alt 需要更新任务图 DirectorCore->>LLM服务: 请求生成新任务图 LLM服务->>DirectorCore: 返回新任务图 DirectorCore->>MindMonitor: 更新任务图 else 不需要更新任务图 DirectorCore->>AgentNode-Expert/Critic/Executor: 继续执行现有任务图中的任务 DirectorCore->>AgentNode-BrowserAgent: 继续执行现有任务图中的任务 end
-
上下文更新:
由于DirectorCore 和 AgentNode是直接引用MindStorage中的变量,因此不需要单独的"上下文更新步骤",DirectorCore可以实时感知变量变化。
六、部署架构
MindHub 初期采用单实例部署架构,简化部署流程。
- DirectorCore: 单个实例运行。
- AgentNode: 单个实例运行。
- MindStorage: 使用内存存储。
- LLM 服务: 根据实际需求选择合适的部署方式。
- 浏览器交互工具: 与 AgentNode 部署在同一实例中。
- API Gateway: 可以使用 Nginx、Kong 或 Envoy 等成熟的 API 网关。
七、安全增强
- 权限控制:
- 通过
configs/permissions.yaml
文件定义角色和权限,控制 DirectorCore 与 AgentNode 内部不同角色之间的访问权限。 - 特别注意限制
BrowserAgent
的权限, 例如禁止访问特定域名、限制可执行的浏览器操作等。
- 通过
- 安全沙箱 (可选):
- 考虑使用安全沙箱隔离
BrowserAgent
,防止其访问系统敏感资源。可以使用 Docker 容器或其他虚拟化技术。
- 考虑使用安全沙箱隔离
- 输入验证:
- 对用户输入进行严格的验证,防止恶意代码注入,特别是用于
BrowserAgent
的任务描述。
- 对用户输入进行严格的验证,防止恶意代码注入,特别是用于
- 访问控制:
- 限制 DirectorCore 和 AgentNode 对 MindStorage 的访问权限,只允许必要的读写操作。
- 数据加密:
- 对 MindStorage 中存储的敏感数据进行加密。
- 日志审计:
- 记录所有操作日志,方便问题排查和安全审计。
八、可选功能
-
上下文压缩 (Context Compressor):
- 目的: 减少 LLM 的输入长度,提高效率和降低成本。
- 实现: 在 DirectorCore 中,使用上下文压缩算法 (例如 TextRank、LSA) 对任务上下文进行压缩。
- 配置: 通过
configs/director/config.yaml
中的context_compressor
参数进行配置。 - 算法选择: 可以选择不同的上下文压缩算法,例如 TextRank、LSA、TF-IDF 等。
- 压缩比例: 可以配置上下文压缩的比例,控制压缩后的上下文长度。
-
Redis 存储 (Redis Storage):
- 目的: 提供持久化存储,支持更大规模的数据和更高的可靠性。
- 实现: 通过
mindstorage/redis_storage.py
实现。 - 配置: 通过
configs/storage_config.yaml
配置storage_type
为redis
,并提供 Redis 连接参数。 - 数据备份: 定期备份 Redis 数据,防止数据丢失。
- 集群部署: 采用 Redis 集群部署,提高系统的可用性和扩展性。
-
快照与回滚:
- 目的: 提供系统容错能力,支持回滚到之前的状态。
- 实现: 在 DirectorCore 中实现快照机制,定期保存任务图、变量和内部状态。当发生错误时,可以选择一个快照进行回滚。
- 配置: 通过
configs/director/config.yaml
中的snapshot
参数进行配置,例如快照频率、存储位置和保留策略。 - 快照存储: 将快照存储到可靠的存储介质中,例如云存储、分布式文件系统等。
- 回滚策略: 定义回滚策略,例如自动回滚、手动回滚等。