Chapter 02

Chain-of-Thought 工程:让模型说出思考

CoT 不只是"一句话提示词",而是一套完整的提示工程体系。掌握它,能让普通模型解决推理模型才能处理的问题。

什么是 Chain-of-Thought

2022 年 Google Brain 发表的论文证明:让模型在给出答案前先写出推理步骤,准确率会显著提高。这个简单发现催生了整个 CoT 提示工程体系。

普通提示: 问:Roger 有 5 个网球,买了 2 罐(每罐 3 个),现在有多少? 答:11 ← 直接输出,无推理 CoT 提示: 问:[同题] 请一步步思考。 答:Roger 开始有 5 个。 买了 2 × 3 = 6 个新球。 5 + 6 = 11 个。 答案是 11。 ← 推理后输出
为什么 CoT 有效?
将复杂问题分解成多个中间步骤,每个步骤都在 LLM 的能力范围内。就像人类在草稿纸上演算一样,中间步骤为下一步提供了正确的"起点"。
CoT 的规模效应
研究发现 CoT 对小模型(<10B)效果有限甚至负面,对大模型(>100B)效果显著。o1/R1 等推理模型将 CoT 能力内化为训练目标,突破了这个限制。

Zero-shot CoT:最简单的触发词

2022 年 Kojima 等人发现:在问题末尾添加 "Let's think step by step" 就能显著提升推理准确率,无需任何示例。

import anthropic

client = anthropic.Anthropic()

def zero_shot_cot(problem: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": f"{problem}\n\n请一步步思考,然后给出最终答案。"
        }]
    )
    return response.content[0].text

# 有效的 Zero-shot CoT 触发词
triggers = [
    "Let's think step by step.",          # 英文通用
    "请一步步分析这个问题。",               # 中文通用
    "Think carefully before answering.",  # 更谨慎
    "Show your reasoning process.",       # 显示过程
]

Few-shot CoT:用示例教会推理风格

当 Zero-shot CoT 不够时,提供 2-8 个带推理过程的示例,引导模型模仿你期望的推理方式:

FEW_SHOT_COT_PROMPT = """解题示例:

Q: 一个水箱可以储存 500 升水,现在已装了 60%,再装 50 升后是多少升?
A: 分析:
   当前水量 = 500 × 60% = 300 升
   加水后 = 300 + 50 = 350 升
   最终答案:350 升

Q: 一个工人每天工作 8 小时,月薪 6400 元,时薪是多少?
A: 分析:
   每月工作天数 = 22 天(标准)
   每月总工时 = 22 × 8 = 176 小时
   时薪 = 6400 ÷ 176 ≈ 36.4 元
   最终答案:约 36.4 元/小时

现在请解答:
Q: {question}
A: 分析:"""
Few-shot 示例设计原则 示例的推理风格要与你希望模型采用的格式一致。示例数量通常 3-5 个效果最好,太多会占用上下文空间。示例要覆盖不同类型的子问题。

Self-Consistency:多路径投票

单次 CoT 存在随机性。Self-Consistency(Wang et al. 2023)通过多次采样取多数票来提高可靠性:

from collections import Counter

def self_consistency(problem: str, n_samples: int = 5) -> str:
    answers = []

    for _ in range(n_samples):
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=512,
            temperature=0.7,  # 适当随机性产生多样路径
            messages=[{
                "role": "user",
                "content": f"{problem}\n\n请一步步思考。最后一行只写最终数字答案。"
            }]
        )
        text = response.content[0].text
        answer = extract_final_answer(text)  # 提取最后一行答案
        answers.append(answer)

    # 多数投票
    counter = Counter(answers)
    majority_answer = counter.most_common(1)[0][0]
    confidence = counter[majority_answer] / n_samples

    print(f"投票结果: {dict(counter)}, 置信度: {confidence:.0%}")
    return majority_answer

Tree-of-Thought:树状搜索

Self-Consistency 是并行的多路径,Tree-of-Thought(Yao et al. 2023)则是主动探索+评估+剪枝的树状搜索:

问题 │ ├─ 思路 A(LLM 评估分:7/10) │ ├─ 继续 A1(分:8/10)→ 继续展开... │ └─ 继续 A2(分:4/10)→ 剪枝,放弃 │ ├─ 思路 B(LLM 评估分:9/10)← 最优 │ └─ 继续 B1(分:9/10)→ 最终答案 │ └─ 思路 C(LLM 评估分:3/10)→ 剪枝,放弃
def tree_of_thought(problem: str, breadth: int = 3, depth: int = 3) -> str:
    # 1. 生成多个初始思路
    thoughts = generate_thoughts(problem, n=breadth)

    for step in range(depth):
        # 2. 评估每个思路的价值
        scored = [(t, evaluate_thought(problem, t)) for t in thoughts]

        # 3. 保留最高分的 top-k 思路(剪枝)
        thoughts = [t for t, s in sorted(scored, key=lambda x: -x[1])[:breadth]]

        # 4. 展开继续推理
        thoughts = expand_thoughts(problem, thoughts)

    # 返回最佳路径的答案
    return extract_best_answer(problem, thoughts)
ToT 的成本 Tree-of-Thought 需要多次 LLM 调用(breadth × depth 次),成本是普通 CoT 的 5-20 倍。仅在问题真正需要探索多条路径时才使用,例如复杂的代码规划、数学证明等。

Least-to-Most:从简到难分解

对于复杂问题,先问"要解决这个问题,需要先解决哪些子问题",然后逐步构建:

LEAST_TO_MOST = """
第一步:将问题分解为更简单的子问题。
列出所有需要先解决的子问题(从最简单开始):

问题:{problem}

子问题分解:"""

# 先获取子问题,再逐一解决,最后综合
sub_problems = get_sub_problems(problem)
solutions = [solve_sub_problem(sp) for sp in sub_problems]
final = synthesize_answer(problem, solutions)
本章小结 Zero-shot CoT 简单有效(加一句话),Few-shot CoT 教会推理风格,Self-Consistency 用投票提高可靠性,ToT 用树搜索解决复杂问题。下一章解析 DeepSeek-R1 如何用强化学习训练推理能力。