用 Python 實現一個“小型 ReAct 智能體”:思維鏈 + 工具調用 + 環境交互

在大語言模型(LLM)的應用開發中,如何讓模型具備調用外部工具的能力是一個關鍵問題。我們不希望模型只是“生成答案”,而是能像一個智能體(Agent)一樣,按照推理鏈條自主決定調用搜索、計算、或數據庫查詢等工具,再結合結果給出最終答案。

本文將通過一段簡潔的 Python 代碼,演示如何實現一個迷你版的 ReAct Agent(Reasoning + Acting)。這個智能體能與用戶進行交互,自動選擇調用 Wikipedia 查詢計算器博客搜索 API 來輔助推理,并逐步生成最終答案。


1. 背景:ReAct 模式與工具調用

ReAct(Reason+Act)是一種大模型交互模式,流程大致為:

  1. Thought:模型根據問題思考下一步的策略。
  2. Action:模型選擇一個工具并傳入參數。
  3. Observation:外部環境返回結果。
  4. 循環:模型繼續思考并執行下一個動作,直到能直接給出最終答案。

這種模式能讓 LLM 從“單純生成”轉變為“與環境交互”,具備更強的可擴展性。


2. 核心代碼結構

我們先來看一段簡化的實現:

import re
import httpx
from langchain_openai import ChatOpenAIclient = ChatOpenAI(base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",api_key="<your_secret_key>",model="qwen2.5-72b-instruct"
)

這里我們使用 ChatOpenAI 封裝了一個大模型客戶端(可替換為任意兼容 OpenAI 接口的模型,例如 Qwen、GPT-4、Claude 等)。

接下來定義了一個 ChatBot 類,用于管理消息上下文:

class ChatBot:def __init__(self, system=""):self.system = systemself.messages = []if self.system:self.messages.append({"role": "system", "content": system})def __call__(self, message):self.messages.append({"role": "user", "content": message})result = self.execute()self.messages.append({"role": "assistant", "content": result})return resultdef execute(self):completion = client.invoke(input=self.messages)return completion.content

關鍵點:

  • self.messages 保存了完整的對話歷史(system prompt + user prompt + assistant response)。
  • __call__ChatBot 實例可以直接作為函數調用,便于迭代。
  • 每次執行都調用 client.invoke(),并把所有上下文交給大模型。

3. Prompt 設計:引導 LLM 遵循 ReAct 格式

prompt = """
You run in a loop of Thought, Action, PAUSE, Observation.
At the end of the loop you output an Answer
Use Thought to describe your thoughts about the question you have been asked.
Use Action to run one of the actions available to you - then return PAUSE.
Observation will be the result of running those actions.Your available actions are:calculate:
e.g. calculate: 4 * 7 / 3
Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessarywikipedia:
e.g. wikipedia: Django
Returns a summary from searching Wikipediasimon_blog_search:
e.g. simon_blog_search: Django
Search Simon's blog for that termAlways look things up on Wikipedia if you have the opportunity to do so.Example session:Question: What is the capital of France?
Thought: I should look up France on Wikipedia
Action: wikipedia: France
PAUSEYou will be called again with this:Observation: France is a country. The capital is Paris.You then output:Answer: The capital of France is Paris
""".strip()

這段 system prompt 明確規定了交互格式:

  • 模型必須先寫 Thought
  • 如果需要調用工具,則寫 Action: 工具名: 參數,然后返回 PAUSE
  • 工具執行結果會以 Observation: ... 的形式喂回給模型。
  • 最后,模型才能輸出 Answer:

通過嚴格約束,我們讓模型進入一個 循環推理-調用-觀察 的流程。


4. 動作解析與執行

利用正則表達式匹配模型輸出中的 Action:

action_re = re.compile('^Action: (\w+): (.*)$')

在主循環 query() 里:

def query(question, max_turns=5):i = 0bot = ChatBot(prompt)next_prompt = questionwhile i < max_turns:i += 1result = bot(next_prompt)print(result)actions = [action_re.match(a) for a in result.split('\n') if action_re.match(a)]if actions:# There is an action to runaction, action_input = actions[0].groups()if action not in known_actions:raise Exception("Unknown action: {}: {}".format(action, action_input))print(" -- running {} {}".format(action, action_input))observation = known_actions[action](action_input)print("Observation:", observation)next_prompt = "Observation: {}".format(observation)else:return

這里的邏輯是:

  1. 把用戶問題送進模型,獲取輸出。
  2. 如果輸出里有 Action,則調用對應工具函數。
  3. 把工具的結果作為 Observation 再送回模型。
  4. 如果模型直接輸出 Answer,就結束循環。

5. 工具實現

目前實現了三個工具:

def wikipedia(q):return httpx.get("https://en.wikipedia.org/w/api.php", params={"action": "query","list": "search","srsearch": q,"format": "json"}).json()["query"]["search"][0]["snippet"]def simon_blog_search(q):results = httpx.get("https://datasette.simonwillison.net/simonwillisonblog.json", params={"sql": """selectblog_entry.title || ': ' || substr(html_strip_tags(blog_entry.body), 0, 1000) as text,blog_entry.createdfromblog_entry join blog_entry_fts on blog_entry.rowid = blog_entry_fts.rowidwhereblog_entry_fts match escape_fts(:q)order byblog_entry_fts.ranklimit1""".strip(),"_shape": "array","q": q,}).json()return results[0]["text"]def calculate(what):return eval(what)known_actions = {"wikipedia": wikipedia,"calculate": calculate,"simon_blog_search": simon_blog_search
}
  • Wikipedia:通過官方 API 獲取搜索摘要。
  • Simon Blog Search:調用 Simon Willison 的博客 API 進行全文檢索。
  • Calculate:直接用 Python eval() 計算表達式(僅演示,實際生產中要做安全防護)。

6. 效果演示

執行:

query("What does India share borders with?")

可得到以下推理過程:

Thought: To answer this question, I need to look up information about India's geography and its neighboring countries on Wikipedia.
Action: wikipedia: India
PAUSE-- running wikipedia India
Observation: <span class="searchmatch">India</span>, officially the Republic of <span class="searchmatch">India</span>, is a country in South Asia. It is the seventh-largest country by area; the most populous country since 2023;
Thought: The provided excerpt does not contain the specific information about the countries that share borders with India. I need to refine my search to get more detailed geographical information.
Action: wikipedia: Geography of India
PAUSE-- running wikipedia Geography of India
Observation:  <span class="searchmatch">Of</span> <span class="searchmatch">India</span>. 2007. ISBN 978-81-230-1423-4. Wikimedia Commons has media related to <span class="searchmatch">Geography</span> <span class="searchmatch">of</span> <span class="searchmatch">India</span>. Singh, R.L. (1971). <span class="searchmatch">India</span> A Regional <span class="searchmatch">Geography</span>. National
Thought: The current observation still does not provide the specific information about the countries that share borders with India. I will try a more direct search to find this information.
Action: wikipedia: Borders of India
PAUSE-- running wikipedia Borders of India
Observation: The Republic <span class="searchmatch">of</span> <span class="searchmatch">India</span> shares <span class="searchmatch">borders</span> with several sovereign countries; it shares land <span class="searchmatch">borders</span> with China, Bhutan, Nepal, Pakistan, Bangladesh, and Myanmar
Answer: India shares borders with China, Bhutan, Nepal, Pakistan, Bangladesh, and Myanmar.

可以看到,模型先思考,再調用 Wikipedia API,拿到結果后生成最終答案。


7. 可擴展的方向

這個簡單的 Demo 展示了 ReAct 智能體的核心循環。在實際應用中,讀者朋友們可以進一步擴展:

  1. 增加更多工具:如數據庫查詢、文件系統、搜索引擎、第三方 API 等。
  2. 錯誤處理:對 eval() 和網絡請求增加異常捕獲和安全限制。
  3. 并行工具調用:讓模型一次調用多個工具,合并結果后繼續推理。
  4. LangChain/LangGraph 集成:結合更強的智能體框架,實現任務規劃、子任務拆解與狀態管理。

8. 總結

通過不到 200 行代碼,我們實現了一個簡潔的 ReAct 風格智能體。它展示了以下關鍵點:

  • 利用 system prompt 約束 LLM 輸出格式。
  • 通過 Action/Observation 循環 讓模型與外部環境交互。
  • 工具調用 抽象成函數,方便擴展和維護。

這類模式是構建 大模型智能體 的核心思路,未來讀者朋友們可以在此基礎上擴展成更強大的多工具、多任務智能體。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919265.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919265.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919265.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

集成電路學習:什么是SIFT尺度不變特征變換

SIFT:尺度不變特征變換 SIFT(尺度不變特征變換,Scale Invariant Feature Transform)是一種在圖像處理和計算機視覺領域廣泛應用的算法,由David Lowe在1999年提出。該算法能夠在圖像的不同尺度、旋轉和光照條件下保持特征不變性,從而提取出獨特的特征點,并用于圖像…

短視頻流量|基于Java+vue的短視頻流量數據分析系統(源碼+數據庫+文檔)

短視頻流量數據分析系統 基于SprinBootvue的短視頻流量數據分析系統 一、前言 二、系統設計 三、系統功能設計 系統功能模塊 管理員功能模塊實現 四、數據庫設計 五、核心代碼 六、論文參考 七、最新計算機畢設選題推薦 八、源碼獲取&#xff1a; 博主介紹&#xff…

【無標題】卷軸屏手機前瞻:三星/京東方柔性屏耐久性測試進展

卷軸屏手機前瞻&#xff1a;三星/京東方柔性屏耐久性測試進展卷軸屏手機的產業化突破臨近2025年全球柔性屏市場規模預計突破186億美元&#xff0c;其中卷軸屏技術正從概念走向量產。三星顯示近期宣布新一代柔性OLED面板通過50萬次折疊認證&#xff0c;日均折疊200次可使用6年以…

Git 入門指南:核心概念與常用命令全解析

Git 入門指南&#xff1a;核心概念與常用命令全解析前言一、Git相關概念1.1 工作目錄1.2 暫存區1.3 本地倉庫1.3 遠程倉庫1.3.1 首次提交到遠程倉庫提示輸入用戶名密碼1.3.2 解決方法二、Git常用命令2.1 配置命令2.1.1 查看當前 Git 配置的所有信息2.1.2 查看系統全局配置2.1.3…

懸賞任務網站源碼多平臺兼職賺錢搭建圖解

功能詳細說明 &#xff08;一&#xff09;登錄與注冊 1、登錄&#xff1a;打開系統用戶端&#xff0c;輸入已注冊的手機號和密碼進行登錄。 若為忘記密碼&#xff0c;可通過 “找回密碼” 功能&#xff0c;按提示驗證身份后重置密碼登錄。 2、注冊&#xff1a;點擊 “注冊” 按…

Node.js簡介及安裝

一、Nodejs簡介 1、核心定義 Node.js 是一個基于 Chrome V8 引擎的開源、跨平臺 JavaScript 運行時環境&#xff08;Runtime&#xff09;&#xff0c;用于在服務器端或本地運行 JavaScript 代碼。它并非編程語言、庫或框架&#xff0c;而是擴展了 JavaScript 的能力&#xff0…

KINGBASE集群日常維護管理命令總結

查看集群的狀態 [kingbasenode1 bin]$ repmgr cluster show查看守護集群狀態 [kingbasenode1 bin]$ repmgr service status查看集群的事件 [kingbasenode1 etc]$ repmgr cluster event查看集群流復制狀態 esrep#select usename,application_name,client_addr,sync_state,state,…

GoLand 調參高手都在用的配置!續集:WebStorm 飛升后,Go 開發 IDE 性能炸裂的秘密

“為什么別人的 GoLand 運行 Go 項目絲滑流暢&#xff0c;而你的卻頻繁卡頓、編譯轉圈&#xff1f;秘密就藏在這個 goland64.exe.vmoptions文件里&#xff01;作為 IDEA/PyCharm/WebStorm 調優系列的續集&#xff0c;我把我壓箱底的 ?GoLand 性能調優參數表? 分享出來—>&…

48Days-Day19 | ISBN號,kotori和迷宮,矩陣最長遞增路徑

ISBN號 ISBN號碼_牛客題霸_牛客網 算法原理 模擬&#xff0c;根據題意模擬就可以了&#xff0c;注意一下余數為10的時候要特別判斷一下是不是X就行了 代碼 import java.util.Scanner;// 注意類名必須為 Main, 不要有任何 package xxx 信息 public class Main {public stat…

Java 泛型類型擦除

&#x1f4d6; 概述 本文檔詳細解釋了 Flink 中 TypeInformation 的作用、原理和使用方法&#xff0c;幫助理解為什么 Flink 需要顯式的類型信息。 &#x1f3af; 核心問題&#xff1a;Java 泛型類型擦除 什么是類型擦除&#xff1f; Java 在編譯時會將泛型信息擦除&#xff0c…

從“寫代碼”到“定義需求”:AI編程工具如何重構軟件開發的核心流程?

從“寫代碼”到“定義需求”&#xff1a;AI編程工具如何重構軟件開發的核心流程&#xff1f; 軟件開發的核心流程正在經歷一場靜默革命。十年前&#xff0c;開發者的日常被“寫代碼”填滿——從變量定義到邏輯實現&#xff0c;每行代碼都需要手動敲擊&#xff1b;而今天&#x…

一顆TTS語音芯片給產品增加智能語音播報能力

?一顆TTS語音芯片給產品增加智能語音播報能力傳統語音播報芯片可以設置一些固定的語音片段或者內容&#xff0c;但是對于現在各種創新產品層出不窮的時代&#xff0c;傳統的語音播報芯片能力似乎有點不夠用了。而TTS語音合成芯片&#xff0c;正在逐漸登上舞臺中央。TTS語音合成…

[免費]基于Python的影視數據可視化分析系統(Flask+echarts)【論文+源碼+SQL腳本】

大家好&#xff0c;我是python222_小鋒老師&#xff0c;看到一個不錯的基于Python的影視數據可視化分析系統(Flaskecharts)&#xff0c;分享下哈。 項目視頻演示 【免費】基于Python的愛奇藝影視電影數據可視化分析系統(Flaskecharts) Python畢業設計_嗶哩嗶哩_bilibili 系統…

Three.js 材質系統深度解析

簡介 Three.js 是一個功能強大的開源 3D 圖形庫&#xff0c;廣泛應用于 Web 端的 3D 可視化開發。其材質系統是 Three.js 的核心組成部分之一&#xff0c;負責定義 3D 對象的表面外觀和渲染效果。從簡單的顏色填充到復雜的動態效果&#xff0c;材質系統為開發者提供了高度靈活…

FP16(半精度)和FP32(單精度)

FP16&#xff08;Half-Precision Floating Point&#xff0c;半精度浮點數&#xff09;是一種使用16位二進制數表示浮點數值的數據格式&#xff0c;在深度學習、圖形渲染和高性能計算中廣泛應用。其核心定義、技術特性與應用價值如下&#xff1a;一、FP16的核心定義與結構二進制…

基于Vue + Node能源采購系統的設計與實現/基于express的能源管理系統#node.js

基于Vue Node能源采購系統的設計與實現/基于express的能源管理系統#node.js

代碼管理系統簡介與部署

目錄版本控制1&#xff1a;版本控制概念2&#xff1a;版本控制的功能&#xff08;1&#xff09;檢入檢出控制&#xff08;2&#xff09;分支和合井&#xff08;3&#xff09;歷史記錄3&#xff1a;版本控制的流程&#xff08;1&#xff09;創建配置項。&#xff08;2&#xff0…

Pandas數據結構詳解Series與DataFrame

Pandas數據結構詳解&#xff1a;Series與DataFrame實戰指南 前言 Pandas是Python數據分析的核心庫&#xff0c;其強大的數據處理能力主要基于兩種核心數據結構&#xff1a;Series和DataFrame。本文將深入解析這兩種數據結構的概念、創建方式、常用屬性和方法&#xff0c;并通…

TensorRT-LLM.V1.1.0rc0:在無 GitHub 訪問權限的服務器上編譯 TensorRT-LLM 的完整實踐

一、TensorRT-LLM有三種安裝方式&#xff0c;從簡單到難 1.NGC上的預構建發布容器進行部署,見《tensorrt-llm0.20.0離線部署DeepSeek-R1-Distill-Qwen-32B》。 2.通過pip進行部署。 3.從源頭構建再部署。 在實際開發中&#xff0c;我們常常面臨這樣的場景&#xff1a;本地筆記…

完整、可落地的 Elasticsearch 拼音補全配置模板 設計方案

在中文搜索場景中&#xff0c;用戶經常使用拼音輸入&#xff08;如 “iPhone”、“pingguo”&#xff09;來搜索中文內容&#xff08;如“蘋果手機”&#xff09;。為了提升用戶體驗&#xff0c;Elasticsearch 可通過 拼音分詞器 Completion Suggester 實現 拼音補全&#xff…