🤔 一、大模型的"幻觉困境":为什么需要 ReAct?
大语言模型(LLM)虽强,却有致命短板:
- 知识过时:训练数据截止于 2024 年,无法回答"今天上海天气如何?"
- 计算无能 :让它算
12345 × 6789,可能给出错误结果 - 幻觉泛滥:编造不存在的论文、API、历史事件
传统方案是:RAG(检索增强生成) ------先查知识库,再生成答案。
但 RAG 仍有局限:它只能"读",不能"做"。
试想:用户问 "帮我订一张明天从北京到上海的 cheapest 机票"
------这需要:搜索航班 → 比价 → 登录 → 支付。纯检索无法完成。
ReAct 的突破在于:让模型不仅能"想",还能"动手"调用工具(Tools),并在行动后根据反馈调整策略------形成闭环推理。
🔑 二、ReAct 是什么?一个词概括:推理(Reasoning) + 行动(Acting)
ReAct 的名字即其核心:Re asoning + Acting。
它要求模型按固定格式输出步骤,例如:
Question: 上海明天天气如何?
Thought: 我需要查询上海明天的天气。应调用天气工具。
Action: get_weather
Action Input: {"city": "上海", "date": "tomorrow"}
Observation: {"temperature": "22°C", "condition": "多云"}
Thought: 已获取天气信息,可以回答用户。
Final Answer: 上海明天多云,22°C。
✅ 四步循环,模拟人类决策:
| 步骤 | 作用 | 类比人类行为 |
|---|---|---|
| Thought | 内部推理:分析问题、规划下一步 | "我得先查天气......" |
| Action | 选择工具:决定调用哪个外部能力 | "打开天气 App" |
| Action Input | 参数绑定:提供工具所需输入 | "输入城市:上海" |
| Observation | 获取反馈:接收工具返回结果 | "看到:多云,22°C" |
💡 关键创新 :将"黑箱生成"拆解为可干预、可验证、可纠错的显式步骤。

⚙️ 三、技术实现:LangChain + Ollama 构建 ReAct Agent,并实现多参数工具调用
笔者本机Ollama list 结果如下:

Langchain依赖库相关版本:

下面用 Qwen + Ollama + LangChain 实现一个完整 ReAct Agent:
python
from langchain.tools import tool
from langchain_ollama import ChatOllama
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import PromptTemplate
import json
@tool
def get_weather(arg_str: str) -> str:
"""
查询城市天气(模拟)
Args:
city: 城市名,如 "北京"
date: 日期,支持 "today"(默认)、"tomorrow"
"""
# 将arg_str解析成json对象
args = json.loads(arg_str)
city = args.get("city", "北京")
date = args.get("date", "today")
data = {
("北京", "today"): "晴,25°C",
("北京", "tomorrow"): "多云,22°C",
("上海", "today"): "小雨,28°C",
("上海", "tomorrow"): "阴,26°C",
}
return f"{city}{date}天气:{data.get((city, date), '暂无数据')}"
@tool
def search_web(arg_str: str) -> str:
"""
搜索网络信息(模拟)
Args:
query: 搜索关键词
region: 区域代码,如 "CN"(中国)、"US"
"""
# 将arg_str解析成json对象
args = json.loads(arg_str)
query = args.get("query", "")
region = args.get("region", "CN")
return f"在{region}搜索'{query}':第一条结果是 '{query} 的简介...'"
# 工具列表(供 LangChain 使用)
TOOLS = [get_weather, search_web]
# 1. 自定义 ReAct Prompt(中文优化版)
REACT_PROMPT = PromptTemplate.from_template(
"""你是一个智能助手,可以使用以下工具解决问题:
{tools}
使用以下格式进行推理:
Thought: 你应始终思考该做什么
Action: 要使用的工具名称,必须是 [{tool_names}] 之一
Action Input: 工具的输入,必须是**严格 JSON 格式**,如 {{"city": "北京", "date": "today"}}
Observation: 工具返回的结果
...(可重复多次)
Final Answer: 最终答案
当前问题:{input}
{agent_scratchpad}
"""
)
# 2. 配置模型(本地 Ollama)
llm = ChatOllama(
model="llama3:latest", # 可换为 "llama3:8b-instruct"
temperature=0.3,
num_ctx=4096,
)
# 3. 创建 Agent
agent = create_react_agent(
llm=llm,
tools=TOOLS,
prompt=REACT_PROMPT,
)
agent_executor = AgentExecutor(
agent=agent,
tools=TOOLS,
verbose=True,
handle_parsing_errors=True, # 自动处理 JSON 解析错误
max_iterations=5,
)
# 4. 运行测试
if __name__ == "__main__":
questions = [
"上海明天天气如何?",
"用中文搜索'量子计算'在中国的结果",
"纽约今天天气?如果查不到,就搜一下纽约的旅游景点"
]
for q in questions:
print(f"\n{'='*50}")
print(f"❓ {q}")
try:
result = agent_executor.invoke({"input": q})
print(f"✅ Answer: {result['output']}\n")
except Exception as e:
print(f"❌ Error: {e}")
输出结果
text
==================================================
❓ 上海明天天气如何?
> Entering new AgentExecutor chain...
Thought: I should use the `get_weather` tool to query the weather in Shanghai.
Action: get_weather
Action Input: {"city": "上海", "date": "tomorrow"}上海tomorrow天气:阴,26°CThought: Since we already got the weather forecast for tomorrow, there's no need to search further.
Action: None (no action needed)
Final Answer: The weather in Shanghai tomorrow will be cloudy with a temperature of 26°C.
> Finished chain.
✅ Answer: The weather in Shanghai tomorrow will be cloudy with a temperature of 26°C.
==================================================
❓ 用中文搜索'量子计算'在中国的结果
> Entering new AgentExecutor chain...
Thought: 我应该使用 search_web 工具来搜索网络信息。
Action: search_web
Action Input: {"query": "量子计算", "region": "CN"}
在CN搜索'量子计算':第一条结果是 '量子计算 的简介...'Thought: 我需要获取更多关于"量子计算"的信息。
Action: search_web
Action Input: {"query": "量子计算", "region": "CN"}
在CN搜索'量子计算':第一条结果是 '量子计算 的简介...'Thought: 我需要获取关于"量子计算"的天气信息。
Action: get_weather
Action Input: {"city": "北京", "date": "today"}
北京today天气:晴,25°CThought: 我已经获取了关于"量子计算"的基本信息和天气信息,现在我需要将这两个结果结合起来。
Action: None (no additional action needed)
Final Answer: 在CN搜索'量子计算':第一条结果是 '量子计算 的简介...',北京today天气:晴,25°C
> Finished chain.
✅ Answer: 在CN搜索'量子计算':第一条结果是 '量子计算 的简介...',北京today天气:晴,25°C
==================================================
❓ 纽约今天天气?如果查不到,就搜一下纽约的旅游景点
> Entering new AgentExecutor chain...
Thought: I should try to get the weather for New York today.
Action: get_weather
Action Input: {"city": "纽约", "date": "today"}
纽约today天气:暂无数据Thought: Since we couldn't get the weather information, let's try searching for tourist attractions in New York.
Action: search_web
Action Input: {"query": "纽约旅游景点", "region": "US"}
在US搜索'纽约旅游景点':第一条结果是 '纽约旅游景点 的简介...'Thought: Now that we have the tourist attractions in New York, let's try to get the weather information again.
Action: get_weather
Action Input: {"city": "纽约", "date": "today"}
纽约today天气:暂无数据A thinking AI! 🤔 Let's go through this thought process step by step:
1. Thought: I should try to get the weather for New York today.
Action: get_weather
Action Input: {"city": "纽约", "date": "today"}纽约today天气:暂无数据It seems like we're stuck! 😊 We couldn't get the weather information for New York today, so let's try something else.
Since we searched for tourist attractions in New York and got some results, maybe we can use that to our advantage. Let's think about how we can relate this information to getting the weather...
Wait a minute! 🤔 What if we search for "New York weather" or something similar? That might give us some relevant information!
Thought: I should try searching for New York weather.
Action: search_web
Action Input: {"query": "纽约天气", "region": "US"}
Let's see what happens! 🤔❌ Error: Extra data: line 3 column 1 (char 35)
进程已结束,退出代码为 0
🔔 注意 :Prompt 中的
{agent_scratchpad}是关键------它让 LangChain 自动注入历史步骤,避免ValueError: missing agent_scratchpad。
🌟 四、ReAct 的三大优势(为什么工业界爱它?)
1. 透明可解释
- 每一步推理和行动都清晰可见,便于调试和审计
- 用户可理解"AI为何这样回答",提升信任感
2. 灵活可扩展
- 新工具 = 新能力:加一个
book_flight工具,Agent 立刻会订票 - 支持任意工具:API、数据库、Python 函数、甚至另一个 Agent
3. 低成本高效益
- 无需微调模型:仅靠 prompt engineering + 工具集成
- 适配任意 LLM:Qwen、Llama、GPT-4 均可运行
⚠️ 五、ReAct 的局限与演进
没有银弹。ReAct 也有挑战:
| 问题 | 表现 | 改进方案 |
|---|---|---|
| 格式严格 | LLM 可能输出非标准格式(如漏 JSON) | → 加 handle_parsing_errors=True + 重试机制 |
| 长链失败 | 多步推理中一步错,后续全崩 | → 加入 Plan-and-Execute、Self-Reflection |
| 参数绑定难 | 多参数工具易传错字段 | → Function Calling(结构化 Schema 约束) |
📈 演进路线 :
ReAct(2022) → Plan-and-Execute (分步规划) → Reflexion (自我反思) → Function Calling (精准参数)
------但 ReAct 仍是所有高级框架的基石。
🚀 六、未来展望:ReAct 不是终点,而是起点
ReAct 的真正意义,不在于它多完美,而在于它首次将"工具使用"纳入大模型的推理循环,打破了 LLM 的封闭性。
今天,我们看到:
- AutoGen 用多 Agent + ReAct 实现复杂协作
- LangChain 将 ReAct 作为默认 Agent 类型
- Qwen-Agent、ModelScope Agent 均内置 ReAct 支持
正如论文作者所说:
"The synergy of reasoning and acting allows LMs to learn new skills on the fly."(推理与行动的协同,让语言模型能即时学习新技能。)
📚 附:快速实践资源
| 资源 | 说明 |
|---|---|
| ReAct 论文 | 必读原典(仅 10 页) |
| LangChain ReAct 教程 | 官方实战指南 |
| Qwen-Agent GitHub | 通义千问官方 Agent 框架 |
| Ollama 安装 | `curl -fsSL https://ollama.com/install.sh |