在人工智能快速演进的今天,如何让大语言模型(LLM)真正“动”起来,而不只是停留在文本生成的层面,成为了开发者们关注的焦点。ReAct(Reasoning + Acting)范式正是打通这一瓶颈的关键桥梁。本文将带你深入理解ReAct的工作原理,并手把手指导你完成核心代码的编写,帮助你构建属于自己的第一个智能体。
什么是ReAct?—— 思考与行动的协奏曲
ReAct是一种将推理(Reasoning)与行动(Acting)深度融合的智能体设计范式。它打破了传统大模型“输入-输出”的线性局限,引入了一个动态的循环决策机制。在这个机制中,模型的每一次决策都基于对当前环境的观察和历史经验的积累。
这种范式与人类解决问题的过程高度相似。例如,当我们在编程时,无论是使用Python、JavaScript还是TypeScript,都会先分析需求(思考),然后编写代码(行动),最后根据运行结果(观察)来调整代码。ReAct正是将这一套逻辑抽象成了通用的智能体工作流。
其核心价值在于:思考指导行动,行动修正思考。通过这种相互促进的循环,模型能够处理复杂的、需要多步骤推理的任务,并且其决策过程具有很高的可解释性。
ReAct工作流程:三步循环的精密协作
ReAct的每一步迭代都遵循一个固定的“三步曲”,这三个步骤循环往复,直至任务完成。让我们拆解这个流程,看看每一步具体在做什么。
- Thought(思考) :这是智能体的“内心独白”阶段。它会分析当前面临的情况,将复杂任务分解为若干子任务,制定下一步的具体行动计划,或者反思上一步行动的结果是否合理。
- Action(行动) ⚡:这是智能体将思考转化为实际行动的阶段。它通常会决定调用一个外部工具来获取信息或执行操作,例如进行网络搜索、查询数据库或运行一段代码。这个工具调用在代码层面通常表现为一个函数调用,其参数由模型根据思考内容生成。
- Observation(观察) :这是智能体接收外部世界反馈的阶段。在执行行动之后,它会获取到工具返回的结果,例如搜索到的网页摘要、API返回的JSON数据或代码的执行日志。
这个循环的巧妙之处在于,每次循环结束后,新的“观察”结果都会被追加到模型的上下文中。这就像给智能体增加了“记忆”,使得它在进行下一轮“思考”时,能够参考之前所有轮次的信息,形成一个不断增长的决策依据链,直到它认为答案已经足够完善,才会输出最终结果。
编码实现准备:搭建你的开发环境
理论讲得再多,不如动手实践。接下来,我们将进入编码环节。本文的示例将以Python语言为主,因为其生态最为丰富。不过,ReAct模式本身是语言无关的,如果你擅长Java、C++或TypeScript,完全可以将其核心逻辑移植过去,因为核心思想都是通用的。
首先,请确保你的本地环境满足以下要求:
- ✅ Python版本:建议使用 3.10 或更高版本,以享受最新的语法特性支持。
- ✅ 核心依赖库:需要安装
openai库(用于与大语言模型交互)和python-dotenv库(用于安全管理API密钥,避免硬编码泄露风险)。
在终端中执行以下命令来安装所需的库:
pip install openai python-dotenv
为了让代码更具通用性和安全性,我们不应将敏感信息(如API密钥)硬编码在代码中。推荐的做法是使用环境变量进行配置。在项目根目录下创建一个 .env 文件:
.env在该文件中,我们定义模型服务的核心配置。这里灵活度很高,你可以将其指向OpenAI官方服务,也可以指向任何兼容OpenAI接口的第三方或本地部署服务(如Ollama、vLLM等),只需修改对应的BASE_URL即可。
# .env file
#使用deepseek
LLM_API_KEY="YOUR-API-KEY"
LLM_MODEL_ID="YOUR-MODEL"
LLM_BASE_URL="YOUR-URL"
⚙️ 构建LLM客户端与工具定义
为了让代码结构更清晰、更易于维护和扩展,我们定义一个专属的LLM客户端类。这个类将负责封装所有与底层模型服务交互的细节,比如处理请求头、超时重试、解析响应等。这样,我们的主逻辑代码就可以更专注于智能体本身的构建,而不必关心网络通信的繁琐细节。
import os
from openai import OpenAI
from dotenv import load_dotenv
from typing import List, Dict
# 加载 .env 文件中的环境变量
load_dotenv()
class HelloAgentsLLM:
"""
为本书 "Hello Agents" 定制的LLM客户端。
它用于调用任何兼容OpenAI接口的服务,并默认使用流式响应。
"""
def __init__(self, model: str = None, apiKey: str = None, baseUrl: str = None, timeout: int = None):
"""
初始化客户端。优先使用传入参数,如果未提供,则从环境变量加载。
"""
self.model = model or os.getenv("LLM_MODEL_ID")
apiKey = apiKey or os.getenv("LLM_API_KEY")
baseUrl = baseUrl or os.getenv("LLM_BASE_URL")
timeout = timeout or int(os.getenv("LLM_TIMEOUT", 60))
if not all([self.model, apiKey, baseUrl]):
raise ValueError("模型ID、API密钥和服务地址必须被提供或在.env文件中定义。")
self.client = OpenAI(api_key=apiKey, base_url=baseUrl, timeout=timeout)
def think(self, messages: List[Dict[str, str]], temperature: float = 0) -> str:
"""
调用大语言模型进行思考,并返回其响应。
"""
print(f" 正在调用 {self.model} 模型...")
try:
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=temperature,
stream=True,
)
# 处理流式响应
print("✅ 大语言模型响应成功:")
collected_content = []
for chunk in response:
content = chunk.choices[0].delta.content or ""
print(content, end="", flush=True)
collected_content.append(content)
print() # 在流式输出结束后换行
return "".join(collected_content)
except Exception as e:
print(f"❌ 调用LLM API时发生错误: {e}")
return None
# --- 客户端使用示例 ---
if __name__ == '__main__':
try:
llmClient = HelloAgentsLLM()
exampleMessages = [
{"role": "system", "content": "You are a helpful assistant that writes Python code."},
{"role": "user", "content": "写一个快速排序算法"}
]
print("--- 调用LLM ---")
responseText = llmClient.think(exampleMessages)
if responseText:
print("\n\n--- 完整模型响应 ---")
print(responseText)
except ValueError as e:
print(e)
如果说大语言模型是智能体的“大脑”,那么工具(Tools)就是其与外部世界交互的“手和脚”。在ReAct范式中,工具是连接模型与现实世界的桥梁。为了让智能体能够真正解决我们设定的实际问题,它必须具备调用外部工具的能力。
实践建议:在定义工具时,建议使用清晰的函数名和详细的文档字符串(Docstring)。因为大语言模型是通过函数的名称和描述来理解工具用途的,描述越清晰,模型调用工具的准确性就越高。例如,你可以定义一个 search_web(query) 函数,其描述为“搜索互联网并返回相关结果摘要”。
[AFFILIATE_SLOT_1]
在实际开发中,工具可以是任何API调用:查询天气、计算数学表达式、操作文件系统,甚至是调用另一个机器学习模型。你可以根据任务需求,为智能体配备不同的“工具包”。
深入思考:ReAct的变体与延伸
ReAct并非唯一的智能体范式,但它为后续更复杂的设计奠定了基础。理解ReAct之后,你会发现许多现代框架(如LangChain、AutoGPT)的核心思想都源于此。
⚠️ 注意事项:虽然ReAct很强大,但它也有局限性。例如,在“思考”和“行动”之间切换会消耗大量的Token,导致成本增加和响应延迟。此外,如果模型的推理能力不足,可能会陷入“思考-行动-观察”的死循环中。因此,在设计智能体时,设置最大迭代次数是一个很好的防御性编程习惯。
为了优化性能,业界也衍生出了多种变体,例如:
- ReAct + 反思(Reflexion):在失败后增加一个自我反思的步骤,总结经验教训,以便在未来的尝试中避免类似错误。
- Plan-and-Execute:先制定一个完整的执行计划,然后逐步执行,而不是每一步都进行深度推理,这适合处理步骤明确的任务。
这些变体本质上都是在“思考”和“行动”的频率与深度上做文章,以适应不同的应用场景。掌握ReAct,就等于掌握了理解这些高级范式的基础钥匙。
总结与展望
本文详细拆解了ReAct范式的核心工作流程(思考-行动-观察),并通过Python代码示例演示了如何搭建环境、配置模型以及定义工具。ReAct通过将大模型的推理能力与外部工具的行动能力相结合,极大地拓展了AI的应用边界。从简单的信息查询到复杂的自动化任务,ReAct提供了一套清晰、可解释的实现路径。
实践建议:不要只停留在阅读,打开你的IDE,尝试将上述代码片段组合起来,运行一个简单的Demo。你可以从一个“计算器”或“搜索助手”开始,逐步增加工具的复杂度,体会智能体行为的变化。无论你使用的是Python、JavaScript还是TypeScript,动手实践都是掌握这项技术的最佳途径。
[AFFILIATE_SLOT_2]
浙公网安备 33010602011771号