
手把手带你理解OpenManus
我之前演示过几个OpenManus的demo,其实也就是demo,包括manus,现在也就是demo阶段,复杂的plan和flow,现在的代码支撑和LLM的能力都有待改善,但是我们这期不是吐槽文章,是来把OpenManus给打开看看它的实现是怎么样的,其实Manus也都差不多,甚至OWL也都差不多,我们看一个就够了。
其他的几个目录也没啥特别需要看的,就看app。
app里面有这么几个结构:
1- agent 没啥好解释的
2- flow 就是来做multiagent的planning和管理任务框架的。
3- prompt
都是这种形式,来定义系统提示词和agent的role。
4- tool
纯纯干活的了。
主要看最重要的目录agent。
大概总体分这么几个agent。
先看base:base.py 模块定义了抽象基类 BaseAgent,用于管理代理的状态、内存、执行循环(包括运行、步骤执行、卡住处理)和消息,并提供初始化和配置功能,为构建具有特定行为的代理提供基础框架。
在看planning:planning.py模块定义了PlanningAgent类,该代理通过PlanningTool和Terminate等工具创建、管理和执行任务计划。它具有初始化、计划创建(create_initial_plan)、思考(think)、行动(act)、计划状态更新(update_plan_status)、步骤跟踪(step_execution_tracker)等功能,并能根据工具执行结果动态调整计划,处理初始请求(run)并检索当前计划状态(get_plan)。
然后是 react.py:react.py模块定义了继承自BaseAgent的抽象类ReActAgent,它通过think(思考,决定下一步行动) 和act(执行行动) 两个抽象方法(需子类实现)以及step方法(整合think和act)来处理和执行任务,并提供基础的任务处理框架。
swe和tool就是 指从code和tool了
manus.py:manus.py模块定义了Manus类,一个继承自ToolCallAgent(实际上你前面提到了继承自 PlanningAgent, 请确认是哪个) 的通用智能代理。Manus具有预定义的名称、描述、系统提示、步骤限制(max_observe,max_steps),并利用包含PythonExecute、WebSearch、BrowserUseTool、FileSaver和Terminate等工具的available_tools集合来执行各种任务,并通过_handle_special_tool方法处理(如清理)BrowserUseTool的结果。
好的,我们来梳理一下这些代码的调用逻辑。这里涉及到多个Agent类(BaseAgent,ReActAgent,ToolCallAgent,PlanningAgent,SWEAgent,Manus),以及它们之间的继承关系和方法调用。我用文字描述,并结合伪代码(因为好解释)来表示调用流程。
1. 总体继承关系:
2.BaseAgent(核心基类):
- 核心方法:
__init__: 初始化Agent的基本属性(name, description, llm, memory, state, max_steps等)。
initialize_agent: 使用model_validator在对象创建后进行进一步初始化(设置默认的LLM和Memory)。
state_context: 一个异步上下文管理器,用于安全地更改Agent的状态(IDLE, RUNNING, ERROR等)。
update_memory: 将消息添加到Agent的内存中。
run: Agent的主执行循环。它会循环调用step()方法,直到达到max_steps或状态变为FINISHED。
step:抽象方法,必须由子类实现。执行Agent的单个步骤。
is_stuck: 检查智能体是否卡住。
handle_stuck_state: 处理卡住的状态。
messages: 属性,用于获取和设置消息。
- 调用流程 (以run方法为例):
3.ReActAgent(ReAct模式的基类):
- 继承自:BaseAgent
- 核心方法:
think:抽象方法,由子类实现。思考下一步行动。
act:抽象方法,由子类实现。执行行动。
step: 实现了BaseAgent的step方法。依次调用think()和act()。
- 调用流程 (以step方法为例):
4.ToolCallAgent(支持工具调用的Agent):
- 继承自:ReActAgent
- 核心方法:
__init__: 初始化工具相关的属性 (available_tools, tool_choices, special_tool_names, tool_calls等)。
think: 根据当前状态和可用工具,决定是否调用工具。使用LLM进行决策。
act: 执行工具调用,并处理工具的输出。
execute_tool: 执行具体的工具调用。
_handle_special_tool: 处理特殊工具。
- 调用流程 (以think和act为例):
5.PlanningAgent(规划型Agent):
- 继承自:ToolCallAgent
- 核心方法:
- initialize_plan_and_verify_tools: 初始化计划ID并验证是否有PlanningTool。
- think: 获取当前计划状态,并让LLM决定下一步行动(包括是否调用工具)。
- act: 执行工具调用,并更新计划状态。
- get_plan: 获取当前计划。
- create_initial_plan: 根据用户请求创建初始计划。
- update_plan_status: 根据工具执行结果更新计划步骤的状态。
- _get_current_step_index: 获取当前计划中第一个未完成步骤的索引。
- 调用流程 (更详细,以run->think->act为例):
6.SWEAgent(软件工程师Agent):
- 继承自:ToolCallAgent
- 核心方法:
think: 更新工作目录,并使用格式化的next_step_prompt。然后调用父类的think。
- 调用流程 (以think为例):
7.Manus(通用Agent):
- 继承自:ToolCallAgent
- 特点:拥有更广泛的工具集 (PythonExecute, WebSearch, BrowserUseTool, FileSaver, Terminate)。
- _handle_special_tool: 重写此方法,处理BrowserUseTool的清理工作。
那么好,我们总结一下:
- BaseAgent提供了Agent的基本框架和执行循环。
- ReActAgent引入了 "思考-行动" 模式。
- ToolCallAgent增加了工具调用的能力。
- PlanningAgent、SWEAgent和Manus是ToolCallAgent的具体实现,分别针对不同的任务类型。
- 调用逻辑主要通过继承和重写think、act和step方法来实现。
- PlanningAgent具有更复杂的内部状态管理,用于跟踪计划的执行。
画出来就是下图这样:
总体调用的抽象感觉就是下图这样:
好了今天这节课就解释到这,大家可以结合我的解释自己去run一下代码,甚至自己按着这个逻辑来新写一套multi-agents的框架也不是特别难的事。
本文转载自熵减AI,作者:周博洋
