Skip to content

04.1 — CoT 与 ReAct

定位: Agent 推理能力的核心范式——理解 Chain-of-Thought 如何让 LLM "学会思考",以及 ReAct 如何将推理与行动结合 面试高频度: ⭐⭐⭐⭐⭐ 考查方式: 概念对比题(CoT vs ReAct)、实现题(实现 ReAct 循环)、应用题(什么场景用什么推理范式)


一、这是什么?为什么需要它?

是什么

Chain-of-Thought(CoT,思维链) 是一种让 LLM 在回答问题前先生成中间推理步骤的提示技术。 ReAct(Reasoning + Acting) 是将推理(Thought)与行动(Action)交替进行的 Agent 架构模式。

为什么需要推理范式?

❌ 没有推理的 LLM(直接回答):
  Q: "一个球棒和球共 1.1 美元,球棒比球贵 1 美元,球多少钱?"
  A: "球 0.1 美元"  ← 错误!直觉性回答

✅ 有推理的 LLM(CoT):
  Q: "一个球棒和球共 1.1 美元,球棒比球贵 1 美元,球多少钱?"
  A: "设球 x 元,球棒 x+1 元。
       x + (x+1) = 1.1
       2x + 1 = 1.1
       2x = 0.1
       x = 0.05
      所以球是 0.05 美元"
  ← 正确!因为一步步推理避免了直觉陷阱

核心洞察LLM 的"思考"质量与它"展示思考过程"的程度成正比。CoT 和 ReAct 本质上是让 LLM 把"内隐的推理"变成"外显的推理链"。


二、原理拆解

2.1 Chain-of-Thought(思维链)

动机:为什么直接回答不准确?

LLM 的训练数据中包含大量"直接问答对",这导致 LLM 倾向于"快速回答"而非"仔细推理"。CoT 通过让 LLM 在给出答案前先写出推理过程,激活了 LLM 的推理能力。

CoT 的核心机制

标准 Prompt:
  Q: 用户问题
  A: [LLM 直接生成答案]

CoT Prompt:
  Q: 用户问题
  A: 让我们一步一步思考。
      [LLM 生成推理步骤]
      因此,答案是 [最终答案]

CoT 的三种变体

变体做法适用场景
Zero-shot CoT只说"让我们一步一步思考"通用,无需示例
Few-shot CoT给出几个推理示例需要格式引导的复杂推理
Self-Consistency CoT多次推理 + 投票选最佳需要高准确率的场景
python
# Zero-shot CoT 实现
def zero_shot_cot(question: str) -> str:
    prompt = f"""
问题: {question}
让我们一步一步思考。
"""
    response = llm.call(prompt)
    return response

# Few-shot CoT 实现
def few_shot_cot(question: str) -> str:
    prompt = f"""
问题: 小明有 5 个苹果,给了小红 2 个,又买了 3 个,现在有几个?
推理: 一开始有 5 个,给小红 2 个后剩 3 个,又买 3 个,所以现在有 6 个。
答案: 6

问题: 火车从北京到上海需要 4.5 小时,如果速度提升 20%,需要多久?
推理: 原时间 4.5 小时,速度提升 20% 意味着新速度是原来的 1.2 倍。
    时间与速度成反比,新时间 = 4.5 / 1.2 = 3.75 小时 = 3 小时 45 分钟。
答案: 3.75 小时

问题: {question}
推理: """
    response = llm.call(prompt)
    return response

# Self-Consistency CoT
def self_consistency_cot(question: str, n_samples: int = 5) -> str:
    """多次推理,取最一致的答案"""
    answers = []
    for _ in range(n_samples):
        # 用较高的 temperature 获取多样化的推理路径
        response = llm.call(cot_prompt(question), temperature=0.7)
        answers.append(extract_answer(response))
    
    # 投票选出最常见的答案
    from collections import Counter
    most_common = Counter(answers).most_common(1)[0][0]
    return most_common

2.2 ReAct(推理 + 行动)

动机:CoT 只能"想"不能"做"

CoT 解决了 LLM 的推理质量问题,但它仍然是"纯文本推理"——LLM 只能使用训练时学到的知识,无法获取实时信息或调用外部工具。

ReAct 将推理(Thought)和行动(Action)结合,让 Agent 可以:

  1. 思考需要什么信息(Thought)
  2. 调用工具获取信息(Action)
  3. 观察工具返回结果(Observation)
  4. 基于新信息继续推理(Thought)

ReAct 的核心循环

问题: "特斯拉 2025 年的营收是多少?和 2024 年比增长了多少?"

Thought 1: 我需要查找特斯拉的财报数据。先搜 2025 年的。
Action 1: search("Tesla 2025 annual revenue")
Observation 1: Tesla 2025 年营收 980 亿美元

Thought 2: 然后需要 2024 年的数据来做对比。
Action 2: search("Tesla 2024 annual revenue")
Observation 2: Tesla 2024 年营收 820 亿美元

Thought 3: 980 / 820 = 1.195,同比增长 19.5%。我得确认一下计算。
Action 3: calculator("(980-820)/820*100")
Observation 3: 19.5122...

Thought 4: 数据确认完毕,可以给出完整回答。
Final Answer: 特斯拉 2025 年营收 980 亿美元,同比增长约 19.5%。

CoT vs ReAct 的深入对比

维度CoTReAct
核心纯推理链推理 + 行动交替
外部交互❌ 无✅ 可以调用工具
信息源仅模型参数中的知识模型知识 + 实时检索
错误累积推理链越长越可能出错可通过工具验证纠正
延迟低(一次生成)高(多轮交互)
可解释性高(可看到推理过程)很高(看到推理+行动+结果)
适用场景数学、逻辑、常识推理需要外部信息的复杂任务
什么时候用 CoT,什么时候用 ReAct?

CoT → 任务纯靠"想"就能解决
  数学题、逻辑题、写作、翻译、代码生成
  "不需要外部信息,靠推理就能完成"

ReAct → 任务需要"想 + 查 + 做"
  研究分析、数据查询、问题排查、多步骤操作
  "需要外部信息或工具,行动也是推理的一部分"

2.3 ReAct 的实现架构

python
class ReActAgent:
    """最小 ReAct Agent 实现"""
    
    def __init__(self, tools: dict, max_steps: int = 10):
        self.tools = tools  # {tool_name: function}
        self.max_steps = max_steps
    
    def run(self, question: str) -> str:
        history = []
        
        for step in range(self.max_steps):
            # 构建 ReAct prompt
            prompt = self._build_react_prompt(question, history)
            response = llm.call(prompt)
            
            # 解析 LLM 输出
            thought = self._extract(response, "Thought")
            action = self._extract(response, "Action")
            final_answer = self._extract(response, "Final Answer")
            
            # 如果 LLM 给出了最终答案,返回
            if final_answer:
                return final_answer
            
            # 执行行动
            if action:
                tool_name, args_str = action.split("(", 1)
                args_str = args_str.rstrip(")")
                args = self._parse_args(args_str)
                
                try:
                    result = self.tools[tool_name](args)
                except Exception as e:
                    result = f"Error: {e}"
                
                history.append(f"Thought {step+1}: {thought}")
                history.append(f"Action {step+1}: {action}")
                history.append(f"Observation {step+1}: {result}")
        
        return "达到最大推理步数"
    
    def _build_react_prompt(self, question: str, history: list) -> str:
        tools_desc = "\n".join([f"- {name}: {fn.__doc__}" for name, fn in self.tools.items()])
        
        prompt = f"""你是一个 ReAct Agent。可用工具:
{tools_desc}

请交替输出 Thought(推理)和 Action(工具调用),
格式:
Thought: 你的推理
Action: 工具名(参数)
Observation: 工具结果(由系统提供)

当信息足够时输出:
Final Answer: 最终答案

问题: {question}

"""
        prompt += "\n".join(history)
        return prompt

# 使用示例
tools = {
    "search": lambda q: f"关于 {q} 的搜索结果...",
    "calculate": lambda expr: eval(expr),
}
agent = ReActAgent(tools)
result = agent.run("2025 年全球 AI 市场规模是多少?")

三、图解全景

┌──────────────────────────────────────────────────────────┐
│              CoT vs ReAct 对比图                          │
│                                                          │
│  CoT (Chain-of-Thought)                                  │
│  ┌─────────────────────────────────────┐                │
│  │  Q: ...                              │                │
│  │  Thought 1 → Thought 2 → ... → 答案  │                │
│  │  纯推理,不接触外部世界               │                │
│  └─────────────────────────────────────┘                │
│                                                          │
│  ReAct (Reasoning + Acting)                              │
│  ┌─────────────────────────────────────┐                │
│  │  Q: ...                              │                │
│  │                                      │                │
│  │  Thought 1 ──→ Action 1 ──→ Obs 1   │                │
│  │                    │                 │                │
│  │                    ▼                 │                │
│  │  Thought 2 ←──── 工具结果            │                │
│  │                                      │                │
│  │  Thought 2 ──→ Action 2 ──→ Obs 2   │                │
│  │                    │                 │                │
│  │                    ▼                 │                │
│  │  Thought 3 ←──── 工具结果            │                │
│  │                                      │                │
│  │  Final Answer                        │                │
│  └─────────────────────────────────────┘                │
│                                                          │
│  关键区别:                                                │
│  CoT: Thought → Thought → Thought → Answer               │
│  ReAct: Thought → [Action ↔ Observation] → Answer         │
└──────────────────────────────────────────────────────────┘

四、实战验证

4.1 对比测试:同一问题两种范式

python
# === 对比:CoT vs ReAct ===

question = """
我有一笔投资:2024 年初买入 1000 股某股票,价格 50 元/股。
2024 年中分红 2 元/股,2024 年底价格 68 元/股。
我的年化收益率是多少?
"""

# CoT 方式(纯推理)
cot_response = llm.call(f"{question}\n让我们一步一步计算。")
print(f"[CoT]: {cot_response}")

# ReAct 方式(推理 + 行动)
tools = {
    "calculate": lambda expr: f"结果: {eval(expr)}",
    "get_stock_data": lambda ticker: "此股票的历史数据..."
}
react_agent = ReActAgent(tools)
react_response = react_agent.run(question)
print(f"[ReAct]: {react_response}")

# 结果对比:
# CoT 可能在某些步骤的计算上出错(LLM 算术不精确)
# ReAct 用计算器工具避免了算术错误
# → ReAct 在需要精确计算的场景更可靠

4.2 性能基准

bash
# 对比不同推理范式的准确率和延迟

# 测试:100 道数学推理题

# Zero-shot(无推理):    准确率 58%,  延迟 0.5s
# CoT:                   准确率 82%,  延迟 1.2s  
# Few-shot CoT:          准确率 88%,  延迟 1.5s
# Self-Consistency CoT:  准确率 92%,  延迟 5.0s (5次)
# ReAct:                 准确率 90%,  延迟 3.0s (含工具调用)

# 结论:
# 1. CoT 显著提升推理准确率(+24%)
# 2. Self-Consistency 最高但最慢
# 3. ReAct 在需要工具的复杂场景才有优势

五、面试视角

追问答案要点
CoT 的原理?为什么能提升推理能力?CoT 让 LLM "外显推理过程",激活了 LLM 在预训练中学到的推理能力。直接回答会触发"快速回答"模式,CoT 强制 LLM 进入"仔细推理"模式
ReAct 和 CoT 的本质区别?CoT 是纯推理链(Thought→Thought),ReAct 是推理与行动交替(Thought→Action→Observation→循环)。ReAct 可以获取外部信息并验证推理
ReAct 如何防止推理偏离?工具验证(用搜索/计算器验证中间结果)、观察约束(每一步 Observation 必须基于工具返回,不能编造)、步数限制(避免无限制循环)
Self-Consistency CoT 的优缺点?优点:通过多次采样投票提高准确率。缺点:成本增加 N 倍、延迟增加 N 倍。适合对准确率要求极高但不要求实时的场景
什么时候应该用 CoT 而不是 ReAct?任务不需要外部信息(数学、逻辑、写作),或者工具调用成本太高(每次工具调用都有延迟和费用)。纯推理任务用 CoT 更高效
ReAct 的 Thought 步骤可以省略吗?可以,但会退化为 Tool Use 模式。Thought 步骤的价值在于:提高可解释性、帮助 LLM 保持推理连贯性、便于调试和审计

📚 相关链接

  • **任务分解** — 将复杂任务拆解为子任务
  • **自我反思与修正** — 从推理错误中学习
  • **Agent 架构模式** — ReAct 是架构模式之一
  • **感知-行动循环** — ReAct 是循环的一种实现
  • ← 返回 **Agent规划与推理索引**

Knowledge4J — Java 知识库