【Agent】OpenManus-Agent架构详细分析
各组件详细设计见:
- BaseAgent:BaseAgent
- ReActAgent:ReActAgent
- ToolCallAgent:ToolCallAgent
- 具体Agent实现:具体Agent
- Memory数据结构:Memory
1. 智能体层次结构
OpenManus 采用了一个多层次的智能体继承结构,形成了清晰的能力分层:
BaseAgent (抽象基类)↓
ReActAgent (思考-行动循环)↓
ToolCallAgent (工具调用能力)↓
具体智能体实现:- Manus (通用智能体)- PlanningAgent (规划智能体)- SWEAgent (软件工程智能体)
2. 核心组件设计
2.1 BaseAgent (基础代理)
设计特点:
- 使用 Pydantic 支持数据验证和序列化
- 实现了状态管理、内存管理和执行循环的基础功能
- 提供了上下文管理器
state_context用于安全的状态转换 - 实现了
run方法作为主要执行入口 - 定义了
step抽象方法,要求子类实现 - 包含循环检测和处理机制
关键属性:
name: 智能体名称description: 智能体描述system_prompt: 系统级指令提示next_step_prompt: 下一步行动提示llm: 语言模型实例memory: 内存存储state: 当前状态max_steps: 最大步骤数current_step: 当前步骤
调用逻辑:
a. 通过 run 方法启动智能体
b. 使用 state_context 管理状态转换
c. 循环执行 step 方法直到达到终止条件
d. 检测并处理循环状态
e. 返回执行结果
2.2 ReActAgent (思考-行动代理)
设计特点:
- 实现了
ReAct(Reasoning and Acting) 模式 - 将
step方法分解为think和act两个抽象方法 - 提供了思考-行动循环的基本框架
关键方法:
think: 抽象方法,处理当前状态并决定下一步行动act: 抽象方法,执行决定的行动step: 实现了单个思考-行动周期
调用逻辑:
a. step 方法首先调用 think 方法
b. 如果 think 返回 True,则调用 act 方法
c. 返回执行结果
2.3 ToolCallAgent (工具调用代理)
设计特点:
- 扩展了
ReActAgent,专注于工具调用能力 - 实现了与
LLM的工具调用接口集成 - 支持多种工具选择模式:none、auto、required
- 提供了工具执行和结果处理机制
- 支持特殊工具处理(如终止工具)
关键属性:
available_tools: 可用工具集合tool_choices: 工具选择模式special_tool_names: 特殊工具名称列表tool_calls: 当前工具调用列表
关键方法:
-
think: 这个方法的核心是与 LLM 交互,获取其决策,并根据不同的工具选择模式决定下一步操作 -
act: 执行 LLM 决定使用的工具,并处理执行结果-
如果没有工具调用且工具选择模式为 ToolChoice.REQUIRED,则抛出异常
-
如果没有工具调用,返回最后一条消息的内容
-
对每个工具调用,执行 execute_tool 方法并获取结果
-
如果设置了 max_observe,限制结果的长度
-
记录工具执行完成的日志
-
将工具响应添加到内存中
-
返回所有结果的组合字符串
-
-
execute_tool: 执行单个工具调用 -
_handle_special_tool: 处理特殊工具执行
调用逻辑:
a. think 方法向 LLM 发送消息并获取响应
b. 解析响应中的工具调用
c. 将响应添加到内存中
d. act 方法执行工具调用
e. 处理工具执行结果
f. 检查特殊工具并更新状态
2.4 Manus (通用智能体)
设计特点:
- 继承自
ToolCallAgent,是项目的主要智能体 - 配置了多种工具:PythonExecute、WebSearch、BrowserUseTool、FileSaver、Terminate
- 使用特定的系统 prompt 和下一步 prompt
- 重写了特殊工具处理方法,确保浏览器资源清理
关键属性:
max_observe: 限制 tool call的长度max_steps: 设置为 20 步
复写_handle_special_tool():
- 检查工具是否为特殊工具
- 如果是特殊工具,清理浏览器资源
- 调用父类的
_handle_special_tool()方法
2.5 PlanningAgent (规划智能体)
设计特点:
- 继承自
ToolCallAgent,专注于任务规划 - 使用
PlanningTool创建和管理结构化计划 - 跟踪计划步骤的执行状态
- 支持计划创建、更新和执行
额外属性:
active_plan_id: 当前活动计划的 IDstep_execution_tracker: 步骤执行跟踪器current_step_index: 当前步骤索引
复写方法:
-
run-
如果提供了请求,创建初始计划
-
调用父类的
run()方法
-
-
think- 获取当前计划状态并添加到提示中
- 获取当前步骤索引
- 调用父类的
think()方法 - 将工具调用与当前步骤关联以进行跟踪
-
act:- 调用父类的
act()方法执行工具 - 更新工具执行状态为已完成
- 如果是非规划、非特殊工具,更新计划状态
- 调用父类的
额外实现方法
-
get_plan: 获取当前计划 -
update_plan_status: 更新计划状态 -
_get_current_step_index(): 解析当前计划以识别第一个未完成步骤的索引 -
create_initial_plan: 创建初始计划
调用逻辑:
- 初始化时创建计划 ID 并验证工具
- 首次运行时创建初始计划
- 执行计划步骤并更新状态
- 跟踪计划进度直到完成
2.6 SWEAgent (软件工程智能体)
设计特点:
- 继承自 ToolCallAgent,专注于软件工程任务
- 配置了 Bash、StrReplaceEditor 和 Terminate 工具
- 跟踪工作目录状态
关键属性:
max_step: 30
额外属性:
bash: Bash 工具实例working_dir: 当前工作目录
复写 think:
- 更新当前工作目录
- 使用当前工作目录格式化
next_step_prompt - 调用父类的
think()方法
3. 智能体调用流程
3.1 初始化流程
-
智能体创建:
agent = Manus() # 或其他具体智能体 -
初始化验证:
- 通过 Pydantic 的
model_validator进行初始化验证 - 设置默认 LLM 和内存实例
- 验证必要的工具和配置
- 通过 Pydantic 的
3.2 执行流程
-
启动执行:
result = await agent.run(prompt) -
状态管理:
- 使用
state_context将状态设置为RUNNING - 执行完成后恢复状态或设置为
FINISHED
- 使用
-
执行循环:
while current_step < max_steps and state != FINISHED:current_step += 1step_result = await step()check_for_stuck_state() -
思考-行动循环:
async def step():should_act = await think()if should_act:return await act() -
工具调用流程:
async def think():response = await llm.ask_tool(messages, tools, tool_choice)parse_tool_calls(response)add_to_memory(response)async def act():for command in tool_calls:result = await execute_tool(command)add_to_memory(result) -
特殊工具处理:
if tool_name in special_tool_names:if should_finish_execution():state = FINISHED
3.3 内存管理
-
消息添加:
agent.update_memory("user", "用户输入") agent.update_memory("assistant", "助手响应") agent.update_memory("tool", "工具结果", tool_call_id="工具ID") -
消息访问:
messages = agent.messages # 获取所有消息
3.4 工具集成
-
工具注册:
available_tools = ToolCollection(PythonExecute(), WebSearch(), BrowserUseTool(), FileSaver(), Terminate() ) -
工具执行:
result = await available_tools.execute(name="tool_name", tool_input=args)
4. 设计模式应用
4.1 模板方法模式
- BaseAgent 定义了算法骨架 (run)
- 子类实现特定步骤 (step, think, act)
4.2 策略模式
- 不同的智能体实现不同的策略
- 通过继承和多态实现策略选择
4.3 组合模式
- ToolCollection 管理多个工具
- 提供统一的接口执行工具
4.4 观察者模式
- 状态变化和事件处理
- 工具执行结果通知
4.5 命令模式
- 工具调用封装为命令对象
- 支持命令执行和结果处理
5. 扩展性设计
5.1 智能体扩展
- 可以通过继承 BaseAgent 或其子类创建新的智能体
- 只需实现必要的抽象方法
5.2 工具扩展
- 通过 ToolCollection 可以灵活添加新工具
- 智能体可以动态配置可用工具
5.3 提示词扩展
- 系统提示和下一步提示可以自定义
- 支持特定领域的提示词模板
6. 错误处理机制
6.1 异常捕获
- 在
think和act方法中捕获异常 - 记录错误并添加到内存中
6.2 状态恢复
- 使用
state_context确保状态正确恢复 - 异常时设置为 ERROR 状态
6.3 循环检测
- 实现了
is_stuck方法检测重复响应 - 通过
handle_stuck_state添加提示改变策略
7. 性能考虑
7.1 异步设计
- 所有关键方法都使用
async/await实现 - 支持非阻塞 I/O 操作
7.2 资源管理
- 特殊工具处理确保资源清理
- 浏览器工具在终止时自动清理
7.3 步骤限制
- 通过
max_steps限制执行步骤 - 防止无限循环和资源耗尽
相关文章:
【Agent】OpenManus-Agent架构详细分析
各组件详细设计见: BaseAgent:BaseAgentReActAgent:ReActAgentToolCallAgent:ToolCallAgent具体Agent实现:具体AgentMemory数据结构:Memory 1. 智能体层次结构 OpenManus 采用了一个多层次的智能体继承结…...
股指期货有卖不出去的时候吗?
在股指期货的交易世界里,很多人都有这样的疑问:股指期货会不会有卖不出去的时候呢?答案是会的,下面咱们就来详细唠唠为啥会出现这种情况。 市场极端行情下难以卖出 1.跌停限制:股指期货和股票一样,也有涨…...
前端Html5 Canvas面试题及参考答案
目录 Canvas 元素的默认尺寸是多少?如何正确设置其宽高以避免图像拉伸? 如何获取 Canvas 的 2D 上下文对象?3D 上下文支持哪些技术? canvas.width 与 canvas.style.width 的区别是什么? Canvas 支持的图像格式有哪些?如何将 Canvas 转换为 Base64 图片? Canvas 中如…...
【ES6】03-Set + Map
本文介绍两种集合 set map 的操作和方法。 目录 1. Set 1.1 set基本使用 1.2 add 1.3 delete 1.4 has 1.5 size 1.6 set转换为数组 1.7 拓展运算符 1.8 for...of 1.9 forEach 1.10 set给数组去重 2. Map 2.1 创建map集合 2.2 set添加元素 2.3 delete删除元素 …...
Java缓存String(字符串常量池)、Integer (-128 到 127 )
对问题的解释 1. “字符串常量池存储的是string对象的直接引用,而不是直接存放的对象,是一张string table” 的含义 这句话可以从以下几个方面理解: (1) 字符串常量池的存储内容 直接引用:字符串常量池中存储的是指向实际 Stri…...
消息队列的特性与使用场景:Kafka、ActiveMQ、RabbitMQ与RocketMQ的深度剖析
在分布式系统和微服务架构中,消息队列是实现服务间通信和解耦的核心组件。Kafka、ActiveMQ、RabbitMQ和RocketMQ是当前最受欢迎的消息队列解决方案,它们各自具有独特的特性和适用场景。本文将从特性和使用场景两个维度进行对比分析,帮助读者更…...
开发、科研、日常办公工具汇总(自用,持续更新)
主要记录汇总一下自己平常会用到的网站工具,方便查阅。 update:2025/2/11(开发网站补一下) update:2025/2/21(补充一些AI工具,刚好在做AI视频相关工作) update:2025/3/7&…...
解决VueI18n使用浏览器插件翻译后,切换国际化失效的问题
问题复现 在使用Vue-i18n对页面进行国际化的时候,使用浏览器翻译插件(如腾讯翻译)后,切换国际化语言,随后当我们关闭浏览器翻译插件后,再次切换国际化语言,原来被翻译的文字无法正确切换 出现…...
HTML5 drag API实现列表拖拽排序
拖拽API(Drag and Drop API)是HTML5提供的一组功能,使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能,用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart࿱…...
改变一生的思维模型【11】升维
升维思维模型:突破认知局限的破局法则 一、定义与核心逻辑 升维思维是通过增加分析维度,将问题投射到更高认知层次寻找解决方案的思考方式。其本质是跳出原有竞争维度,在更广阔的空间重构游戏规则。核心逻辑在于:当低维战场陷入…...
【动手学深度学习】#2线性神经网络
主要参考学习资料: 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 2.1 线性回归2.1.1 线性回归的基本元素线性模型损失函数解析解随机梯度下降 2.1.3 最大似然估计 2.2 线性回归从零开始实现2.2.1 生成数据集2.2.2 读取数…...
计算机网络——NAT
一、什么是NAT? NAT(Network Address Translation,网络地址转换) 是一种将 私有IP地址 与 公有IP地址 相互映射的技术,主要用于解决IPv4地址不足的问题。它像一名“翻译官”,在数据包经过路由器或防火墙时…...
Stable Deffusion--常见模型插件详解
1.Checkpoint大模型 Checkpoint 是生成图像的基础模型,决定了整体画风如动漫、写实、机甲等。它是必选项,所有图像生成必须基于一个主模型。文件体积较大通常 1.5GB 以上,格式为 .ckpt 或 .safetensors。 存放位置为:\models\Sta…...
防重复提交详解:从前端Vue到后端Java的全面解决方案
防重复提交详解:从前端Vue到后端Java的全面解决方案 一、重复提交问题概述 在Web应用开发中,表单重复提交是一个常见问题,可能导致: 数据库中出现重复记录重复执行业务逻辑(如多次扣款)系统资源浪费用户…...
同一子网通信
添加交换机后的通信流程 1. 同一子网内(使用交换机) 判断是否在同一子网: 主机A通过子网掩码判断主机B的IP地址是否属于同一子网。若在同一子网,主机A需要通过ARP获取主机B的MAC地址。 ARP请求(广播)&…...
快速迭代:利用 nodemon 和其他工具实现 Express.js 热更新
在开发 Express.js 应用时,热更新(Hot Reloading)可以显著提升开发效率,因为它允许你在修改代码后立即看到效果,而无需手动重启服务器。以下是几种实现热更新的方法和工具,帮助你在开发过程中更高效地工作。…...
BUG日志:Maven项目启动报错(文件名或者文件扩展名过长)
Bug日志编号:[Maven-001] 标题:Windows系统下Maven项目因路径过长导致命令行执行失败 1. 问题描述 现象:执行mvn clean install时报错: The input line is too long 或 The filename or extension is too long触发条件…...
IntelliJ IDEA 快捷键系列:重命名快捷键详解
目录 引言一、默认重命名快捷键1. Windows 系统2. Mac 系统 二、操作步骤与技巧1. 精准选择重命名范围2. 智能过滤无关内容 三、总结 引言 在代码重构中,重命名变量、类、方法 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 Ma…...
零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]
一、为什么需要分布式ID? 🤔 在单机系统中,使用数据库自增ID就能满足需求。但在分布式系统中,多个服务节点同时生成ID时会出现以下问题: ID冲突:不同节点生成相同ID 扩展困难:数据库自增ID无法…...
使用python反射,实现pytest读取yaml并发送请求
pytest yaml yaml - feature: 用户模块story: 登录title: 添加用户request:method: POSTurl: /system/user/listheaders: nullparams: nullvalidate: nullread_yaml_all def read_yaml_all(path):with open(path, r, encodingutf-8) as f:value yaml.safe_load(f)return v…...
点灯、点各式各样的灯
鱼离水则身枯,心离书则神索。 前言闪灯呼吸灯流水灯二进制数显示灯蜂鸣器节拍流水音乐会总结 前言 上回书咱们简单了解了一点有关特殊功能寄存器sfr、通用输入输出GPIO、位操作运算符sbit和一个不靠单片机上的晶振(拿来定时的)的依托于单片机CPU空操作的ms级延时函…...
Matlab 汽车悬架系统动力学建模与仿真
1、内容简介 略 Matlab 170-汽车悬架系统动力学建模与仿真 可以交流、咨询、答疑 2、内容说明 略 本文对题目给定的1/2汽车四自由度模型,建立状态空间模型进行系统分析,并通过MATLAB仿真对系统进行稳定性、可控可观测性分析,对得的结果进行…...
专访数势科技谭李:智能分析 Agent 打通数据平权的最后一公里
作者|斗斗 编辑|皮爷 出品|产业家 伦敦塔桥下的泰晤士河底,埋藏着工业革命的隐秘图腾——布鲁内尔设计的隧道盾构机。在19世纪城市地下轨道建设的过程中,这个直径11米的钢铁巨兽没有选择拓宽河道,而是开创了地下通行的新维度。 “我们不…...
了解浏览器
本文来自腾讯元宝 Chrome浏览器(Google Chrome)是由Google开发的一款免费网页浏览器,自2008年发布以来凭借其高效、安全、简洁的特点成为全球市场份额最高的浏览器。以下是其核心信息及最新动态的综合分析: 一、核心优势与技术特点…...
2、操作系统之软件基础
一、硬件支持系统 ,系统管理硬件 操作系统核心功能可以分为: 守护者:对硬件和软件资源的管理协调者:通过机制,将各种各样的硬件资源适配给软件使用。 所以为了更好的管理硬件,操作系统引进了软件。其中3大…...
STC89C52单片机学习——第20节: [8-2]串口向电脑发送数据电脑通过串口控制LED
写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.03.15 51单片机学习——第20节: [8-2]串口向电脑发送数据&电脑通过串口控制LED 前言…...
K8S下nodelocaldns crash问题导致域名请求响应缓慢
前言 最近做项目,有业务出现偶发的部署导致响应很慢的情况,据了解,业务使用域名访问,相同的nginx代理,唯一的区别就是K8S重新部署了。那么问题大概率出现在容器平台,毕竟业务是重启几次正常,偶…...
CVPR2024 | TT3D | 物理世界中可迁移目标性 3D 对抗攻击
Towards Transferable Targeted 3D Adversarial Attack in the Physical World 速览总结摘要-Abstract引言-Introduction相关工作-Related Work方法-MethodologyPreliminray-预备知识问题表述-Problem FormulationNeRF参数空间中的双重优化-Dual Optimization in NeRF Paramete…...
全面对比分析:HDMI、DP、DVI、VGA、Type-C、SDI视频接口特点详解
在当今的多媒体时代,视频接口的选择对于设备连接和显示效果至关重要。不同的视频接口在传输质量、兼容性、带宽等方面各有优劣。本文将全面对比分析常用的视频接口HDMI、DP、DVI、VGA、Type-C、SDI,帮助读者更好地理解它们的特点和适用场景。 一、HDMI&…...
传输层自学
传输实体:完成传输层任务的硬件或软件 可能位于: 操作系统内核独立的用户进程绑定在网络应用中的链接库网络接口卡 1.功能: 网络层与传输层作用范围比较? 网络层负责把数据从源机送达到目的机 传输层负责把数据送达到具体的应…...
