ReAct 与思维链:AI 的推理模式
ReAct 和思维链(CoT)是当前 AI Agent 最核心的推理范式。本文深入解析两者的原理、区别以及如何选择合适的推理模式。
01.内容
# ReAct 与思维链:AI 的推理模式
当我们谈论 AI Agent 时,核心问题只有一个:AI 如何推理?
传统聊天机器人只是「输入→输出」的单向映射,而 Agent 的关键在于能够多步思考、持续推理、动态调整。这个能力的基础就是各种推理模式,其中最核心的两个范式是 思维链(Chain of Thought, CoT) 和 ReAct(Reasoning + Acting)。
本文将深入解析这两种推理模式的原理、实现方式以及适用场景。
02.1. 思维链(Chain of Thought)
1.1 什么是思维链?
思维链(CoT)是一种让 AI 在给出最终答案前,先展示推理过程的技术。它的核心思想是:与其直接给出答案,不如让模型把思考过程「说出来」。
没有思维链:
用户: 25 * 4 + 10 = ?
AI: 110有思维链:
用户: 25 * 4 + 10 = ?
AI: 先算 25 * 4 = 100,再算 100 + 10 = 110。所以答案是 110。看似简单的一个变化,却带来了惊人的效果提升。研究表明,CoT 能让大语言模型在数学、逻辑、代码等任务上的性能提升 50% 以上。
1.2 思维链的原理
为什么「说出思考过程」能提升 AI 的能力?这里有几个关键原因:
1. 分布式的计算压力
将复杂问题拆解为多个简单步骤,每个步骤只需少量 Token 就能准确处理。这避免了「一步到位」时需要同时考虑所有因素的认知压力。
2. 中间结果的可追溯性
当 AI 说出「先算 25 * 4 = 100」时,这个中间结果成为了下一步推理的锚点。后续推理可以在这个锚点基础上继续,而不是从头开始。
3. 自我纠错的可能性
如果推理过程中间出现错误,模型可以回头检查中间步骤,发现矛盾点并尝试修正。这是单纯「输入→输出」模式做不到的。
1.3 思维链的实现方式
思维链的实现主要有三种方式:
(1)Few-shot 示例引导
在提示词中给出几个「思考过程」的例子,让模型模仿:
prompt = """
问题:小明有 5 个苹果,小红给了他 3 个,小明吃了 2 个,现在有多少个?
思考过程:
1. 小明原来有 5 个苹果
2. 小红给了他 3 个,5 + 3 = 8
3. 小明吃了 2 个,8 - 2 = 6
答案:6 个
问题:如果每袋子里有 12 个苹果,小明买了 3 袋子,又买了 2 个散装的,现在有多少个?
思考过程:
"""(2)显式引导词
简单加一句「让我们一步步思考」:
问题:如果列文虎克最早发现的细菌是 1676 年,而青霉素是 1928 年发现的,两者相差多少年?
让我们一步步思考。这种简单的话语就能触发模型的 CoT 模式,效果出乎意料地好。
(3)结构化思维链
对于复杂推理,可以强制模型按固定格式输出:
请按以下格式回答:
1. 理解问题:...
2. 分析条件:...
3. 推导过程:...
4. 得出结论:...1.4 思维链的适用场景
思维链特别适合以下场景:
- •数学计算:需要逐步推导的任务
- •逻辑推理:涉及条件判断、因果关系的任务
- •代码生成:需要理解问题→分析→实现的流程
- •复杂决策:需要权衡多个因素的决策
1.5 思维链的局限性
思维链不是万能的:
- •对模型规模有要求:一般需要 30B 参数以上的模型才能稳定触发 CoT
- •可能产生幻觉:推理步骤越多,中间步骤出错的可能性越大
- •不适用于简单问题:对于「今天天气怎么样」这类问题,CoT 没有意义
03.2. ReAct 范式
2.1 什么是 ReAct?
ReAct(Reasoning + Acting)由 Google 在 2022 年提出,是一种将推理和行动结合的 Agent 架构。
如果说思维链是「在心里想」,那 ReAct 就是「边想边做」:
- •Reasoning:推理当前状态,决定下一步行动
- •Acting:执行行动(通常是调用工具),获取反馈
- •Observing:观察行动结果,更新认知
- •Repeat:循环直到任务完成
2.2 ReAct 的工作流程
用户:帮我查一下今天北京的天气,如果下雨就提醒我带伞
ReAct 循环:
1. Thought:我需要先查询北京今天的天气
2. Action:调用天气 API
3. Observation:结果显示北京今天有雨,气温 15-20 度
4. Thought:根据天气结果,今天有雨,我需要提醒用户带伞
5. Action:生成提醒文本
6. Output:带伞提醒注意这个循环中的 Thought → Action → Observation 三步,每一步都是基于前一步的结果动态生成的。
2.3 ReAct vs 思维链
| 维度 | 思维链 (CoT) | ReAct |
|---|---|---|
| 核心动作 | 纯推理 | 推理 + 行动 |
| 外部交互 | 无 | 有(工具调用) |
| 反馈机制 | 无 | 有(观察行动结果) |
| 适用场景 | 封闭域任务 | 开放域任务 |
| 实现复杂度 | 简单 | 较复杂 |
关键区别:思维链是「想清楚了再做」,ReAct 是「做一做再想」。
在某些任务中,ReAct 的效果显著优于单纯的 CoT。例如在 HotpotQA(多跳问答)任务中,ReAct 的准确率比 CoT 提升了 8-10 个百分点。
2.4 ReAct 的实现
ReAct 的实现需要几个关键组件:
(1)Prompt 模板
prompt = """
你是一个智能助手,可以调用工具来完成任务。
可用工具:
- search(query): 搜索信息
- calculate(expression): 数学计算
请按照以下格式回答:
Thought: 你对当前情况的分析
Action: 你要执行的行动(如果是最终答案,输出 Finish)
Action Input: 行动的输入
Observation: 行动的结果
开始!
问题:{question}
"""(2)循环控制
def react_agent(question, max_iterations=10):
context = []
for i in range(max_iterations):
# 1. 生成 Thought + Action
response = llm.generate(context + [f"问题:{question}"])
# 2. 解析动作
thought = extract_thought(response)
action = extract_action(response)
# 3. 执行动作
if action == "Finish":
return extract_answer(response)
result = execute_tool(action)
# 4. 添加观察结果
context.append(f"Thought: {thought}")
context.append(f"Action: {action}")
context.append(f"Observation: {result}")
return "达到最大迭代次数"(3)与工具系统的集成
ReAct 的强大之处在于可以动态选择工具:
available_tools = {
"search": search_function,
"calculate": calculate_function,
"lookup": lookup_function,
"send_email": send_email_function,
}
def execute_tool(action):
tool_name, tool_input = parse_action(action)
return available_tools[tool_name](tool_input)2.5 ReAct 的进阶变体
ReAct 提出后,社区发展出多种改进版本:
(1)ReAct + CoT(CoT+ReAct)
先用 CoT 全面分析,再用 ReAct 执行:
Thought:首先让我分析这个问题...(CoT 模式)
Action:基于分析,我需要...(ReAct 模式)(2)Self-Ask
模型先自问自答,再给出最终答案:
用户:爱因斯坦什么时候出生?
Self-Ask:我应该先查一下爱因斯坦的出生日期...
Action:search("爱因斯坦 出生 日期")
Observation:1879年3月14日
回答:爱因斯坦出生于 1879 年 3 月 14 日(3)Plan-and-Solve
先制定计划,再逐步执行:
Thought:这个任务可以分成三步:1) 查天气 2) 判断是否下雨 3) 生成提醒
Action:先执行第1步
...04.3. 如何选择推理模式
3.1 决策框架
选择推理模式时,考虑以下因素:
(1)任务是否需要外部信息?
- •需要 → ReAct
- •不需要 → CoT
(2)任务是否有明确的步骤?
- •有明确步骤 → CoT 或 Plan-and-Solve
- •步骤需要动态决定 → ReAct
(3)任务是否需要工具调用?
- •需要 → ReAct
- •不需要 → CoT
(4)模型的规模?
- •大于 30B 参数 → 两者都可以
- •小于 30B 参数 → 优先 CoT(ReAct 效果不稳定)
3.2 组合使用
实际项目中,往往需要组合使用多种推理模式:
def hybrid_agent(task):
# 第一阶段:用 CoT 分析任务
analysis = cot_analyze(task)
# 第二阶段:根据分析结果选择模式
if needs_external_data(analysis):
return react_execute(analysis)
elif has_clear_steps(analysis):
return plan_execute(analysis)
else:
return cot_generate(analysis)05.4. 实战:构建一个 ReAct Agent
让我们用 LangGraph 实现一个完整的 ReAct Agent:
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain.tools import tool
@tool
def search_wiki(query: str):
"""搜索维基百科"""
# 实现搜索逻辑
return wikipedia.search(query)
@tool
def calculate(expr: str):
"""计算数学表达式"""
return eval(expr)
# 定义状态
class AgentState(dict):
question: str
thought: str
action: str
action_input: str
observation: str
answer: str
iterations: int
# 推理节点
def reason_node(state: AgentState):
llm = ChatOpenAI(model="gpt-4")
prompt = f"""
问题:{state['question']}
之前的观察:{state.get('observation', '无')}
你需要决定下一步做什么。可用工具:search_wiki, calculate
请按以下格式回答:
Thought: 你的分析
Action: 工具名 或 Finish
Action Input: 工具输入 或 最终答案
"""
response = llm.invoke(prompt)
# 解析 response...
return {"thought": thought, "action": action, "action_input": input_}
# 执行节点
def act_node(state: AgentState):
tool = get_tool(state["action"])
result = tool.invoke(state["action_input"])
return {"observation": result, "iterations": state["iterations"] + 1}
# 构建图
graph = StateGraph(AgentState)
graph.add_node("reason", reason_node)
graph.add_node("act", act_node)
graph.set_entry_point("reason")
# 添加条件边
def should_continue(state):
if state["action"] == "Finish":
return "end"
return "act"
graph.add_conditional_edges("reason", should_continue)
graph.add_edge("act", "reason")
app = graph.compile()06.5. 总结
| 模式 | 核心思想 | 适用场景 | 复杂度 |
|---|---|---|---|
| CoT | 说出推理过程 | 数学、逻辑、代码 | 低 |
| ReAct | 边想边做 | 需要工具调用的开放任务 | 中 |
| Plan-and-Solve | 先计划再执行 | 多步骤复杂任务 | 中 |
| Self-Ask | 自问自答 | 需要澄清的任务 | 低 |
理解这些推理模式,是构建高效 AI Agent 的基础。下一篇文章我们将介绍如何选择和比较不同的 LLM API——毕竟,再好的推理模式,也需要强大的模型来支撑。