一文入門Agent:從理論到代碼實戰(zhàn)
Agent(智能體)比較權(quán)威的定義出自 Stuart Russell 與 Peter Norvig 的《Artificial Intelligence: A Modern Approach》(1995, 《人工智能:一種現(xiàn)代方法》)。
An agent is anything that can be viewed as perceiving its environment through sensors and acting upon that environment through actuators.
通常指一個能夠自主感知環(huán)境、決策并執(zhí)行動作以完成特定目標的智能系統(tǒng) 。
圖片
簡單來說,它就像是一個智能代理,可以接受我們的指令,在一定程度上自己想辦法去完成任務(wù),而不僅僅是被動響應(yīng)。
舉個日常類比:可以把 Agent 想象成自己的 AI 助手或員工,給出任務(wù),它會自己想如何去做,必要時查資料、調(diào)用工具,最后給出結(jié)果。
發(fā)展歷史
人工智能領(lǐng)域的「Agent」概念經(jīng)歷了漫長的發(fā)展演變:
規(guī)則驅(qū)動的系統(tǒng)與專家系統(tǒng)(1950 - 1990年):
早期的 AI 系統(tǒng)多是基于手工編寫規(guī)則的。這類系統(tǒng)按照預(yù)設(shè)的 if-then 規(guī)則集工作,缺乏靈活性但在特定領(lǐng)域表現(xiàn)不錯。
典型代表是專家系統(tǒng),例如 1970s 的醫(yī)學(xué)診斷專家系統(tǒng) MYCIN 和更早的 DENDRAL 。專家系統(tǒng)通過將人類專家的知識轉(zhuǎn)化為規(guī)則庫,能在狹窄領(lǐng)域模擬出專家級推理 。
比如 MYCIN 系統(tǒng)包含數(shù)百條治療傳染病的規(guī)則,可以根據(jù)患者癥狀給出診斷和治療建議。它甚至能用一定的自然語言與用戶交互并解釋自己的推理過程 。
然而,這類系統(tǒng)的局限在于:知識獲取成本高(需要專家手工編碼大量規(guī)則),不具備自我學(xué)習(xí),遇到規(guī)則覆蓋不到的情況就束手無策。
強化學(xué)習(xí) Agent(1990 - 2020年)
隨著機器學(xué)習(xí)興起,Agent 的智能決策開始由學(xué)習(xí)而非死板規(guī)則產(chǎn)生。
強化學(xué)習(xí)(Reinforcement Learning, RL)提供了一種讓 Agent 通過試錯與環(huán)境交互、自主學(xué)習(xí)策略的框架。
經(jīng)典的 RL 設(shè)定中,Agent 不斷感知環(huán)境狀態(tài),采取動作,根據(jù)環(huán)境給的獎勵/懲罰調(diào)整策略。經(jīng)過無數(shù)輪訓(xùn)練,Agent 學(xué)會在環(huán)境中達到獎勵最大化的行動序列。
1990 - 2000 年代,RL 被用于機器人控制、游戲等領(lǐng)域,但真正讓大眾震撼的是 2010 年代的深度強化學(xué)習(xí):例如 2016 年 DeepMind 的 AlphaGo 通過深度神經(jīng)網(wǎng)絡(luò)結(jié)合強化學(xué)習(xí),在圍棋上擊敗了人類世界冠軍,展示了 Agent 在復(fù)雜環(huán)境下驚人的決策能力。
這一時期的 Agent 多數(shù)是在模擬/游戲環(huán)境里訓(xùn)練出的「智能體」(如學(xué)會玩雅達利游戲、下棋等),它們能自行探索出有效策略。
然而,RL Agent 通常需要明確的獎勵函數(shù)和大量訓(xùn)練樣本,在現(xiàn)實開放任務(wù)上應(yīng)用受限。此外,訓(xùn)練得到的策略往往專門針對某一任務(wù),缺乏通用性。
大語言模型時代的 Agent(2020年代)
進入 2020 年,AI 出現(xiàn)了一個新拐點:大型語言模型(LLM)的崛起。
像 GPT-3、GPT-4 這樣的模型在海量文本上預(yù)訓(xùn)練,掌握了豐富的世界知識和推理能力。
研究者們很快意識到,可以把 LLM 當作通用「大腦」來賦予 Agent 智慧,而不必像過去那樣為每個任務(wù)單獨訓(xùn)練模型。
2022年,提出了鏈式思考(Chain-of-Thought, CoT)提示方法,讓語言模型學(xué)會在輸出最終答案前先生成逐步的思考過程。這使模型在復(fù)雜推理題上表現(xiàn)大幅提升 。
緊接著,研究者開始探索如何讓 LLM 不僅會「想」也會「做」,于是出現(xiàn)了將推理和行動交織的架構(gòu)(后面詳述的 ReAct 等),賦予模型調(diào)用工具、與外界交互的能力 。
Autonomous Agent(自主代理)的概念在 2023 年引爆開源社區(qū):比如 AutoGPT 和 BabyAGI 等項目火遍全網(wǎng) 。這些系統(tǒng)基于 GPT-4 等強大 LLM,圍繞「讓AI自主完成復(fù)雜任務(wù)」展開實驗。
例如 AutoGPT 可以在給定一個高階目標后,自己拆解子任務(wù)、通過互聯(lián)網(wǎng)搜索信息、執(zhí)行代碼等,一系列操作循環(huán),直到完成目標。
雖然早期的 AutoGPT 暫未表現(xiàn)出可靠實用的效果,但它標志著一種全新的 Agent 形態(tài):完全由 LLM 驅(qū)動的自治智能體。
同時,LangChain 等開發(fā)框架崛起,為構(gòu)建此類 LLM Agent 提供了便利工具庫。
總的來說,LLM時代的 Agent 相比以往有幾個顯著特點:無需專項訓(xùn)練即可通用(依賴預(yù)訓(xùn)練知識),以自然語言為接口(決策過程和人類可讀的計劃融為一體),以及能夠調(diào)用開放工具和知識源(如網(wǎng)絡(luò)、數(shù)據(jù)庫),從而顯著拓展了 AI 解決現(xiàn)實任務(wù)的能力。
LLM agent
回到目前爆火的大語言模型(LLM) agent。業(yè)界逐漸探索出多種架構(gòu)范式,其中有兩種典型模式:一種是 ReAct (Reason + Act) 推理-行動交替模式,另一種是 Plan-and-Execute 先規(guī)劃再執(zhí)行的模式。
ReAct
ReAct 是 Reasoning and Acting 的縮寫,顧名思義,它的核心思想是在 Agent 內(nèi)部將「思考(Reason)」和「行動(Act)」交替進行 。這一范式最早由 2022 年谷歌大腦團隊的論文「ReAct: Synergizing Reasoning and Acting in Language Models」提出 。
簡單來說,ReAct 讓 LLM 在解決任務(wù)時模擬人類的思考過程:想一步,做一步,再根據(jù)結(jié)果調(diào)整思考,再行動……如此循環(huán),直到得出最終答案。
圖片
ReAct Agent 的典型工作流程如下:
- Thought(思考):Agent(LLM)對當前問題或狀態(tài)進行分析,在內(nèi)部生成一段思考/推理。這一步類似人腦的自言自語,可能涉及分解問題、制定子目標、假設(shè)下一步需要的信息等。例如面對一個復(fù)雜提問,Agent 可能產(chǎn)生內(nèi)部思考:「要回答這個問題,我需要先查找相關(guān)統(tǒng)計數(shù)據(jù)」。
- Action(行動):基于上一步的思考結(jié)論,Agent 決定采取一個具體行動 。在LLM Agent中,這通常體現(xiàn)為模型輸出一個特殊格式的指令,如調(diào)用某個工具。舉例:“Action: Search[關(guān)于X的統(tǒng)計數(shù)據(jù)]”。這里的工具可以是預(yù)先注入 Agent 的函數(shù),比如網(wǎng)絡(luò)搜索、計算器、數(shù)據(jù)庫查詢等。ReAct 提示模板通常要求模型按照「Thought: … \n Action: … \n Action Input: …」格式輸出 ,以明確指示要用的工具及輸入 。
- Observation(觀察):一旦 Agent 發(fā)出了 Action 指令,外部環(huán)境(或我們預(yù)先設(shè)置的執(zhí)行器)就會執(zhí)行這個動作,并將結(jié)果返回給 Agent 。比如當 Action 是搜索查詢時,Observation 可能是一段搜索結(jié)果摘要。當 Action 是調(diào)用計算器,Observation 則是計算結(jié)果的值。這個觀察結(jié)果相當于 Agent 在環(huán)境中獲取到的新信息。
- 循環(huán)迭代:Agent 將 Observation 納入自己的上下文,再次進入 Thought 階段進行推理,總結(jié)新獲取的信息,與之前的目標對比,決定下一步怎么做 。它可能修正原先思路或提出新的子任務(wù)。如果任務(wù)還沒完成就繼續(xù) Thought → Action → Observation 循環(huán)。如此反復(fù),Agent 不斷交替“思考-行動”,逐步推進任務(wù)。
- Final Answer(最終答案):當 Agent 判斷已經(jīng)收集了足夠信息或完成了目標,就會在最后一次 Thought 后輸出最終答案而不是新行動指令 。這標志著 ReAct 流程的終止,Agent 向用戶給出結(jié)果。
用一個具體例子說明:假設(shè)用戶問題是“中國的人口是多少的兩倍?”。一個 ReAct Agent 可能這樣運作:
- 初始 Thought:“用戶在問中國人口的兩倍,這需要先查中國人口是多少”。
- Action:“Search[中國人口]”。
- Observation:“搜索結(jié)果顯示:中國 2023 年人口約 14.1 億”。
- Thought:“好的,中國人口約 14.1 億,問題要兩倍,那計算一下 2×14.1 億”。
- Action:“Calculator[ 2 * 14.1 億]”。(注:Agent可能將14.1億轉(zhuǎn)成數(shù)字再計算)
- Observation:“結(jié)果=28.2 億”。
- Thought:“已經(jīng)得到答案,可以作答”。
- Final Answer:“約 28.2 億”。
ReAct 模式以其直觀明了的循環(huán)成為LLM Agent的基礎(chǔ)范式之一。
它通過交替的「思想」和「行動」賦予 Agent 如同人類一般的解題風(fēng)格,能逐步推理、調(diào)用工具獲取實時信息以降低幻覺,并通過思維外顯便于調(diào)試,通用性強。
但它效率較低、缺乏全局規(guī)劃且依賴工具,因而更適合交互性強、步驟較少、需要實時查詢或輕量推理的任務(wù)場景。
Plan-and-Execute 模式:先計劃后執(zhí)行
當任務(wù)變得更加復(fù)雜、步驟繁多時,另一種「規(guī)劃-執(zhí)行」架構(gòu)開始展現(xiàn)威力。
這種模式將 Agent 的流程明確分為兩個階段:先規(guī)劃(Plan),再執(zhí)行(Execute) 先讓 Agent 想出一整套方案,然后按照方案逐步落實。
與 ReAct 不同,Plan-and-Execute 會強制 LLM 做全局思考。它通常涉及兩個子 Agent 或子模塊:一個 Planner(規(guī)劃者)和一個Executor(執(zhí)行者)。兩者分工如下:
- Planner:由一個 LLM 來承擔(dān),它的任務(wù)是分析目標,產(chǎn)出詳細的執(zhí)行計劃。Planner 會接收用戶的最終任務(wù)描述,然后以列表形式生成需要完成的子任務(wù)序列。Planner 在這一步可以充分利用 LLM 的鏈式思考能力,將模糊的目標細化為可執(zhí)行的步驟,并考慮步驟間的依賴、先后順序等 。
- **Executor(s)**:執(zhí)行者負責(zé)按照 Planner 給出的每個子任務(wù),逐條執(zhí)行 。Executor 本質(zhì)上也是一個 Agent,可以針對不同子任務(wù)切換工具或 API,也可以調(diào)用一個內(nèi)部 ReAct Agent 來完成。Executor 會讀取任務(wù)清單的某一條,比如「第1步:搜索 X 信息」,然后實際調(diào)用對應(yīng)的工具完成它,將結(jié)果記錄下來,再執(zhí)行下一步。
Plan-and-Execute 模式的運行過程可以概括如下:
圖片
https://blog.langchain.com/planning-agents/#:~:text=Prompting%20arxiv,consists%20of%20two%20basic%20components
- 任務(wù)規(guī)劃(Planning):接收用戶請求后,首先調(diào)用 Planner (LLM) 來生成完整計劃。Planner 輸出的計劃通常是有序列表形式的步驟1、步驟2… 。例如用戶讓 Agent 「寫一份關(guān)于某課題的調(diào)研報告」,Planner 可能輸出:1. 搜集背景資料;2. 分析資料;3. 撰寫報告初稿;4. 定稿并輸出報告。Planner 提示詞通常會明示模型:「先理解問題并制定計劃,然后我們再逐步執(zhí)行」。這一階段,LLM 會盡量細化步驟直到每一步可以由工具或簡單操作完成。
- 任務(wù)執(zhí)行(Execution):拿到 Planner 給出的任務(wù)清單后,進入執(zhí)行環(huán)節(jié)。Executor 會逐步讀取每條子任務(wù)并執(zhí)行之 。執(zhí)行時可能再次用到LLM,尤其當需要處理任務(wù)中的自然語言邏輯時。例如 LangChain 實現(xiàn)中,每一步的執(zhí)行其實可以調(diào)用一個內(nèi)部 ReAct Agent 來完成 (因為子任務(wù)本身也許需要檢索或計算,多步才能得出結(jié)果)。但重要的是,Executor 聚焦于當前子任務(wù)的完成,不用操心全局流程。執(zhí)行一個步驟后,把結(jié)果保存到共享狀態(tài)中(相當于黑板或內(nèi)存,記錄目前有哪些信息、子任務(wù)完成情況) 。
- 計劃調(diào)整(Replan,可選):理想情況下,按照初始計劃順利執(zhí)行完所有步驟,就可以結(jié)束了。然而現(xiàn)實中,有時初始計劃并不完美:可能遺漏了一些步驟,或者某步結(jié)果出乎意料、需要增加新的步驟。Plan-and-Execute 架構(gòu)因此通常允許一個反饋回路:當執(zhí)行到一定階段后,Agent 可以啟動 Planner 進行重新規(guī)劃 (Replan) 。此時 Planner 會參考當前已完成的任務(wù)狀態(tài),增補或修改后續(xù)計劃。這個規(guī)劃-執(zhí)行循環(huán)可以進行多輪,直到 Agent 確信任務(wù)完成。
- 生成最終答案:所有必要的子任務(wù)都執(zhí)行完畢,Agent 最后匯總狀態(tài)中的信息,由 LLM 編寫最終交付結(jié)果,并返回給用戶 (比如完整的報告文本) 。
Plan-and-Execute 的核心優(yōu)勢在于結(jié)構(gòu)化地解決復(fù)雜任務(wù),但也帶來額外成本。
相比 ReAct,它通過 Planner 和 Executor 分工來保證任務(wù)分解、執(zhí)行更有條理,適合多步驟、長程、高精度和跨工具的任務(wù)。
但缺點在于:實現(xiàn)復(fù)雜、誤差傳遞、上下文管理壓力大、執(zhí)行耗時。
因此,它更適合在復(fù)雜問題分解、長程規(guī)劃、精度要求高或需要跨工具協(xié)調(diào)的場景下使用,而在簡單任務(wù)或即時反應(yīng)的場合,ReAct 往往更高效。
代碼實戰(zhàn)
零框架實現(xiàn) ReAct
核心是兩點:
- 通過 prompt 控制大模型的輸出格式
- 解析大模型的輸出,手動調(diào)用工具
直接 Cursor 生成代碼就好:
圖片
忘了讓 AI 用 ollama,再讓它改一下:
圖片
核心就是一個不停的調(diào)用大模型的循環(huán),期間拆解動作,執(zhí)行動作,循環(huán)往復(fù):
def solve(self, question: str, verbose: bool = True) -> str:
"""
使用 ReAct 模式解決問題
Args:
question: 用戶問題
verbose: 是否顯示詳細過程
Returns:
最終答案
"""
messages = [
{"role": "system", "content": self._get_system_prompt()},
{"role": "user", "content": question}
]
for step in range(self.max_steps):
if verbose:
print(f"\\n=== 步驟 {step + 1} ===")
# 獲取模型響應(yīng)
try:
assistant_message = self._call_llm(messages)
if verbose:
print(f"Assistant: {assistant_message}")
messages.append({"role": "assistant", "content": assistant_message})
# 檢查是否包含最終答案
if"Final Answer:"in assistant_message:
final_answer = assistant_message.split("Final Answer:")[-1].strip()
if verbose:
print(f"\\n?? 找到答案: {final_answer}")
return final_answer
# 解析并執(zhí)行行動
action_result = self._parse_action(assistant_message)
if action_result:
tool_name, params = action_result
observation = self._execute_tool(tool_name, params)
if verbose:
print(f"?? 執(zhí)行工具: {tool_name}")
print(f"?? 參數(shù): {params}")
print(f"??? 觀察結(jié)果: {observation}")
# 添加觀察結(jié)果到對話歷史
messages.append({
"role": "user",
"content": f"Observation: {observation}"
})
else:
# 如果沒有找到有效的行動,繼續(xù)下一輪
if verbose:
print("?? 未找到有效的行動,繼續(xù)思考...")
except Exception as e:
error_msg = f"API 調(diào)用錯誤: {str(e)}"
if verbose:
print(f"? {error_msg}")
return error_msg
return"達到最大步數(shù)限制,未能找到答案。"拆解一下:
一個循環(huán)的框架:
def solve(self, question: str, verbose: bool = True) -> str:
"""
使用 ReAct 模式解決問題
Args:
question: 用戶問題
verbose: 是否顯示詳細過程
Returns:
最終答案
"""
messages = [
{"role": "system", "content": self._get_system_prompt()},
{"role": "user", "content": question}
]
for step in range(self.max_steps):
...
except Exception as e:
error_msg = f"API 調(diào)用錯誤: {str(e)}"
if verbose:
print(f"? {error_msg}")
return error_msg
return"達到最大步數(shù)限制,未能找到答案。"_get_system_prompt 返回提示詞:
def _get_system_prompt(self) -> str:
"""獲取系統(tǒng)提示詞"""
tools_desc = "\\n".join([
f"- {name}: {desc}"
for name, desc in self.tool_descriptions.items()
])
return f"""你是一個智能助手,使用 ReAct(Reasoning and Acting)模式來解決問題。
可用工具:
{tools_desc}
工作流程:
1. Thought: 分析問題,制定計劃
2. Action: 選擇并執(zhí)行工具
3. Observation: 觀察結(jié)果
4. 重復(fù)直到找到答案
格式要求:
- 用 "Thought:" 開始你的思考
- 用 "Action:" 開始行動,格式為 Action: tool_name(parameters)
- 我會提供 "Observation:" 顯示行動結(jié)果
- 用 "Final Answer:" 給出最終答案
示例:
Thought: 我需要計算 25 + 17 的結(jié)果
Action: calculator(25 + 17)
Observation: 42
Final Answer: 25 + 17 = 42
現(xiàn)在開始解決用戶的問題。"""其中的可用工具,需要提前實現(xiàn):
可用工具:
? calculator: 計算數(shù)學(xué)表達式,支持基本運算和常用數(shù)學(xué)函數(shù)(sqrt, sin, cos, tan, log)
? web_search: 搜索網(wǎng)絡(luò)信息,獲取實時數(shù)據(jù)和知識
? web_scraper: 抓取指定網(wǎng)頁的文本內(nèi)容
? read_file: 文件操作工具,支持讀取、寫入文件和列出目錄內(nèi)容
? write_file: 寫入內(nèi)容到文件
? list_directory: 列出目錄內(nèi)容
? get_weather: 獲取指定城市的天氣信息
image-20250925071319523
接著是循環(huán)里邊,將用戶問題和提示詞傳給大模型:
def solve(self, question: str, verbose: bool = True) -> str:
"""
使用 ReAct 模式解決問題
Args:
question: 用戶問題
verbose: 是否顯示詳細過程
Returns:
最終答案
"""
messages = [
{"role": "system", "content": self._get_system_prompt()},
{"role": "user", "content": question}
]
for step in range(self.max_steps):
if verbose:
print(f"\\n=== 步驟 {step + 1} ===")
# 獲取模型響應(yīng)
try:
assistant_message = self._call_llm(messages)
if verbose:
print(f"Assistant: {assistant_message}")
messages.append({"role": "assistant", "content": assistant_message})
# 檢查是否包含最終答案
if"Final Answer:"in assistant_message:
final_answer = assistant_message.split("Final Answer:")[-1].strip()
if verbose:
print(f"\\n?? 找到答案: {final_answer}")
return final_answer
...
except Exception as e:
error_msg = f"API 調(diào)用錯誤: {str(e)}"
if verbose:
print(f"? {error_msg}")
return error_msg
return"達到最大步數(shù)限制,未能找到答案。"因為 prompt 中要求了大模型用 「Final Answer:」給出最終答案,因此循環(huán)終點就是判斷是否有 「Final Answer」。
接著再解析大模型返回的 Action ,來手動調(diào)用提前實現(xiàn)好的工具:
def solve(self, question: str, verbose: bool = True) -> str:
"""
使用 ReAct 模式解決問題
Args:
question: 用戶問題
verbose: 是否顯示詳細過程
Returns:
最終答案
"""
messages = [
{"role": "system", "content": self._get_system_prompt()},
{"role": "user", "content": question}
]
for step in range(self.max_steps):
if verbose:
print(f"\\n=== 步驟 {step + 1} ===")
# 獲取模型響應(yīng)
try:
assistant_message = self._call_llm(messages)
if verbose:
print(f"Assistant: {assistant_message}")
messages.append({"role": "assistant", "content": assistant_message})
# 檢查是否包含最終答案
if"Final Answer:"in assistant_message:
final_answer = assistant_message.split("Final Answer:")[-1].strip()
if verbose:
print(f"\\n?? 找到答案: {final_answer}")
return final_answer
# 解析并執(zhí)行行動
action_result = self._parse_action(assistant_message)
if action_result:
tool_name, params = action_result
observation = self._execute_tool(tool_name, params)
if verbose:
print(f"?? 執(zhí)行工具: {tool_name}")
print(f"?? 參數(shù): {params}")
print(f"??? 觀察結(jié)果: {observation}")
# 添加觀察結(jié)果到對話歷史
messages.append({
"role": "user",
"content": f"Observation: {observation}"
})
else:
# 如果沒有找到有效的行動,繼續(xù)下一輪
if verbose:
print("?? 未找到有效的行動,繼續(xù)思考...")
except Exception as e:
error_msg = f"API 調(diào)用錯誤: {str(e)}"
if verbose:
print(f"? {error_msg}")
return error_msg
return"達到最大步數(shù)限制,未能找到答案。"其中 _parse_action 就是解析 prompt 中說的 用 "Action:" 開始行動,格式為 Action: tool_name(parameters)
def _parse_action(self, text: str) -> Optional[tuple]:
"""
解析行動文本,提取工具名稱和參數(shù)
Args:
text: 包含行動的文本
Returns:
(tool_name, parameters) 或 None
"""
# 查找 Action: 行
action_pattern = r"Action:\s*(\w+)\((.*?)\)"
match = re.search(action_pattern, text, re.DOTALL)
if match:
tool_name = match.group(1)
params_str = match.group(2).strip()
if tool_name in self.tools:
# 嘗試解析參數(shù)
try:
# 簡單的參數(shù)解析(可以根據(jù)需要改進)
if params_str:
# 如果參數(shù)看起來像 JSON,嘗試解析
if params_str.startswith('{') and params_str.endswith('}'):
params = json.loads(params_str)
else:
params = params_str
else:
params = None
return tool_name, params
except json.JSONDecodeError:
return tool_name, params_str
returnNone先正則解析出 Action 的內(nèi)容 r"Action:\s*(\w+)\((.*?)\)" ,接著拿到 tool_name(工具名)和 params_str(入?yún)ⅲ┓祷亍?/p>
拿到之后去調(diào)用函數(shù):
action_result = self._parse_action(assistant_message)
if action_result:
tool_name, params = action_result
observation = self._execute_tool(tool_name, params)
def _execute_tool(self, tool_name: str, params: Any) -> str:
"""
執(zhí)行工具函數(shù)
Args:
tool_name: 工具名稱
params: 工具參數(shù)
Returns:
工具執(zhí)行結(jié)果
"""
try:
tool_func = self.tools[tool_name]
if params isNone:
result = tool_func()
elif isinstance(params, dict):
result = tool_func(**params)
else:
result = tool_func(params)
return str(result)
except Exception as e:
returnf"工具執(zhí)行錯誤: {str(e)}"拿到對應(yīng)的函數(shù),然后將參數(shù)傳入即可。
最后將工具返回的結(jié)果追加到對話列表中下一次循環(huán)即可:
observation = self._execute_tool(tool_name, params)
if verbose:
print(f"?? 執(zhí)行工具: {tool_name}")
print(f"?? 參數(shù): {params}")
print(f"??? 觀察結(jié)果: {observation}")
# 添加觀察結(jié)果到對話歷史
messages.append({
"role": "user",
"content": f"Observation: {observation}"
})看下運行效果:
圖片
直接調(diào)用一次 Action: calculator(9 * 8 - 2)
圖片
調(diào)用兩次 Action,web_search("中國當前人口數(shù)") 和 calculator(1400000000 * 2)。
LangChain 實現(xiàn) Plan-and-Execute
用 LangChain 的話,我們只需要提供 Tools,提示詞、agent、記憶管理全部內(nèi)置了,代碼會簡單很多:
from langchain_community.llms import Ollama
from langchain.agents import Tool
from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner
from duckduckgo_search import DDGS
# 初始化LLM模型(Ollama qwen2.5:7b)
llm = Ollama(model="qwen2.5:7b", temperature=0)
# 定義一個DuckDuckGo搜索工具
def ddg_search(query: str) -> str:
"""使用DuckDuckGo進行搜索,返回前幾條結(jié)果摘要。"""
results = []
with DDGS() as ddgs: # 使用duckduckgo_search庫
for r in ddgs.text(query, max_results=3): # 取前三條結(jié)果
results.append(f"{r['title']}: {r['body']}")
return"\n".join(results)
search_tool = Tool(
name="WebSearch",
func=ddg_search,
descriptinotallow="用于在互聯(lián)網(wǎng)上搜索信息的工具。輸入查詢,返回相關(guān)簡要結(jié)果。"
)
tools = [search_tool]
# 加載 Planner 和 Executor
planner = load_chat_planner(llm) # 規(guī)劃階段使用同一LLM
executor = load_agent_executor(llm, tools, verbose=True) # 執(zhí)行階段Agent(允許調(diào)用搜索工具)
agent = PlanAndExecute(planner=planner, executor=executor, verbose=True)
# 運行 Agent 執(zhí)行任務(wù)
task = "調(diào)查氣候變化對北極熊種群的影響,并給出一份總結(jié)報告。"
result = agent.run(task)
print("最終匯總報告:\n", result)調(diào)用 load_agent_executor 就可以得到一個 ReAct 的 Agent,調(diào)用 load_chat_planner 就得到了可以 planner 的 Agent。
問一個相對復(fù)雜的問題 「調(diào)查氣候變化對北極熊種群的影響,并給出一份總結(jié)報告。」,最開始是生成了步驟,然后一步一步得出了結(jié)論:
Entering new PlanAndExecute chain...
steps=[Step(value='確定氣候變化的主要影響因素。'), Step(value='分析這些因素如何具體影響北極熊的生存環(huán)境和行為模式。'), Step(value='收集并分析相關(guān)科學(xué)研究數(shù)據(jù),了解北極熊種群數(shù)量變化趨勢。'), Step(value='總結(jié)氣候變化對北極熊種群的具體影響,并提出保護建議。\n\n')]
> Entering new AgentExecutor chain...
Action:
```
{
"action": "WebSearch",
"action_input": "確定氣候變化的主要影響因素"
}
```
/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation:
Thought:Action:
```
{
"action": "WebSearch",
"action_input": "確定氣候變化的主要影響因素"
}
```/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation: Butant? (district of S?o Paulo) - Wikipedia: Butant? (Portuguese pronunciation: [but???t??], from the tupi for"crushed soil") is a district of the city of S?o Paulo, Brazil. It is part of the homonymous subprefecture, located on the west bank of the …
Home - Subprefeitura - Butant? - Prefeitura: Confira informa??es atualizadas sobre a cidade de S?o Paulo!
Bairro do Butant?: 5 passeios para fazer por lá! - Visite S?o Paulo: Mar 21, 2024 · Explore o bairro do Butant?, com passeios cheios de diversidade, cultura e história. Descubra locais incríveis localizados no bairro!
Thought:Action:
```
{
"action": "WebSearch",
"action_input": "確定氣候變化的主要影響因素"
}
```/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation: YouTube: Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
YouTube on the App Store: Get the official YouTube app on iPhones and iPads. See what the world is watching -- from the hottest music videos to what’s popular in gaming, fashion, beauty, news, learning and more.
YouTube – Apps on Google Play: Get the official YouTube app on Android phones and tablets. See what the world is watching -- from the hottest music videos to what’s popular in gaming, fashion, beauty, news, learning and …
Thought:Action:
... 此處省略中間
```
{
"action": "WebSearch",
"action_input": "北極熊種群數(shù)量變化趨勢 科學(xué)研究"
}
```/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation: 新研究將北極熊數(shù)量下降與氣候變化聯(lián)系起來 - TUN: Jan 31, 2025 · 多倫多大學(xué)士嘉堡分校的研究人員得出了一個令人警醒的結(jié)論,他們證實了氣候變化導(dǎo)致的海冰萎縮與哈德遜灣西部北極熊種群數(shù)量下降之間存在直接聯(lián)系。
在快速變化的北極地區(qū)建立北極熊預(yù)測模型的增量演化,Ecological …: 在這里,我們回顧了預(yù)測全球北極熊 ( Ursus maritimus ) 種群狀況變化的前兩代貝葉斯網(wǎng)絡(luò)概率模型,并根據(jù)最新的研究結(jié)果和新氣候模型的海冰預(yù)測提供了當代更新。
北極熊滅絕的科學(xué)預(yù)測和模型 - Sigma Earth: 在過去的幾十年里,科學(xué)預(yù)測和模型越來越多地警告說,如果目前的氣候變化趨勢持續(xù)下去,北極熊可能會滅絕。 本文探討了這些預(yù)測背后的技術(shù)以及對北極熊種群的結(jié)論和影響。
Thought:Action:
```
{
"action": "WebSearch",
"action_input": "北極熊種群數(shù)量變化趨勢 科學(xué)研究"
}
```/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation:
Thought:Action:
```
{
"action": "WebSearch",
"action_input": "北極熊種群數(shù)量變化趨勢 科學(xué)研究"
}
```/Users/windliang/my-project/agent-demo/plan.py:13: RuntimeWarning: This package (`duckduckgo_search`) has been renamed to `ddgs`! Use `pip install ddgs` instead.
with DDGS() as ddgs: # 使用duckduckgo_search庫
Observation:
Thought:Action:
```
{
"action": "Final Answer",
"action_input": "根據(jù)科學(xué)研究,氣候變化導(dǎo)致的海冰萎縮是影響北極熊種群數(shù)量下降的主要因素之一。多倫多大學(xué)士嘉堡分校的研究人員證實了這一點,并指出哈德遜灣西部的北極熊種群數(shù)量已經(jīng)因為海冰減少而有所下降。此外,預(yù)測模型表明,如果不采取措施減緩氣候變化,北極熊可能會面臨滅絕的風(fēng)險。"
}
```
> Finished chain.
*****
Step: 收集并分析相關(guān)科學(xué)研究數(shù)據(jù),了解北極熊種群數(shù)量變化趨勢。
Response: 根據(jù)科學(xué)研究,氣候變化導(dǎo)致的海冰萎縮是影響北極熊種群數(shù)量下降的主要因素之一。多倫多大學(xué)士嘉堡分校的研究人員證實了這一點,并指出哈德遜灣西部的北極熊種群數(shù)量已經(jīng)因為海冰減少而有所下降。此外,預(yù)測模型表明,如果不采取措施減緩氣候變化,北極熊可能會面臨滅絕的風(fēng)險。
> Entering new AgentExecutor chain...
Action:
```
{
"action": "Final Answer",
"action_input": "氣候變化通過減少棲息地和狩獵范圍、增加能量消耗以及導(dǎo)致繁殖困難等途徑,對北極熊的生存環(huán)境和行為模式產(chǎn)生了顯著影響。這些因素共同作用下,北極熊種群數(shù)量正在下降,并且有滅絕的風(fēng)險。為了保護北極熊,建議采取以下措施:1. 減少溫室氣體排放;2. 保護森林資源;3. 加強國際合作,共同應(yīng)對氣候變化問題;4. 建立保護區(qū),為北極熊提供安全的棲息地;5. 開展科學(xué)研究,監(jiān)測北極熊種群數(shù)量變化趨勢。"
}
```
> Finished chain.
*****
Step: 總結(jié)氣候變化對北極熊種群的具體影響,并提出保護建議。
Response: 氣候變化通過減少棲息地和狩獵范圍、增加能量消耗以及導(dǎo)致繁殖困難等途徑,對北極熊的生存環(huán)境和行為模式產(chǎn)生了顯著影響。這些因素共同作用下,北極熊種群數(shù)量正在下降,并且有滅絕的風(fēng)險。為了保護北極熊,建議采取以下措施:1. 減少溫室氣體排放;2. 保護森林資源;3. 加強國際合作,共同應(yīng)對氣候變化問題;4. 建立保護區(qū),為北極熊提供安全的棲息地;5. 開展科學(xué)研究,監(jiān)測北極熊種群數(shù)量變化趨勢。
> Finished chain.
最終匯總報告:
氣候變化通過減少棲息地和狩獵范圍、增加能量消耗以及導(dǎo)致繁殖困難等途徑,對北極熊的生存環(huán)境和行為模式產(chǎn)生了顯著影響。這些因素共同作用下,北極熊種群數(shù)量正在下降,并且有滅絕的風(fēng)險。為了保護北極熊,建議采取以下措施:1. 減少溫室氣體排放;2. 保護森林資源;3. 加強國際合作,共同應(yīng)對氣候變化問題;4. 建立保護區(qū),為北極熊提供安全的棲息地;5. 開展科學(xué)研究,監(jiān)測北極熊種群數(shù)量變化趨勢。總結(jié)
大模型是一個聰明的大腦,但它不會主動做什么,需要我們通過 prompt 指揮,然后它需要干什么我們幫它去做,循環(huán)往復(fù),結(jié)合起來就變成了一個 agent。

Prompt 控制 / 模塊化設(shè)計、規(guī)劃策略、工具調(diào)度 / 使用、記憶機制、控制流與反饋、Agent 協(xié)同架構(gòu)、以及工具庫可擴展性 / 安全性,這些共同決定了一個 agent 表現(xiàn)的好壞,也誕生了現(xiàn)在各種各樣的 agent 應(yīng)用。

































