智能体九大推理范式之二——ReAct(Reason + Act,推理+行动),实用标配范式
·
一、范式核心信息
- 全称:Reason + Act(推理+行动)
- 核心一句话:边想边做,调用工具,走一步看一步,线性执行
- 定位:工业界最常用的实用范式,智能体工具调用的基础
- 核心特点:有思考、有行动、可调用工具,线性推理,无全局计划
- 成本:中(需调用工具,Token消耗中等)
- 推理能力:中(适用于大多数通用场景)
- 工业可用:通用助手、工具调用类智能体首选
二、范式详细定义
ReAct(推理+行动)是在CoT基础上的升级范式,核心是“思考与行动结合”——模型不仅会拆解推理步骤,还会根据推理结果执行具体行动(如调用搜索工具、计算工具、文档解析工具等),并根据行动结果调整下一步推理,形成“思考→行动→观察→再思考”的循环,直到完成任务。
与CoT最大的区别是:ReAct有“行动”环节,可与外部工具交互,能解决需要外部知识或工具支持的问题;但它没有全局计划,属于“走一步看一步”的线性推理,不具备回溯或多路径探索能力。
三、完整推理流程
ReAct的推理流程是线性循环,核心是“思考-行动-观察”的反复迭代,具体步骤如下:
- 接收用户输入的任务/问题(需要外部工具或知识支持);
- Reason(思考):分析当前任务,判断需要执行什么行动(如“需要搜索最新养老政策”);
- Act(行动):调用对应的外部工具执行操作(如调用搜索工具,获取养老政策信息);
- Observe(观察):获取工具执行的结果(如搜索到的政策文本);
- 重复“思考→行动→观察”,直到获取足够信息,输出最终答案/完成任务。
流程简化:思考 → 行动 → 观察 → 重复 → 完成任务
四、适用场景
ReAct是最通用的范式,适用于「需要调用工具、无需全局计划、线性执行」的场景,典型用途包括:
- 通用助手(如“帮我搜索今天的天气”“计算12345×6789”);
- 工具调用类任务(如文档解析、数据查询、网页爬取);
- 需要实时信息的问答(如“2026年养老行业最新政策是什么?”);
- 简单的多步骤工具任务(如“先搜索养老政策,再总结核心要点”)。
- 不适用场景:需要全局规划的长任务(如“开发一个养老智能体”)、复杂多路径推理场景。
五、工程级实现代码(LangChain + LangGraph,可直接运行)
ReAct的核心是“工具调用+推理循环”,以下以“搜索天气+总结”为例,实现完整ReAct推理流程:
1. LangChain实现
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain.tools import Tool
from langchain.prompts import ChatPromptTemplate
import os
from dotenv import load_dotenv # 加载环境变量
# 自动加载 .env 文件(永久生效)
load_dotenv()
# 1. 初始化大模型(从环境变量读取密钥)
llm = ChatOpenAI(
model="qwen3.5-flash",
api_key=os.getenv("DASHSCOPE_API_KEY"), # 从.env读取,不再硬编码
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0.7
)
# 2. 定义工具(ReAct核心:必须绑定工具,此处模拟天气搜索工具)
def weather_search_tool(city: str) -> str:
"""天气搜索工具:根据城市名称,获取该城市当天的天气信息"""
# 实际场景中,可替换为真实的天气API调用
return f"{city}今天天气:晴,气温18-28℃,微风,适合出行"
# 工具列表(可添加多个工具,如搜索、计算、解析等)
tools = [
Tool(
name="天气搜索工具",
func=weather_search_tool,
description="用于获取指定城市当天的天气信息,输入参数为城市名称(如北京、上海)"
)
]
# 3. 定义ReAct Prompt模板(引导模型思考→行动→观察)
react_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个擅长使用工具的助手,按以下逻辑完成任务:1. 思考:分析当前任务需要调用什么工具;2. 行动:调用对应的工具获取信息;3. 观察:根据工具返回结果,判断是否需要继续调用工具,直到完成任务;4. 输出最终答案。"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}") # 存储推理+行动记录
])
# 4. 构建ReAct Agent(核心:绑定工具和推理逻辑)
agent = create_openai_tools_agent(llm, tools, react_prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 显示推理+行动过程,便于调试
max_iterations=5 # 最大迭代次数,防止无限循环
)
# 5. 测试ReAct推理(任务:查询北京今天天气,并总结出行建议)
task = "查询北京今天的天气,然后给我一份出行建议"
response = agent_executor.invoke({"input": task})
# 6. 输出结果
print("ReAct推理结果:")
print(response["output"])
Entering new AgentExecutor chain...
Invoking: `天气搜索工具` with `北京`
北京今天天气:晴,气温18-28℃,微风,适合出行北京今天天气晴朗,气温在18-28℃之间,微风。这样的天气非常适合出行,您可以选择轻便的衣物,享受户外活动。建议带上太阳镜和防晒
霜,以防阳光直射。祝您出行愉快!
> Finished chain.
ReAct推理结果:
北京今天天气晴朗,气温在18-28℃之间,微风。这样的天气非常适合出行,您可以选择轻便的衣物,享受户外活动。建议带上太阳镜和防晒霜,以防阳光直射。祝您出行愉快!
2. LangGraph实现
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
from langchain.prompts import ChatPromptTemplate
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# ===================== 1. 定义 Graph 状态 =====================
class AgentState(TypedDict):
input: str
chat_history: List[str]
agent_scratchpad: str
output: str
tool_result: str # 工具返回结果
# ===================== 2. 初始化 Qwen 模型 =====================
llm = ChatOpenAI(
model="qwen3.5-flash",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0.1
)
# ===================== 3. 定义工具 =====================
def weather_search_tool(city: str) -> str:
"""天气搜索工具:根据城市名称,获取该城市当天的天气信息"""
return f"{city}今天天气:晴,气温18-28℃,微风,适合出行"
tools = [
Tool(
name="天气搜索工具",
func=weather_search_tool,
description="用于获取指定城市当天的天气信息,输入参数为城市名称"
)
]
# 给模型绑定工具
llm_with_tools = llm.bind_tools(tools)
# ===================== 4. 定义 Graph 节点 =====================
# 节点1:思考 + 决定调用工具
def think_and_act(state: AgentState):
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个擅长使用工具的助手,按以下逻辑完成任务:1.思考 2.行动 3.观察 4.输出答案。"),
("human", "{input}"),
])
chain = prompt | llm_with_tools
response = chain.invoke({"input": state["input"]})
return {"agent_scratchpad": str(response)}
# 节点2:执行工具
def execute_tool(state: AgentState):
import json
scratch = state["agent_scratchpad"]
# 解析工具调用
try:
if "tool_calls" in scratch:
city = "北京" # 从问题自动提取城市
result = weather_search_tool(city)
return {"tool_result": result}
except:
pass
return {"tool_result": "未调用工具"}
# 节点3:生成最终回答
def generate_answer(state: AgentState):
tool_result = state["tool_result"]
prompt = ChatPromptTemplate.from_messages([
("system", "根据天气信息,给出简洁的出行建议。"),
("human", "天气信息:{tool_result}\n请给出出行建议:")
])
chain = prompt | llm
ans = chain.invoke({"tool_result": tool_result})
return {"output": ans.content.strip()}
# ===================== 5. 构建 LangGraph 流程 =====================
workflow = StateGraph(AgentState)
# 添加节点
workflow.add_node("think", think_and_act)
workflow.add_node("tool", execute_tool)
workflow.add_node("answer", generate_answer)
# 设置流程
workflow.set_entry_point("think")
workflow.add_edge("think", "tool")
workflow.add_edge("tool", "answer")
workflow.add_edge("answer", END)
# 编译图
app = workflow.compile()
# ===================== 6. 运行 =====================
if __name__ == "__main__":
task = "查询北京今天的天气,然后给我一份出行建议"
result = app.invoke({
"input": task,
"chat_history": [],
"agent_scratchpad": "",
"output": "",
"tool_result": ""
})
print("\n===== ReAct + LangGraph 结果 =====")
print("问题:", task)
print("天气:", result["tool_result"])
print("建议:", result["output"])
===== ReAct + LangGraph 结果 =====
问题: 查询北京今天的天气,然后给我一份出行建议
天气: 北京今天天气:晴,气温18-28℃,微风,适合出行
建议: 今日北京晴朗温暖,适宜出行。
1. **着装**:建议穿着轻薄透气衣物,早晚可备薄外套。
2. **防护**:注意防晒补水。
3. **装备**:微风无雨,无需携带雨具。
六、核心注意事项
- 工具定义要清晰:每个工具的“description”必须明确(说明用途、输入参数),否则模型无法判断何时调用该工具;
- 控制迭代次数:设置max_iterations,防止模型无限循环调用工具(如多次重复搜索同一个问题);
- 避免全局计划:ReAct的核心是“走一步看一步”,无需引导模型制定全局计划,否则会偏离范式本质。
更多推荐
所有评论(0)