LLM Chain-of-Thought (CoT) 完全指南:从原理到 Prompt Engineering 最佳实践
一、CoT 的本质:一句话理解
CoT 就是给模型一张草稿纸 —— 把模型的内部隐式推理,转化为外部显式推理。
LLM 是逐 token 生成的(autoregressive),每一个新 token 的概率都依赖于前面所有已生成的 token。CoT 利用这个机制,让模型先把中间推理步骤"写出来"变成 token,这些 token 留在 context 中成为后续生成的输入,相当于给模型提供了"外部工作记忆"。
Autoregressive 的意思就是:模型每次只生成一个 token,而每一个新 token 的生成都依赖于前面所有已经生成的 token。
“Auto"是"自己”,“regressive"是"回归/依赖”。合起来就是"自己依赖自己之前的输出"。
用最直观的比喻理解:想象你在一个字一个字地写一篇文章。你写下第一个字的时候,脑子里只有题目。写第二个字的时候,你看了看第一个字,然后决定第二个字写什么。写第三个字的时候,你看了前两个字… 以此类推。你 永远不会一次性写出整篇文章 ,而是每一步都根据"已经写了什么"来决定"下一个写什么"。
LLM 做的就是完全相同的事情,只不过它写的单位不是"字",而是"token"。
用数学精确描述的话,LLM 生成一个完整序列的过程,本质上是在计算一个 条件概率链 :
P(整个输出) = P(token₁) × P(token₂|token₁) × P(token₃|token₁,token₂) × ...
展开来看每一步:
第1步:模型看到 [prompt]
→ 计算 P(token₁ | prompt)
→ 采样得到 token₁
第2步:模型看到 [prompt, token₁]
→ 计算 P(token₂ | prompt, token₁)
→ 采样得到 token₂
第3步:模型看到 [prompt, token₁, token₂]
→ 计算 P(token₃ | prompt, token₁, token₂)
→ 采样得到 token₃
...如此循环,直到生成结束符 <EOS>
注意关键点: 每一步都是一次完整的 Transformer 前向传播 。模型把当前所有已知的 token(prompt + 已生成的 token)全部送进 N 层 Transformer,得到下一个 token 的概率分布,然后从这个分布中采样出一个 token。
一个具体的例子:
假设 prompt 是"法国的首都是",模型的生成过程是这样的:
输入:[法国, 的, 首都, 是]
→ Transformer 前向传播 → 下一个 token 的概率分布:
"巴" (0.92), "法" (0.03), "一" (0.01), ...
→ 采样 → "巴"
输入:[法国, 的, 首都, 是, 巴]
→ Transformer 前向传播 → 下一个 token 的概率分布:
"黎" (0.97), "塞" (0.01), ...
→ 采样 → "黎"
输入:[法国, 的, 首都, 是, 巴, 黎]
→ Transformer 前向传播 → 下一个 token 的概率分布:
"。" (0.85), "," (0.05), ...
→ 采样 → "。"
当"巴"被生成后,“黎"的概率从一个不确定的值飙升到 0.97——因为在训练数据中,“巴"后面几乎总是跟"黎”。这就是 autoregressive 的核心: 前面的输出极大地约束了后面的可能性 。
为什么理解这个概念如此重要?
因为我们今天讨论的所有 prompt engineering 技术,本质上都是在 操控这个逐步生成的过程 。
二、为什么 CoT 有效:底层原理
2.1 Transformer 的固定深度限制
Transformer 的层数 N 是一个固定的架构常数。无论问题多难,模型都只跑这 N 层就输出结果。每一层做的事情是"通过 attention 收集信息 + 通过 FFN 加工信息”,总计算深度固定为 N。
当一个任务需要的推理步骤数超过模型在 N 层内能完成的上限时,模型就会"力不从心"。这就是为什么 LLM 做简单数学很准确,但多位数乘法经常出错。
2.2 CoT 如何突破这个限制
不用 CoT 时,推理深度固定为 N 层(一次前向传播)。使用 CoT 后,每生成一步中间结果,这些 token 会成为下一次前向传播的输入 context,有效计算深度变为 K × N(K 步推理 × 每步 N 层)。
CoT 本质上是把一个固定深度的计算电路,变成了一个深度可以动态增长的计算电路。2023 年论文《Chain-of-Thought Empowers Transformers to Solve Inherently Serial Problems》从数学上严格证明了这一点。
2.3 从 Attention 机制理解
CoT 的每一步中间输出都成了后续步骤的 Key 和 Value。当模型在最后一步需要引用之前的计算结果时,它的 Query 可以直接 attend 到前面步骤中的具体数值位置。这比在隐藏层中从模糊的分布式表示中"回忆"要精确得多。
三、CoT 的三重价值
| 受益方 | 价值 | 说明 |
|---|---|---|
| 模型自身 | 扩展计算深度 | 突破固定 N 层的推理限制 |
| 开发者 | 可调试性 | 检查中间推理步骤,精确定位错误 |
| 终端用户 | 可解释性 | 看到"为什么",而不只是"是什么" |
四、CoT 的实现方式
4.1 Zero-Shot CoT
不给示例,只用一句触发语:
"Let's think step by step." ← 最经典,论文验证最有效
"请一步一步地思考这个问题。"
"Think through this carefully."
"Before answering, reason through the problem."
实战技巧:即使 prompt 主体是中文,CoT 触发语用英文往往效果更好。因为 LLM 训练数据中英文的逻辑推理文本占比远高于中文,模型对 “step by step” 的响应更强烈。
适用场景:任务种类多变,难以准备覆盖所有情况的示例时。
4.2 Few-Shot CoT
在 prompt 中给出几个"带推理过程的示例",让模型模仿:
问题:一个水池有两个进水管,A管每小时进3吨,B管每小时进5吨,
同时开两管,几小时能注满40吨的水池?
推理:
- A管速率:3吨/小时
- B管速率:5吨/小时
- 合计速率:3 + 5 = 8吨/小时
- 所需时间:40 ÷ 8 = 5小时
答案:5小时
问题:{new_question}
推理:
Few-Shot CoT 比 Zero-Shot CoT 更可靠,因为你不仅告诉模型"要推理",还展示了推理的格式和粒度。
适用场景:你能提供明确优于模型默认行为的高质量示例时。
4.3 Structured CoT(工程化 CoT)
用 XML/JSON 等结构化标签组织推理过程,方便代码解析:
请严格按以下结构输出你的分析:
<thinking>
<symptom_extraction>[提取关键症状]</symptom_extraction>
<severity_assessment>[评估严重程度]</severity_assessment>
<possible_conditions>[列出可能病症]</possible_conditions>
</thinking>
<answer>[最终答案]</answer>
适用场景:AI 应用开发中需要分别处理推理过程和最终答案时。
4.4 Thinking 模型的内置 CoT
Claude Extended Thinking、OpenAI o1/o3、Gemini Thinking Mode 等模型,在训练阶段通过强化学习(RL)专门优化了推理能力。它们自动在 thinking 块中进行深度推理,不需要手动触发 CoT。
与 Prompt-based CoT 的关键区别:
| 维度 | Prompt-based CoT | Thinking 模型 |
|---|---|---|
| 推理能力来源 | 模仿训练数据中的推理模式 | 经过 RL 专门优化的推理策略 |
| 触发方式 | 需要 prompt 中显式触发 | 自动进行 |
| 推理格式控制 | 开发者可完全控制 | 模型自主决定 |
| 推理质量 | 依赖 prompt 设计和示例质量 | 通常更强,尤其在复杂任务上 |
五、CoT Prompt Engineering 最佳实践
实践一:分离推理和最终答案
在生产环境中,推理过程需要存入日志用于调试和审计,最终答案返回给用户。必须用结构化标签分离两者:
请分析这个问题。
<thinking>
[在这里写出你的推理过程]
</thinking>
<answer>
[在这里给出最终答案]
</answer>
实践二:指定推理的维度和方向
不要只说"请推理",要给推理过程设定"路线图":
分析这段代码是否有问题。
请从以下维度逐一分析:
1. 首先检查逻辑正确性——代码是否实现了预期功能
2. 然后检查边界情况——空输入、极大值、并发等
3. 接着检查性能——时间复杂度和空间复杂度是否合理
4. 最后检查安全性——是否存在注入、越权等风险
对每个维度,先给出判断(有问题/无问题),再说明理由。
原理:如果不指定维度,模型可能在第一个发现的问题上展开大量篇幅,后面的维度因为 token 预算耗尽而被忽略。指定维度确保每个关键方面都被覆盖。
实践三:Self-Consistency(自洽性验证)
对高风险推理任务,让模型多次独立推理(需设置 temperature > 0),然后取多数答案。
核心逻辑:每次推理可能走不同的路径,但正确答案更可能被多条路径共同指向。
# 伪代码
answers = [model.generate(question, temperature=0.7) for _ in range(5)]
final_answer = majority_vote(answers)
confidence = count(final_answer) / 5
适用场景:成本翻倍但能提升 5-15% 准确率,仅用于高风险场景(医疗、金融、法律)。
实践四:给模型"反思"的机会
让模型在推理后自我检查:
第一步:写出你的推理过程和初步答案。
第二步:回顾你的推理,检查是否有以下问题:
- 是否有计算错误?
- 是否遗漏了某个条件?
- 结论是否合理?
如果发现问题,请修正并给出最终答案。
原理:反思阶段的 context 中已包含完整推理链,模型可以用新的一轮前向传播来"审视"之前的推理,类似人类做完数学题后验算。
实践五:Thinking 模型的策略调整
对 Claude Extended Thinking、OpenAI o1/o3 等 thinking 模型:
不要手动触发 CoT(“Let’s think step by step”)—— 这可能干扰模型已优化过的推理策略,反而降低效果。
要做的是清晰地描述任务和期望的输出格式:
分析以下代码中的所有安全漏洞。
对每个漏洞给出:漏洞类型、严重程度(高/中/低)、修复建议。
以 JSON 数组格式输出结果。
模型会自动在 thinking 块中做深度推理,你只需关注任务描述的清晰度。
六、Few-Shot CoT 的质量把控
6.1 差的示例比没有示例更糟糕
Few-shot 是一把双刃剑。模型通过 attention 机制进行模式匹配和复制,它不区分"好模式"和"坏模式",只会忠实模仿。
差的示例会造成三种伤害:
推理粒度天花板:示例只展示粗糙两步推理,模型也只做两步,即使问题需要五步。
推理方向误导:示例中的推理路径有跳步或逻辑漏洞,模型会学到这些坏习惯。
格式过度约束:示例全是某种特定格式,模型被锁定在该格式中,即使另一种格式更适合当前问题。
6.2 判断标准
用 Few-Shot CoT 的前提:你能提供明确优于模型默认行为的示例(如特定领域的专家级推理范例,或需要严格遵循的输出格式)。
用 Zero-Shot CoT 更适合:你不确定最优推理路径是什么,或任务种类多变。此时不给示例反而给了模型更大的自由度。
核心原则:如果你自己都不确定"标准答案的推理过程"该长什么样,就别给示例,让模型自己发挥。
6.3 如果必须用 Few-Shot,如何确保质量
推荐方法:“让模型帮你生成和筛选示例”。
- 让模型对一批问题做 Zero-Shot CoT
- 人工验证哪些推理过程是正确且高质量的
- 把验证通过的作为 Few-Shot 示例
这比从零手写示例更有效,因为模型生成的推理风格和它自己的"思维习惯"一致。
七、CoT 的局限和代价
| 代价 | 说明 |
|---|---|
| Token 消耗增加 | 中间推理步骤消耗计算资源和 API 费用,可能从 50 token 膨胀到 300-500 token |
| 延迟增加 | 更多 token = 更长生成时间,影响实时应用的用户体验 |
| 不保证正确 | 模型可以生成逻辑通顺但实际有错误的推理链(faithful reasoning 问题) |
| 简单任务可能反效果 | 对直接检索型问题,强制 CoT 浪费 token 且可能引入"想太多"的干扰 |
八、CoT 使用决策树
你在用 Thinking 模型(o1/o3、Claude Extended Thinking、Gemini Thinking)吗?
│
├── 是 → 不要手动触发 CoT
│ 专注于清晰的任务描述和输出格式
│
└── 否 → 任务需要多步推理吗?
│
├── 否 → 不用 CoT,直接回答
│ (事实检索、翻译、创意写作等)
│
└── 是 → 你有高质量的推理示例吗?
│
├── 是 → 用 Few-Shot CoT
│ + 指定推理维度
│ + 分离 thinking 和 answer
│
└── 否 → 用 Zero-Shot CoT
("Let's think step by step")
│
└── 是高风险场景吗?
│
├── 是 → 加上 Self-Consistency
│ + 反思检查
│
└── 否 → 基础 CoT 即可
九、与 Prompt Engineering 其他技术的关系
CoT 不是孤立的技术,它与 Prompt Engineering 的其他核心技术协同工作:
Clear Instructions + CoT:指定推理维度就是 Clear Instructions 在 CoT 场景中的应用。
Few-Shot + CoT:Few-Shot CoT 是 Few-Shot 和 CoT 的自然结合——示例中不仅展示输入输出,还展示推理过程。
CoT + 分隔符:用 XML 标签分离推理和答案,是分隔符技术在 CoT 场景中的应用。
CoT 与 Context Engineering 的关系:CoT 生成的推理 token 会占据 context window 空间。在 agent 长期运行的场景中,需要对历史推理过程进行压缩或摘要,避免 context window 溢出。这是 Context Engineering 的核心挑战之一。
十、关键论文参考
- Chain-of-Thought Prompting Elicits Reasoning in Large Language Models (Wei et al., 2022) - CoT 的奠基论文
- Large Language Models are Zero-Shot Reasoners (Kojima et al., 2022) - 发现 “Let’s think step by step” 的有效性
- Self-Consistency Improves Chain of Thought Reasoning (Wang et al., 2023) - 多次采样取多数的方法
- Chain-of-Thought Empowers Transformers to Solve Inherently Serial Problems (Feng et al., 2023) - 从理论上证明 CoT 突破固定深度限制