從對(duì)話到自主行動(dòng):AI應(yīng)用如何從 Chat 進(jìn)化為 Agent?開(kāi)源項(xiàng)目源碼深度揭秘
目錄
一、引言
二、以「對(duì)話為中心」的ChatBot
三、以「交付為中心」的多智能體Agent
三、什么是智能體Agent
1. 從Prompt到思維鏈
2. ReAct架構(gòu)
3. Agent
4. Manus:一個(gè)Agent典型案例
5.大模型上下文協(xié)議(MCP)
四、智能體Agent實(shí)現(xiàn)的源碼剖析(OpenManus項(xiàng)目)
1. 準(zhǔn)備
2. 代碼
五、總結(jié)
一、引言
從2022年12月份OpenAI發(fā)布ChatGPT產(chǎn)品至今已有2年多的時(shí)間,當(dāng)大家已經(jīng)習(xí)慣于在對(duì)話框中與AI交互,習(xí)慣于通過(guò)各種Prompt技巧讓AI更好的理解并回答我們的問(wèn)題,似乎默認(rèn)這就是一種比較好與AI的交互方式了。
然而,這就是我們期盼的與AI交互的形式嘛?這是一種高效的方式嘛?
顯然,這是不夠的。
我們期望的是:告訴AI我們想要的目標(biāo)或者任務(wù),AI能夠理解深度理解并分析我們的意圖、自動(dòng)的進(jìn)行任務(wù)的拆解、自動(dòng)的尋找可以使用的工具、自動(dòng)的進(jìn)行結(jié)果數(shù)據(jù)的匯總過(guò)濾、自動(dòng)的呈現(xiàn)符合任務(wù)的展示形式。同時(shí)在任務(wù)處理過(guò)程中,可以自己完成異常的檢測(cè)和修改。就如同一位優(yōu)秀的同學(xué),我們告訴他任務(wù)的目標(biāo),他可以自己尋找飛書(shū)文檔、搜索網(wǎng)絡(luò)知識(shí)、使用內(nèi)部系統(tǒng)、自己編碼驗(yàn)證方案可行性,并最終給一份好的解決方案。
二、以「對(duì)話為中心」的ChatBot
我們發(fā)送一條指令,AI被動(dòng)的響應(yīng)指令。即完成一輪人與AI的交互。
三、以「交付為中心」的多智能體Agent
我們發(fā)送一個(gè)任務(wù),AI自動(dòng)分析任務(wù)、調(diào)用可用的工具、分析結(jié)果、過(guò)濾數(shù)據(jù)并自動(dòng)處理異常,最終呈現(xiàn)解決方案。
完成這樣的一個(gè)任務(wù),需要多智能體Agent間的協(xié)作以及對(duì)常用工具的調(diào)用。那什么是智能體Agent呢?
四、什么是智能體Agent
從Prompt到思維鏈
隨著大模型的發(fā)展,Prompt工程已成為撬動(dòng)大模型潛能的核心技術(shù)。即使我們普通用戶在與大模型的交互中,也通過(guò)角色定義(如"資深工程師")或示例引導(dǎo)來(lái)優(yōu)化輸出效果,但這類簡(jiǎn)單提示往往難以突破模型固有的邏輯天花板——就像給賽車(chē)裝自行車(chē)輪胎,再怎么調(diào)整也難以突破速度極限。
但偶然間,人們發(fā)現(xiàn)了一個(gè)神奇的咒語(yǔ):只需要告訴大模型,你的 think 要 step by step。研究者發(fā)現(xiàn)只要加了這個(gè)prompt,就能極為顯著地改善大模型做數(shù)學(xué)題的正確率。
大模型的數(shù)學(xué)與邏輯能力短板,是所有體驗(yàn)過(guò)其對(duì)話功能的用戶都能直觀感受到的痛點(diǎn)。這一缺陷嚴(yán)重制約了大模型的商業(yè)化落地進(jìn)程,畢竟沒(méi)有人敢輕易信任一個(gè)邏輯混亂的智能系統(tǒng)能輸出可靠的決策結(jié)果。于是,提升大模型數(shù)學(xué)能力,被所有做基礎(chǔ)模型的公司當(dāng)作了第一目標(biāo)。
研究者試圖通過(guò)強(qiáng)化思維鏈來(lái)突破這一瓶頸。一個(gè)直觀的思路是:讓模型像人類解題時(shí)在草稿紙上推演那樣,通過(guò) "step by step" 的方式展開(kāi)邏輯鏈條 —— 在這個(gè)過(guò)程中,包含假設(shè)、演繹、反思、糾錯(cuò)等一系列思維活動(dòng)。既然人類通過(guò)這種結(jié)構(gòu)化的思考方式能夠有效解決數(shù)學(xué)問(wèn)題,那么大模型是否也能通過(guò)類似機(jī)制實(shí)現(xiàn)能力躍遷?這一猜想推動(dòng)著研究向縱深發(fā)展,最終形成了思維鏈技術(shù)的核心框架。這樣的觀念經(jīng)過(guò)繼續(xù)鉆研,最終就構(gòu)成了思維鏈,思維鏈?zhǔn)且粋€(gè)能以最小的代價(jià),而非常顯著提升模型智力水平(邏輯能力、解題能力、代碼能力)的技術(shù)。
值得注意的是,2025 年春節(jié)期間引發(fā)廣泛關(guān)注的 DeepSeek 大模型,正是思維鏈技術(shù)的成功實(shí)踐典范。盡管 DeepSeek 并非首創(chuàng)者,但其通過(guò)創(chuàng)新性地融合混合專家(MoE)架構(gòu)與強(qiáng)化學(xué)習(xí)技術(shù),顯著提升了思維鏈推理的計(jì)算效率與性能表現(xiàn)。這種技術(shù)優(yōu)化使得 DeepSeek 在保持高精度推理的同時(shí),大幅降低了計(jì)算成本,最終實(shí)現(xiàn)了屠榜級(jí)表現(xiàn)。
ReAct架構(gòu)
如果說(shuō)思維鏈(COT)是給 AI 裝上了人類的 "草稿紙",那么 ReAct 框架就是為它配備了 "雙手"—— 讓 AI 不僅能在腦子里推演,還能主動(dòng)采取行動(dòng)獲取信息。這種 "思考 + 行動(dòng)" 的組合,正在把大模型從 "紙上談兵" 的理論家,變成能解決現(xiàn)實(shí)問(wèn)題的實(shí)干家。
ReAct 的核心在于將推理(Reasoning)與行動(dòng)(Action)緊密結(jié)合。當(dāng)模型面對(duì)復(fù)雜問(wèn)題時(shí),會(huì)先像人類一樣拆解思考步驟,然后根據(jù)中間結(jié)果調(diào)用外部工具(如搜索引擎、數(shù)據(jù)庫(kù)、計(jì)算器)獲取實(shí)時(shí)數(shù)據(jù),再把這些信息整合到后續(xù)推理中。
其實(shí),實(shí)現(xiàn)一個(gè)ReAct很簡(jiǎn)單,只需要構(gòu)建Prompt+提供工具+循環(huán)執(zhí)行即可,筆者在這里不進(jìn)行詳細(xì)的介紹,只需要給一個(gè)Prompt例子,讀者就能理解:
盡可能最好地為用戶回答接下來(lái)的問(wèn)題,你可以使用以下工具來(lái)輔助你:{tools} 使用以下格式:
- 問(wèn)題:你需要回答的輸入問(wèn)題
- 思考:你需要持續(xù)思考下一步采取什么行動(dòng)
- 行動(dòng):要采取的行動(dòng),應(yīng)該是 [{tool_names}] 中的一個(gè),以及該行動(dòng)的輸入內(nèi)容
- 觀察:行動(dòng)并觀測(cè)結(jié)果,并判斷結(jié)果是否合理 ...(這個(gè)思考 / 行動(dòng) / 觀察可以重復(fù) N 次,直到你認(rèn)為知道了最終答案
- 最終答案:原始輸入問(wèn)題的最終答案
開(kāi)始!
- 問(wèn)題:{input}
Tools支持開(kāi)發(fā)者自定義,比如給予LLM一個(gè)查詢天氣的接口、計(jì)算器接口等。
ReAct架構(gòu)實(shí)現(xiàn)了一種"問(wèn)題拆解-工具調(diào)用-結(jié)果整合"的閉環(huán)機(jī)制,使得開(kāi)發(fā)者僅需通過(guò)定義工具集(如天氣API、計(jì)算器、知識(shí)圖譜接口)和設(shè)計(jì)任務(wù)引導(dǎo)詞,就能將大模型轉(zhuǎn)化為可執(zhí)行多步驟決策的智能體。最終可以使大模型突破純文本推理的局限,真正具備了在動(dòng)態(tài)場(chǎng)景中解決開(kāi)放性問(wèn)題的工程化能力。
Agent
Agent作為大模型技術(shù)的集大成者,通過(guò)整合思維鏈(CoT)的推理能力和ReAct框架的行動(dòng)機(jī)制,構(gòu)建了具備自主決策與執(zhí)行能力的智能系統(tǒng)。其核心突破在于將“大腦”與“四肢”有機(jī)統(tǒng)一,標(biāo)志著大模型從被動(dòng)應(yīng)答邁向主動(dòng)干預(yù)現(xiàn)實(shí)的質(zhì)變。
在架構(gòu)上,Agent與ReAct差別不大,ReAct是Agent的核心實(shí)現(xiàn)范式之一,Agent進(jìn)一步整合記憶存儲(chǔ)、多智能體協(xié)作等模塊,形成更完整的自主決策系統(tǒng)。下圖是一個(gè)簡(jiǎn)單的Agent架構(gòu)圖:
Agent處理流程
1-4步會(huì)循環(huán)進(jìn)行,直到LLM認(rèn)為問(wèn)題已被回答。
1.規(guī)劃(Planning):
- 定義:規(guī)劃是Agent的思維模型,負(fù)責(zé)拆解復(fù)雜任務(wù)為可執(zhí)行的子任務(wù),并評(píng)估執(zhí)行策略。
- 實(shí)現(xiàn)方式:通過(guò)大模型提示工程(如ReAct、CoT推理模式)實(shí)現(xiàn),使Agent能夠精準(zhǔn)拆解任務(wù),分步解決。
2.記憶(Memory):
- 定義:記憶即信息存儲(chǔ)與回憶,包括短期記憶和長(zhǎng)期記憶。
- 實(shí)現(xiàn)方式:短期記憶用于存儲(chǔ)會(huì)話上下文,支持多輪對(duì)話;長(zhǎng)期記憶則存儲(chǔ)用戶特征、業(yè)務(wù)數(shù)據(jù)等,通常通過(guò)向量數(shù)據(jù)庫(kù)等技術(shù)實(shí)現(xiàn)快速存取。
3.工具(Tools):
- 定義:工具是Agent感知環(huán)境、執(zhí)行決策的輔助手段,如API調(diào)用、插件擴(kuò)展等。
- 實(shí)現(xiàn)方式:通過(guò)接入外部工具(如API、插件)擴(kuò)展Agent的能力,如ChatPDF解析文檔、Midjourney文生圖等。
4.行動(dòng)(Action):
- 定義:行動(dòng)是Agent將規(guī)劃與記憶轉(zhuǎn)化為具體輸出的過(guò)程,包括與外部環(huán)境的互動(dòng)或工具調(diào)用。
- 實(shí)現(xiàn)方式:Agent根據(jù)規(guī)劃與記憶執(zhí)行具體行動(dòng),如智能客服回復(fù)、查詢天氣預(yù)報(bào)、AI機(jī)器人抓起物體等。
Manus:一個(gè)Agent典型案例
在讀完前一節(jié)關(guān)于智能體(Agent)的技術(shù)解析后,讀者也許會(huì)認(rèn)為這類系統(tǒng)的工程實(shí)現(xiàn)并非難事,實(shí)際上也確實(shí)是這樣。近期爆火的 Agent 產(chǎn)品 Manus 便是典型案例。當(dāng)用戶提出 "定制 7 天日本旅行計(jì)劃" 的需求時(shí),Manus 能夠基于目標(biāo),自主進(jìn)行網(wǎng)絡(luò)搜索并將信息整合,展現(xiàn)出高度擬人化的任務(wù)執(zhí)行邏輯。
盡管 Manus 目前尚未向普通用戶開(kāi)放,且采用邀請(qǐng)制注冊(cè)的封閉運(yùn)營(yíng)模式,但其通過(guò)官方演示視頻呈現(xiàn)的強(qiáng)大智能化表現(xiàn),已在技術(shù)圈引發(fā)廣泛關(guān)注。值得關(guān)注的是,隨著Agent技術(shù)的熱度攀升,開(kāi)源社區(qū)已迅速涌現(xiàn)出 OpenManus、OWL 等多個(gè)復(fù)刻項(xiàng)目。
因?yàn)镸anus并非開(kāi)源,我們很難了解其技術(shù)細(xì)節(jié)。但好在:
- "Manus 的部分技術(shù)細(xì)節(jié),包括其提示詞設(shè)計(jì)、運(yùn)行機(jī)制等內(nèi)容被網(wǎng)友通過(guò)非官方渠道披露,感興趣的讀者可自行查閱相關(guān)公開(kāi)資料。
- 我們可以了解一下大模型上下文協(xié)議(Model Context Protocol,MCP),這是 Anthropic (Claude) 主導(dǎo)發(fā)布的一個(gè)開(kāi)放的、通用的、有共識(shí)的協(xié)議標(biāo)準(zhǔn),雖然Manus不一定用了這個(gè)協(xié)議,但目前一些相關(guān)開(kāi)源項(xiàng)目也是基于MCP的,本文會(huì)在下面介紹MCP。
- 目前已有復(fù)刻的開(kāi)源項(xiàng)目Openmanus,筆者會(huì)在接下來(lái)的章節(jié)剖析其源碼。
大模型上下文協(xié)議(MCP)
MCP是做什么的?
MCP(Model Context Protocol)作為一項(xiàng)開(kāi)放協(xié)議,旨在為應(yīng)用程序與大型語(yǔ)言模型(LLMs)之間的上下文交互提供標(biāo)準(zhǔn)化框架。其設(shè)計(jì)理念可類比為數(shù)字時(shí)代的 "USB-C 接口"—— 正如 USB-C 統(tǒng)一了設(shè)備與外設(shè)的連接標(biāo)準(zhǔn),MCP 通過(guò)標(biāo)準(zhǔn)化的上下文交互接口,實(shí)現(xiàn)了 AI 模型與多樣化數(shù)據(jù)源、工具之間的無(wú)縫對(duì)接。
如下圖所示,圖中的MCP server都可以看成一個(gè)個(gè)工具(如搜索引擎、天氣查詢),通過(guò)“接口”連接到MCP clients(大模型)上,大模型可以使用各種MCP server來(lái)更好地處理用戶的問(wèn)題。
此外,下游工具的開(kāi)發(fā)者也可以更好的開(kāi)發(fā)其工具,目前在MCP官網(wǎng)即可了解其各種編程語(yǔ)言的SDK和相關(guān)概念。
MCP架構(gòu)
MCP 的核心采用客戶端-服務(wù)器架構(gòu),其中 host 可以連接到多個(gè)服務(wù)器,讀者簡(jiǎn)單看看即可:
- MCP 主機(jī)(MCP Hosts):指需要通過(guò) MCP 協(xié)議獲取數(shù)據(jù)的應(yīng)用程序,涵蓋 AI 開(kāi)發(fā)工具(如 Claude Desktop)、集成開(kāi)發(fā)環(huán)境(IDEs)等智能應(yīng)用場(chǎng)景。
- MCP 客戶端(MCP Clients):作為協(xié)議的執(zhí)行者,每個(gè)客戶端與對(duì)應(yīng)的 MCP 服務(wù)器建立一對(duì)一的專屬連接,負(fù)責(zé)協(xié)議層面的通信交互。
- MCP 服務(wù)器(MCP Servers):輕量化的功能載體,通過(guò)標(biāo)準(zhǔn)化的 Model Context Protocol 對(duì)外開(kāi)放特定能力,可視為連接模型與工具的智能橋梁。
- 本地化數(shù)據(jù)源(Local Data Sources):包括服務(wù)器可安全訪問(wèn)的本地文件系統(tǒng)、數(shù)據(jù)庫(kù)及專有服務(wù),構(gòu)成數(shù)據(jù)交互的近端生態(tài)。
- 遠(yuǎn)程服務(wù)(Remote Services):通過(guò)互聯(lián)網(wǎng)連接的外部系統(tǒng),例如各類 API 接口服務(wù),拓展了模型的能力邊界。
為什么要用MCP?
從技術(shù)演進(jìn)視角看,MCP 的誕生是提示工程(Prompt Engineering)發(fā)展的必然產(chǎn)物。研究表明,結(jié)構(gòu)化的上下文信息能顯著提升大模型的任務(wù)表現(xiàn)。在傳統(tǒng)提示工程中,我們往往需要人工從數(shù)據(jù)庫(kù)篩選信息或通過(guò)工具檢索相關(guān)內(nèi)容,再手動(dòng)將這些信息注入提示詞。然而,隨著復(fù)雜任務(wù)場(chǎng)景的增多,這種手工注入信息的操作變得愈發(fā)繁瑣且低效。
為解決這一痛點(diǎn),主流大模型平臺(tái)(如 OpenAI、Google)先后引入了函數(shù)調(diào)用(Function Call)機(jī)制。該機(jī)制允許模型在推理過(guò)程中主動(dòng)調(diào)用預(yù)定義函數(shù)獲取數(shù)據(jù)或執(zhí)行操作,極大提升了自動(dòng)化水平。然而,函數(shù)調(diào)用機(jī)制存在顯著局限性:其一,不同平臺(tái)的函數(shù)調(diào)用 API 存在較大差異,例如 OpenAI 與 Google 的實(shí)現(xiàn)方式互不兼容,開(kāi)發(fā)者在切換模型時(shí)需重新編寫(xiě)代碼,徒增適配成本;其二,該機(jī)制在安全性、交互性及復(fù)雜場(chǎng)景的擴(kuò)展性方面仍存在優(yōu)化空間。
在此背景下,MCP 協(xié)議通過(guò)標(biāo)準(zhǔn)化的上下文交互接口,為大模型構(gòu)建了更具普適性的工具調(diào)用框架。它不僅解耦了模型與工具的依賴關(guān)系,還通過(guò)統(tǒng)一的協(xié)議規(guī)范解決了跨平臺(tái)兼容性問(wèn)題。更重要的是,MCP 將上下文管理提升到系統(tǒng)架構(gòu)層面,為大模型在復(fù)雜業(yè)務(wù)場(chǎng)景中的深度應(yīng)用提供了可擴(kuò)展的技術(shù)底座。這種從碎片化的提示工程到體系化的上下文協(xié)議的演進(jìn),標(biāo)志著大模型應(yīng)用正在向更高效、更規(guī)范的方向邁進(jìn)。
四、智能體Agent實(shí)現(xiàn)的源碼剖析(OpenManus項(xiàng)目)
OpenManus 是一個(gè)基于 MCP 協(xié)議的開(kāi)源智能體實(shí)現(xiàn)項(xiàng)目,旨在通過(guò)標(biāo)準(zhǔn)化的上下文協(xié)議實(shí)現(xiàn)大模型與工具的高效協(xié)同。當(dāng)前項(xiàng)目仍處于快速迭代階段,本文以其 2025 年 3 月 12 日的版本為分析對(duì)象。選擇該項(xiàng)目的原因如下:
- 團(tuán)隊(duì)背景與代碼質(zhì)量:項(xiàng)目作者來(lái)自MetaGPT,具備深厚的工程經(jīng)驗(yàn),代碼結(jié)構(gòu)清晰且注釋完善,兼顧了技術(shù)實(shí)現(xiàn)與可讀性。
- 部署便捷性:只需通過(guò)虛擬環(huán)境安裝依賴并配置大模型 API Key(如 OpenAI 的 API 密鑰),即可快速啟動(dòng),降低了技術(shù)門(mén)檻。
- 技術(shù)前沿性:項(xiàng)目緊跟大模型技術(shù)發(fā)展,且目前仍在不斷迭代的過(guò)程中。
在經(jīng)過(guò)前面對(duì)相關(guān)概念的討論,我們可以得知實(shí)現(xiàn)Agent有幾個(gè)關(guān)鍵的點(diǎn),讀者可以帶著問(wèn)題在項(xiàng)目中尋找答案:
- Prompt:其結(jié)構(gòu)化的Prompt是什么樣的?通過(guò)Prompt可以對(duì)其架構(gòu)有一個(gè)初步認(rèn)識(shí)。
- OpenManus:怎么通過(guò)大模型思考和處理問(wèn)題?
- 工具相關(guān):怎么進(jìn)行工具注冊(cè)、工具管理的?工具執(zhí)行邏輯是什么的?
準(zhǔn)備
項(xiàng)目地址:https://github.com/mannaandpoem/OpenManus/tree/main
構(gòu)建環(huán)境
創(chuàng)建一個(gè)pythnotallow=3.12的虛擬環(huán)境
- 筆者測(cè)試了一下,非3.12版本會(huì)有一個(gè)package不兼容。
- 可以用conda或python內(nèi)置的uv,項(xiàng)目文檔提供了詳細(xì)的指令。
安裝playwright
- 如果第一次使用,需要安裝playwright。
playwright install
## 或者
python -m playwright install
## 以上命令會(huì)安裝所有瀏覽器,如果只需要安裝一個(gè)瀏覽器比如firefox
python -m playwright install firefox
配置大模型API Key
- 可以用DeepSeek或通義千問(wèn)的API Key,其中通義有免費(fèi)額度,DeepSeek雖然收費(fèi)但價(jià)格便宜,測(cè)試一次使用約1000token,成本不到0.01元。
- 根據(jù)項(xiàng)目文檔配置cofig.yaml即可,但項(xiàng)目調(diào)用大模型是使用基礎(chǔ)的OpenAI API,如果使用其他大模型,可能需要基于對(duì)應(yīng)的官方文檔小改一下。
代碼
OpenManus客戶端
Python OpenManus/main.py即可在終端運(yùn)行OpenManus,讀者也可以嘗試其Web版本。
- 具體會(huì)調(diào)用20行代碼,執(zhí)行Manus類的方法run()。
進(jìn)入OpenManus/app/agent/manus.py查看Manus類,可以發(fā)現(xiàn)它繼承了ToolCallAgent類,再進(jìn)入會(huì)發(fā)現(xiàn)又是繼承,有點(diǎn)復(fù)雜,這里我畫(huà)一張關(guān)系圖。
- act()執(zhí)行時(shí)使用execute_tools()進(jìn)行具體的工具執(zhí)行。
- 總體來(lái)說(shuō),Manus類定義了Prompt和可使用的工具。
- Base類定義了run(),在run()中會(huì)循環(huán)執(zhí)行ReAct類的方法step(),直到Finish或達(dá)到max_step。
- step()類會(huì)順序執(zhí)行ToolCallAgent類的think()和act()。
當(dāng)然,這里只羅列了重要的組件和方法,一些方法沒(méi)有畫(huà)在圖中。
Prompt
一般來(lái)說(shuō),輸入給LLM的prompt分為兩種:1)系統(tǒng) prompt,用于定義模型的角色定位和行為規(guī)則;2)用戶 prompt(OpenManus稱為Next Step Prompt),用于傳達(dá)具體的任務(wù)指令或信息需求。
在OpenManus/app/prompt/manus.py中即可看到Manus的Prompt,這里展示一下中文版,讀者基于此可對(duì)OpenManus架構(gòu)有一個(gè)初步認(rèn)識(shí):
- 系統(tǒng)Prompt(SYSTEM_PROMPT):“你是 OpenManus,一個(gè)全能的人工智能助手,旨在解決用戶提出的任何任務(wù)。你擁有各種可使用的工具,能調(diào)用這些工具高效地完成復(fù)雜的請(qǐng)求。無(wú)論是編程、信息檢索、文件處理還是網(wǎng)頁(yè)瀏覽,你都能應(yīng)對(duì)自如。”
- 下一步Prompt(NEXT_STEP_PROMPT):“你可以使用 PythonExecute 與計(jì)算機(jī)進(jìn)行交互,通過(guò) FileSaver 保存重要的內(nèi)容和信息文件,使用 BrowserUseTool 打開(kāi)瀏覽器,并使用 GoogleSearch 檢索信息。根據(jù)用戶的需求,主動(dòng)選擇最合適的工具或工具組合。對(duì)于復(fù)雜的任務(wù),你可以將問(wèn)題分解,逐步使用不同的工具來(lái)解決它。在使用完每個(gè)工具后,清晰地解釋執(zhí)行結(jié)果并給出下一步的建議。
當(dāng)然,在實(shí)際執(zhí)行時(shí)會(huì)對(duì)prompt有進(jìn)一步優(yōu)化,不過(guò)核心的系統(tǒng)定位與任務(wù)指導(dǎo)原則是不會(huì)改變的。
Manus類
我們先看一下OpenManus擁有的工具,工具也支持自定義,會(huì)在后文進(jìn)行介紹。
- PythonExecute:執(zhí)行 Python 代碼以與計(jì)算機(jī)系統(tǒng)交互、進(jìn)行數(shù)據(jù)處理、自動(dòng)化任務(wù)等等。
- FileSaver:在本地保存文件,例如 txt、py、html 等文件。
- BrowserUseTool:打開(kāi)、瀏覽并使用網(wǎng)絡(luò)瀏覽器。如果你打開(kāi)一個(gè)本地 HTML 文件,必須提供該文件的絕對(duì)路徑。
- GoogleSearch:執(zhí)行網(wǎng)絡(luò)信息檢索。
- Terminate:如果LLM認(rèn)為回答完畢,會(huì)調(diào)用這個(gè)工具終止循環(huán)。
Base類
run()
- 首先,輸入的request就是用戶輸入的提問(wèn)。
狀態(tài)管理
- 執(zhí)行時(shí)首先檢查代理的當(dāng)前狀態(tài)是否為 IDLE?(空閑狀態(tài))。如果不是空閑狀態(tài),會(huì)拋出 RuntimeError 異常,因?yàn)橹挥性诳臻e狀態(tài)下才能啟動(dòng)代理的執(zhí)行。
- 當(dāng)進(jìn)入循環(huán)時(shí)前,使用 state_context?上下文管理器將代理的狀態(tài)臨時(shí)切換到 RUNNING?(運(yùn)行狀態(tài))。在上下文管理器中執(zhí)行的代碼塊會(huì)在進(jìn)入時(shí)將狀態(tài)切換為指定狀態(tài),在退出時(shí)恢復(fù)到之前的狀態(tài)。如果在執(zhí)行過(guò)程中發(fā)生異常,會(huì)將狀態(tài)切換為 ERROR。
Memory管理
我們調(diào)用大模型的API,本質(zhì)是向大模型提供方發(fā)http請(qǐng)求,http請(qǐng)求是無(wú)狀態(tài)的。
- 也就是說(shuō),服務(wù)端不會(huì)保留任何會(huì)話信息。對(duì)于每次都完成一個(gè)獨(dú)立的任務(wù),無(wú)狀態(tài)是沒(méi)有任何問(wèn)題的。但對(duì)持續(xù)聊天來(lái)說(shuō),就會(huì)出現(xiàn)對(duì)之前會(huì)話一無(wú)所知的情況。
所以為了讓大模型持續(xù)與用戶的對(duì)話,一種常見(jiàn)的解決方案就是把聊天歷史告訴大模型。
- 因此,在OpenManus中會(huì)進(jìn)行Memory的管理。
- 用戶提供的 request? 參數(shù),調(diào)用 update_memory 方法將該請(qǐng)求作為用戶消息添加到代理的Memory中。
- 除了這個(gè)函數(shù),Manus也在進(jìn)行think()、act()時(shí)也會(huì)更新Memory,同時(shí)Memory容量也不是無(wú)限大的,容量滿時(shí)需要?jiǎng)h除老的Message。
主循環(huán)
agent本質(zhì)就是循環(huán)執(zhí)行。
- step實(shí)現(xiàn)參考react step。
- 循環(huán)結(jié)束條件:max_steps或者FINISHED狀態(tài)。
- 每次執(zhí)行一個(gè)step并獲得result——step_result = await self.step()。
- is_stuck? 方法用于檢查代理是否陷入了循環(huán)(即是否出現(xiàn)了重復(fù)的響應(yīng))。如果是,則調(diào)用 handle_stuck_state 方法處理這種情況,例如添加一個(gè)提示來(lái)改變策略。
ReAct
step()
- 這里的邏輯很簡(jiǎn)單。
ToolcallAgent
Think()
- 輸入:不需要輸入,因?yàn)橛脩舻膓uestion是被存放在Memory中。
- 輸出:一個(gè)bool類型,當(dāng)內(nèi)部LLM判斷需要act()時(shí),為T(mén)rue,否則為Fasle。
詢問(wèn)LLM
- 55行的代碼用于調(diào)用LLM的API接口,獲取回復(fù)。
對(duì)應(yīng)到OpenManus/app/llm.py 233行附近,這里就是基于OpenAI提供的API接口進(jìn)行對(duì)話,具體的參數(shù)可參考相應(yīng)官方文檔。
- 這里會(huì)將之前定義的下一步Prompt發(fā)給LLM,LLM會(huì)根據(jù)提供的工具列表,判斷是否需要且調(diào)用的是哪個(gè)工具,當(dāng)然也可能是:1)不需要工具只進(jìn)行回復(fù) 2)調(diào)用Terminate工具結(jié)束會(huì)話。
下圖是一次返回response結(jié)果。
- 輸入的question是“計(jì)算Kobe Bryant的BMI?”,LLM先分析出了要通過(guò)瀏覽器查詢資料,因此要use the BrowserUseTool。
- 根據(jù)傳入的工具類型等信息,LLM自動(dòng)構(gòu)建了執(zhí)行工具需要用的tool_name、action等參數(shù)。
ChatCompletionMessage(
cnotallow="It seems there was an issue with retrieving the information about Kobe Bryant's height and weight through a Google search. To calculate Kobe Bryant's BMI, we need his height and weight. Let's try to find this information by opening a browser and visiting a reliable source. I will use the BrowserUseTool to navigate to a website that provides details about Kobe Bryant's height and weight. Let's proceed with this approach.",
refusal=None,
role='assistant',
annotatinotallow=None,
audio=None,
function_call=None,
tool_calls=[
ChatCompletionMessageToolCall(
id='call_aez57ImfIEZrqjZdcW9sFNEJ',
functinotallow=Function(
arguments='{
"action":"navigate",
"url":"https://www.biography.com/athlete/kobe-bryant"
}',
name='browser_use'),
type='function')]
)
think后續(xù)邏輯
- think()后續(xù)的邏輯比較簡(jiǎn)單,主要是更新memory(memory存儲(chǔ)單位是message),最后在100行附近的邏輯,基于self.tool_choices等參數(shù)的設(shè)置和LLM返回的工具列表,輸出bool類型結(jié)果。
- 同時(shí),需要被調(diào)用的工具會(huì)被記錄到self.tool_calls這個(gè)列表中,后續(xù)的act()會(huì)執(zhí)行對(duì)應(yīng)的工具。
Act()
- 輸入:同think(),不需要輸入。
- 輸出:results,根據(jù)工具結(jié)果構(gòu)建的一個(gè)字符串。
- 這個(gè)函數(shù)比較簡(jiǎn)單,主要是調(diào)用execute_tool()函數(shù)。
Execute_tool()
該函數(shù)會(huì)調(diào)用Tool類提供的接口execute()。
- Tool類接口會(huì)在后面介紹。
同時(shí),對(duì)于預(yù)設(shè)定的special tool,會(huì)self._handle_special_tool(name=name, result=result)進(jìn)行特殊處理。
- 當(dāng)前的special tool只有一個(gè)Terminate工具,特殊處理就是設(shè)置Agent的狀態(tài)為AgentState.FINISHED,結(jié)束對(duì)話。
工具相關(guān)
我們?cè)谥敖榻B了MCP相關(guān)的概念,如下圖所示:
事實(shí)上,OpenManus也是基于MCP的,OpenManus的tool相當(dāng)于MCP server,根據(jù)MCP協(xié)議,我們只需要定義tool類支持的方法和參數(shù)等,每次注冊(cè)一個(gè)新工具,根據(jù)父類override一個(gè)子類即可。
那我們首先要了解父類都定義了什么參數(shù)和方法,也就是OpenManus/app/tool/base.py定義的Basetool類。
Base Tool
可以看出,代碼很簡(jiǎn)單,每個(gè)tool包含的參數(shù)為:name、description(提供給LLM看的,對(duì)工具的介紹)、parameters(執(zhí)行工具時(shí)要用的參數(shù))。
同時(shí),一個(gè)tool支持的方法有execute()和to_param()。
- execute()用于執(zhí)行具體的邏輯,每個(gè)子類需要override這個(gè)方法。
- to_param()將工具調(diào)用的結(jié)果結(jié)構(gòu)化輸出。
當(dāng)然,這里還有一個(gè)python關(guān)鍵字__call__,這個(gè)關(guān)鍵字很簡(jiǎn)單,定義了__call__,該類的實(shí)例對(duì)象可以像函數(shù)一樣被調(diào)用。
工具JSON
可以根據(jù)OpenManus預(yù)定義的工具json簡(jiǎn)單了解一下,每個(gè)工具執(zhí)行時(shí)需要的參數(shù)。
[
{
"type": "function",
"function": {
"name": "python_execute",
"description": "Executes Python code string. Note: Only print outputs are visible, function return values are not captured. Use print statements to see results.",
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "The Python code to execute."
}
},
"required": ["code"]
}
}
},
{
"type": "function",
"function": {
"name": "google_search",
"description": "Perform a Google search and return a list of relevant links.\nUse this tool when you need to find information on the web, get up-to-date data, or research specific topics.\nThe tool returns a list of URLs that match the search query.\n",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "(required) The search query to submit to Google."
},
"num_results": {
"type": "integer",
"description": "(optional) The number of search results to return. Default is 10.",
"default": 10
}
},
"required": ["query"]
}
}
]
工具示例——google_search
OpenManus項(xiàng)目在OpenManus/app/tool中定義了bash工具、瀏覽器工具、谷歌搜索工具等,這里簡(jiǎn)單看一下谷歌搜索工具。
當(dāng)然,國(guó)內(nèi)可能比較難使用谷歌搜索,OpenManus社區(qū)也有大佬提供了baidu、bing等搜索引擎工具。
可以看出,代碼很簡(jiǎn)單,主要做了兩件事。
- 定義工具參數(shù):name、description、parameters。
- 定義execute:基于googlesearch庫(kù)提供的函數(shù)進(jìn)行搜索并返回。
五、總結(jié)
OpenManus的代碼介紹到這里,主要是介紹一下核心代碼,同時(shí),原作者寫(xiě)了planning部分的代碼但暫時(shí)沒(méi)有應(yīng)用到項(xiàng)目中,筆者也沒(méi)有介紹。如果想對(duì)該項(xiàng)目有更進(jìn)一步的了解,請(qǐng)大家查看github上提供的源碼。而且,作者還是非常積極的,每天會(huì)有十幾個(gè)commit。
同時(shí),讀者可以簡(jiǎn)單本地部署玩一下OpenManus,通過(guò)幾個(gè)prompt,就可以知道該項(xiàng)目還是停留在“玩具階段”,比如筆者測(cè)試了一下,當(dāng)詢問(wèn)“計(jì)算一下科比的BMI?”,OpenManus可以很準(zhǔn)確的實(shí)現(xiàn)谷歌搜索——瀏覽器訪問(wèn)——python計(jì)算這個(gè)過(guò)程。但如果詢問(wèn)“計(jì)算科比、梅西的BMI并排序?”,無(wú)論我改寫(xiě)了幾次prompt,OpenManus都沒(méi)有給我滿意的回答。
此外,無(wú)論是在工具參數(shù)信息、還是prompt、memory管理中,都可以看到agent應(yīng)用大模型token消耗量巨大,即使我們不考慮token成本,但大模型的上下文仍然是有限的,這種資源消耗也會(huì)直接導(dǎo)致模型在處理多步驟任務(wù)時(shí)面臨信息截?cái)嗟娘L(fēng)險(xiǎn) —— 早期的關(guān)鍵信息可能因上下文溢出而被丟棄,進(jìn)而引發(fā)推理鏈條的斷裂。更值得警惕的是,當(dāng)模型試圖在有限的上下文中 “腦補(bǔ)” 缺失的信息時(shí),往往會(huì)產(chǎn)生與事實(shí)不符的幻覺(jué)。
鑒于此,盡管 OpenManus 展示出了利用工具鏈解決復(fù)雜問(wèn)題的潛力,不過(guò)距離成為一個(gè)實(shí)用、高效且穩(wěn)定的生產(chǎn)級(jí)人工智能助手仍有很長(zhǎng)的路要走。未來(lái),開(kāi)發(fā)者們或許需要在優(yōu)化工具使用邏輯、提升多任務(wù)處理能力、降低大模型 token 消耗以及增強(qiáng)上下文管理等方面進(jìn)行深入探索與改進(jìn)。同時(shí),對(duì)于普通用戶而言,在體驗(yàn)這類項(xiàng)目時(shí),也應(yīng)該保持理性和客觀的態(tài)度,既看到其創(chuàng)新性和趣味性,也認(rèn)識(shí)到其當(dāng)前存在的局限性。希望在技術(shù)的不斷迭代和完善下,OpenManus 以及類似的項(xiàng)目能夠早日突破現(xiàn)有的瓶頸,真正為人們的工作和生活帶來(lái)實(shí)質(zhì)性的幫助。
本文轉(zhuǎn)載自??得物技術(shù)??,作者:漢堡
