用 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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…