乐于分享
好东西不私藏

openmanus调通案例和源码走读

openmanus调通案例和源码走读

背景

OpenManus 是由 MetaGPT 团队开发的一个开源的多功能 AI 助手系统,旨在复刻并优化 Manus 的核心功能。它无需邀请码即可使用,支持本地化部署,能够执行多种复杂任务,如代码生成、文件处理、网络信息检索和网页自动化操作。截止到今天,它的github星标如下,妥妥的一炮走红

安装

遵循官方的教程,我们开始安装, 首先确保你的电脑有conda,如下是在windows下安装的

  • step1:
conda create -n open_manus python=3.12conda activate open_manus
  • step2: 我们将仓库下载到本地,比如这个目录下

然后执行如下命令

cd D:\Work\pywork\openmauns\OpenManus-mainpip install -r requirements.txt

后面就是漫长的等待了。。。。,下载好了之后,我们到

修改一下config.toml文件,改为如下

# Global LLM configuration[llm]model = "moonshot-v1-8k"base_url = "https://api.moonshot.cn/v1"api_key = "sk-SCGEM75yGFGMthlW4qUCHbXWp8zBHsV2fFMoZJvTv0cMs6z9"max_tokens = 4096temperature = 0.0# [llm] #AZURE OPENAI:# api_type= 'azure'# model = "YOUR_MODEL_NAME" #"gpt-4o-mini"# base_url = "{YOUR_AZURE_ENDPOINT.rstrip('/')}/openai/deployments/{AZURE_DEPOLYMENT_ID}"# api_key = "AZURE API KEY"# max_tokens = 8096# temperature = 0.0# api_version="AZURE API VERSION" #"2024-08-01-preview"# Optional configuration for specific LLM models[llm.vision]model = "claude-3-5-sonnet"base_url = "https://api.openai.com/v1"api_key = "sk-..."

我这里用的是kimi的api,你如何申请了记得修改喜爱model base_url api_key这三个参数哦

  • step3:
cd D:\Work\pywork\openmauns\OpenManus-mainpython main.py

会出现如下的界面

我们输入我们要让它做的事

可以看到,上面开始运行了

代码走读

整个框架非常简单,如下所示

主要的就一个main文件以及app文件夹里面的一些脚本,我是小白,先看下main.py,如下

主要我们看下其最后调用的app.run。

该函数位于app/agent目录下,在此目录下的文件还有

  • manus.py
  • planning.py(负责规划)
  • react.py(自我反思是自主智能体)
  • swe.py(SWEAgent是OpenManus项目中的一个组件,主要负责编程相关的任务)
  • base.py(管理agent的抽象类)

我们挨个来看每个py文件

manus.py

classManus(ToolCallAgent):"""    一个多功能通用代理,通过规划来解决各种任务。    该代理扩展了 PlanningAgent,具备一套全面的工具和能力,    包括 Python 执行、网页浏览、文件操作和信息检索,    以处理广泛的用户请求。    """

父类是ToolCallAgent,顾名思义ToolCallAgent就是工具调用的agent,当然,Manus这个类里面还有很多参数,我们有时间继续看

planning,py

classPlanningAgent(ToolCallAgent):"""    一个创建并管理计划以解决任务的代理。    该代理使用规划工具来创建和管理结构化计划,    并通过各个步骤跟踪进度,直到任务完成。    """

父类是ToolCallAgent

react.py

这个类是比较重要的,是一个基于 ReAct(Reasoning and Acting)框架 的代理类。它通过交替进行 思考(Think) 和 行动(Act) 来完成任务。具体来说:

  1. 思考(Think):分析当前状态并决定是否需要采取行动。
  2. 行动(Act):执行具体的行动并返回结果。
classReActAgent(BaseAgent, ABC):"""    一个基于 ReAct(思考-行动)框架的代理。    该代理通过交替进行思考(Think)和行动(Act)来完成任务。    它继承自 BaseAgent 并实现了 ReAct 模式的核心逻辑。    """# 代理的核心属性    name: str  # 代理的唯一名称    description: Optional[str] = None# 代理的简要描述(可选)    system_prompt: Optional[str] = None# 系统级别的提示(可选)    next_step_prompt: Optional[str] = None# 用于决定下一步行动的提示(可选)    llm: Optional[LLM] = Field(default_factory=LLM)  # 语言模型实例    memory: Memory = Field(default_factory=Memory)  # 代理的记忆存储    state: AgentState = AgentState.IDLE  # 代理的当前状态,默认为 IDLE    max_steps: int = 10# 最大执行步骤数    current_step: int = 0# 当前执行步骤    @abstractmethodasyncdefthink(self) -> bool:"""        处理当前状态并决定下一步行动。        返回:            bool: 是否需要执行行动(True 表示需要行动,False 表示不需要)。        """pass    @abstractmethodasyncdefact(self) -> str:"""        执行已决定的行动。        返回:            str: 行动的结果描述。        """passasyncdefstep(self) -> str:"""        执行单一步骤:思考并行动。        返回:            str: 步骤执行的结果描述。        """# 调用 think 方法决定是否需要行动        should_act = await self.think()ifnot should_act:return"Thinking complete - no action needed"# 如果不需要行动,返回提示# 如果需要行动,调用 act 方法并返回结果returnawait self.act()

这个类虽然重要,但是也是很多类的子类

swe.py

SWEAgent 是一个专门用于 代码执行和自然对话 的代理类。它基于 ToolCallAgent,具备与计算机直接交互的能力,能够执行 Bash 命令、编辑文本以及终止任务。以下是其核心功能:

代码执行:通过 Bash 工具执行命令。

自然对话:通过 system_prompt 和 next_step_prompt 实现与用户的交互。

任务管理:支持任务终止(通过 Terminate 工具)。

如下所示:

classSWEAgent(ToolCallAgent):"""    一个实现 SWEAgent 范式的代理,用于执行代码和进行自然对话。    该代理是一个自主的 AI 程序员,能够直接与计算机交互以完成任务。    """# 代理的核心属性    name: str = "swe"# 代理的名称    description: str = "an autonomous AI programmer that interacts directly with the computer to solve tasks."# 代理的描述# 提示模板    system_prompt: str = SYSTEM_PROMPT  # 系统提示    next_step_prompt: str = NEXT_STEP_TEMPLATE  # 下一步行动提示模板# 可用工具集合    available_tools: ToolCollection = ToolCollection(        Bash(), StrReplaceEditor(), Terminate()    )# 特殊工具名称列表    special_tool_names: List[str] = Field(default_factory=lambda: [Terminate().name])# 最大执行步骤数    max_steps: int = 30# Bash 工具实例    bash: Bash = Field(default_factory=Bash)# 当前工作目录    working_dir: str = "."asyncdefthink(self) -> bool:"""        处理当前状态并决定下一步行动。        返回:            bool: 是否需要执行行动(True 表示需要行动,False 表示不需要)。        """# 更新当前工作目录        self.working_dir = await self.bash.execute("pwd")# 格式化下一步行动提示,插入当前目录        self.next_step_prompt = self.next_step_prompt.format(            current_dir=self.working_dir        )# 调用父类的 think 方法returnawait super().think()

toolcall.py

几个主要函数的功能如下

think

  • 作用:处理当前状态并决定下一步行动,使用工具调用。
  • 关键逻辑
    • 如果存在 next_step_prompt,将其作为用户消息添加到记忆。
    • 调用语言模型(llm.ask_tool)获取响应,包括工具调用选项。
    • 根据 tool_choices 模式(noneautorequired)决定是否使用工具。
    • 记录日志并返回是否需要执行行动。

act

  • 作用:执行工具调用并处理结果。
  • 关键逻辑
    • 如果没有工具调用,返回最后一条消息的内容。
    • 遍历工具调用列表,逐个执行工具并记录结果。
    • 将工具执行结果添加到记忆。
    • 返回所有工具执行结果的汇总。

execute_tool

  • 作用:执行单个工具调用,并提供健壮的错误处理。
  • 关键逻辑
    • 检查工具调用是否有效。
    • 解析工具调用的参数。
    • 调用工具并获取结果。
    • 处理特殊工具(如 Terminate)。
    • 返回工具执行结果或错误信息。

_handle_special_tool

  • 作用:处理特殊工具的执行和状态变更。
  • 关键逻辑
    • 检查工具是否为特殊工具。
    • 如果是特殊工具且满足完成条件,将代理状态设置为 FINISHED

_should_finish_execution

  • 作用:判断工具执行是否应终止代理。
  • 关键逻辑
    • 默认返回 True,表示工具执行应终止代理。
    • 可根据需要被子类重写以实现自定义逻辑。

_is_special_tool

  • 作用:检查工具名称是否在特殊工具列表中。
  • 关键逻辑
    • 比较工具名称与 special_tool_names 列表中的名称(忽略大小写)。
    • 返回布尔值,表示是否为特殊工具。

流程走通

  1. 先进入到main.py函数里面执行程序
  2. 调用.run函数,查看代码结构,发现.run函数在base.py里面的BaseAgent里面
  1. run函数调用.step,查看代码,发现.step在react.py里面

好了,搞清楚了,先self.think一下,怎么想,用代码想啊

想的过程就要将工具加进来了

加进来后就采取act,需要act的话,就self.act

需要act的话,就要操作工具了,openmanus提供了很多的工具,