概述

链式推理(Chain-of-Thought, CoT)是一种提示工程技术,通过让语言模型显式生成推理步骤来提升复杂推理任务的表现。CoT的核心洞察是:展示推理过程比直接给出答案更能激发模型的推理能力。1

核心思想:模型”思考”的方式——展示中间步骤——决定了最终答案的质量。

背景与发现

CoT的发现历程

2022年,Wei等人发现当语言模型被要求生成中间推理步骤时,在复杂推理任务上表现出显著的能力提升:

标准提示:
输入: Roger有5个网球。他又买了2罐网球,每罐3个。
      Roger现在有多少个网球?
输出: 11个

CoT提示:
输入: Roger有5个网球。他又买了2罐网球,每罐3个。
      Roger现在有多少个网球?
让我们逐步思考:
1. Roger一开始有5个网球
2. 每罐有3个网球,买了2罐
3. 新买的网球数 = 2 × 3 = 6
4. 总网球数 = 5 + 6 = 11
输出: Roger现在有11个网球。

关键发现

发现描述
规模效应CoT主要在足够大的模型(≥100B参数)上有效
任务类型对数学、代码、逻辑等任务效果显著
格式灵活推理步骤可以是自然语言、数学推导或代码
与采样互补CoT + 自我一致性可以进一步提升

理论解释

1. 外部化工作记忆

CoT有效的一个解释是:它将模型的”工作记忆”外部化到语言输出中。

# 没有CoT时,模型需要在"内部"维护中间状态
def solve_internal(model, problem):
    # 所有计算都在隐状态中进行
    return model.generate(problem)
 
# 有CoT时,中间状态被"外部化"到文本
def solve_with_cot(model, problem):
    # 中间计算结果被明确写出
    reasoning = """
    让我分析这个问题:
    1. 首先理解问题...
    2. 然后...
    """
    return model.generate(problem + reasoning)

2. 程序化推理

另一种解释将CoT视为一种”程序合成”:推理步骤定义了一个计算过程:

# CoT本质上是在生成"程序"
reasoning = """
设 x = 初始值
对每个操作:
    应用操作到 x
返回 x
"""
# 模型"执行"这个程序来得到答案

3. 隐式计算假说

研究表明,CoT可能在模型内部触发了更深的计算:

CoT不只是在输出中写步骤——它可能引导模型在内部进行更深的推理。

CoT变体

1. Few-Shot CoT

通过示例展示推理过程:

few_shot_prompt = """
示例1:
问题:小明有10个苹果,给了小红3个,又买了5个。小明有多少苹果?
推理:10 - 3 = 7,7 + 5 = 12
答案:12
 
示例2:
问题:计算 15 × 17
推理:15 × 17 = 15 × (20 - 3) = 300 - 45 = 255
答案:255
 
当前问题:
问题:{question}
推理:
"""

2. Zero-Shot CoT

通过简单的触发词激活推理能力:

def zero_shot_cot(model, question):
    # 触发词:"让我们逐步思考"
    prompt = question + "\n让我们逐步思考。"
    reasoning = model.generate(prompt)
    
    # 触发答案提取
    answer_prompt = reasoning + "\n所以答案是多少?"
    answer = model.generate(answer_prompt)
    
    return reasoning, answer
 
# 简化为:
prompt = question + "让我们逐步思考。"
response = model.generate(prompt)
# 答案包含在response中

3. 思维骨架(Skeleton-of-Thought)

针对长输出的优化,先规划骨架再展开:

def skeleton_of_thought(model, task, max_points=5):
    """
    1. 生成思维骨架
    2. 对每个骨架点进行扩展
    """
    # Step 1: 生成骨架
    skeleton_prompt = f"""
任务:{task}
请列出完成这个任务的关键步骤(不超过{max_points}个):
1. ...
2. ...
...
"""
    skeleton = model.generate(skeleton_prompt)
    
    # Step 2: 逐点扩展
    expanded_sections = []
    for point in skeleton.split('\n'):
        if point.strip():
            expansion = model.generate(f"详细说明:{point}")
            expanded_sections.append(expansion)
    
    return combine(expanded_sections)

4. 长思维链(Long CoT)

o1和R1等推理模型使用超长的内部推理链:

# 长CoT可能包含数百到数千个token的推理过程
long_cot_example = """
让我仔细分析这个问题...
 
首先,我需要理解问题的核心...
 
根据已知条件,我可以推断...
 
更仔细地考虑这个子问题...
 
实际上,我之前的分析有一个问题...
 
重新审视...
 
从另一个角度考虑...
 
综合以上分析...
 
最后,我得出结论...
"""

自我一致性(Self-Consistency)

核心思想

自我一致性通过采样多个推理路径来提升CoT的可靠性:

import torch
from collections import Counter
 
def self_consistency(model, question, n_samples=40, temperature=0.7):
    """
    自我一致性:
    1. 用CoT采样N个不同的推理路径
    2. 通过多数投票选择最终答案
    """
    answers = []
    
    for _ in range(n_samples):
        # 使用非零温度采样,生成不同的推理路径
        prompt = question + "\n让我们逐步思考。"
        response = model.generate(prompt, temperature=temperature)
        
        # 提取答案
        answer = extract_final_answer(response)
        answers.append(answer)
    
    # 多数投票
    answer_counts = Counter(answers)
    return answer_counts.most_common(1)[0][0], answer_counts

为什么有效?

问题:如果x + y = 10,x = 4,求y。

采样路径1:10 - 4 = 6,答案是6 ✓
采样路径2:10 - 4 = 6,答案是6 ✓
采样路径3:4 = 10 - y,y = 6 ✓
采样路径4:10 × 4 = 40,答案是40 ✗  ← 错误路径
采样路径5:4 + 6 = 10,答案是6 ✓

投票结果:6 (4票) > 40 (1票)
最终答案:6

实验结果

模型GSM8KSVAMPStrategyQA
GPT-3 (CoT)46.9%52.2%53.8%
GPT-3 (Self-Consistency)74.4%76.4%57.5%
提升+27.5%+24.2%+3.7%

树状思考(Tree of Thoughts)

超越线性链

当问题有多个分支决策时,线性CoT可能陷入局部最优。树状思考(ToT)维护多条推理路径:

from dataclasses import dataclass
from typing import List, Optional
import heapq
 
@dataclass
class ThoughtNode:
    text: str
    value: float
    parent: Optional['ThoughtNode'] = None
    depth: int = 0
 
class TreeOfThoughts:
    def __init__(self, model, num_branches=5, max_depth=10):
        self.model = model
        self.num_branches = num_branches
        self.max_depth = max_depth
    
    def expand_node(self, node: ThoughtNode) -> List[ThoughtNode]:
        """扩展一个思考节点"""
        prompt = f"基于以下思考,继续推理:\n{node.text}\n可能的下一个步骤是:"
        suggestions = self.model.generate(prompt, n=self.num_branches)
        
        children = []
        for suggestion in suggestions:
            value = self.evaluate(suggestion)  # 评估节点价值
            children.append(ThoughtNode(
                text=suggestion,
                value=value,
                parent=node,
                depth=node.depth + 1
            ))
        
        return children
    
    def search(self, initial_thought: str) -> str:
        """使用束搜索进行树搜索"""
        # 初始化
        frontier = [ThoughtNode(text=initial_thought, value=0.0)]
        
        while frontier and frontier[0].depth < self.max_depth:
            # 扩展所有节点
            new_frontier = []
            for node in frontier:
                children = self.expand_node(node)
                new_frontier.extend(children)
            
            # 剪枝:保留top-k
            new_frontier.sort(key=lambda x: x.value, reverse=True)
            frontier = new_frontier[:self.num_branches]
        
        # 返回最佳路径
        best = max(frontier, key=lambda x: x.value)
        return self.reconstruct_path(best)
    
    def evaluate(self, thought: str) -> float:
        """评估思考节点的价值"""
        # 可以使用价值模型或启发式评估
        return self.model.evaluate(thought)

ToT vs CoT vs BFS

特性CoTToT最佳搜索
路径数1取决于问题
回溯能力
适用场景线性推理多分支决策复杂规划
计算成本中-高

CoT的理论基础

1. 计算等价性

研究表明,经过适当prompt的LLM可以模拟任意多项式时间图灵机:

定理(CoT的计算理论):对于任意多项式时间算法 ,存在一个CoT提示,使得LLM模拟 的行为。

2. 形式语言与正则语言

CoT表达能力与形式语言理论有关:

推理任务计算复杂度LLM能力
命题逻辑P
一阶逻辑PSPACE✓ (有限上下文)
算术推理PTIME
图灵机模拟EXPTIME有限

3. 思维语言假说

一些研究者提出LLM内部有一个”思维语言”:

自然语言(输出)  ←→  思维语言(内部表示)  ←→  概念空间
     CoT                       隐式推理              知识

实践指南

CoT设计原则

  1. 分解问题:将复杂问题分解为可管理的步骤
  2. 明确中间目标:每个步骤应有清晰的子目标
  3. 保持一致性:推理风格和格式保持一致
  4. 检查点:在关键决策点添加验证
# 好的CoT设计示例
def good_cot_design(question):
    return f"""
问题:{question}
 
让我系统地分析这个问题:
 
【第一步:理解问题】
- 问题的核心是什么?
- 已知条件有哪些?
- 需要求解什么?
 
【第二步:制定计划】
- 我可以使用什么方法?
- 需要哪些公式或定理?
- 有哪些约束条件?
 
【第三步:执行计算】
[详细写出每一步计算]
 
【第四步:验证结果】
- 检查计算是否正确
- 结果是否符合常识
- 有没有遗漏的情况?
 
答案:
"""

何时使用CoT

场景推荐CoT变体
数学计算Few-Shot CoT + 精确示例
代码生成Zero-Shot CoT + “写代码”
逻辑推理ToT + 验证器
开放式问题Self-Consistency
实时响应Zero-Shot CoT

局限性与挑战

1. 推理错误传播

早期步骤的错误会传播到后续步骤:

# 错误示例
"让我计算 23 × 47:
1. 23 × 47 = 20 × 40 + 3 × 7  ← 错误分解
2. = 800 + 21 = 821           ← 错误答案
"

2. 虚假推理

模型可能生成看似合理但逻辑错误的推理:

“因为所有乌鸦都是鸟,所有黑的东西都是乌鸦…”(组合谬误)

3. 计算成本

CoT显著增加了输出长度和推理时间:

# 成本对比
no_cot_output_tokens = 50
cot_output_tokens = 500  # 10x增加

参考


相关主题

Footnotes

  1. Wei et al. “Chain-of-Thought Prompting Elicits Reasoning in Large Language Models”. NeurIPS, 2022.