跳转到内容

9.2.3 链式推理策略

  • 理解链式推理策略为什么会提升多步任务表现
  • 理解 CoT 适合什么任务,不适合什么任务
  • 通过可运行示例理解“直接答”和“分步答”的差别
  • 理解生产环境里怎样使用结构化推理,而不是无节制长文本

为什么“先想步骤”会有帮助?

Section titled “为什么“先想步骤”会有帮助?”

例如这道题:

  • 支持队列里有 18 张未处理工单,其中 4 张是需要合并的重复工单,然后又来了 7 张紧急工单,最后需要分诊多少张?

如果模型直接生成答案, 它可能会犯很典型的错误:

  • 把重复工单当成新增工单,而不是先去掉
  • 漏掉后面新来的紧急工单
  • 步骤顺序搞错

而如果它先把过程拆开:

  1. 18 - 4 = 14
  2. 14 + 7 = 21

最终答案通常会更稳定。

CoT 的核心不是“写很多字”,而是“暴露中间结构”

Section titled “CoT 的核心不是“写很多字”,而是“暴露中间结构””

这一点特别重要。 链式推理真正有用的地方不是:

  • 输出更长

而是:

  • 把局部事实
  • 中间变量
  • 步骤依赖

显式写出来。

一个类比:草稿便签不是为了显得认真

Section titled “一个类比:草稿便签不是为了显得认真”

运营团队复核复杂工单时写草稿便签,不是为了让答案更长, 而是为了:

  • 防止脑中状态丢失
  • 把复杂问题拆小
  • 方便检查

CoT 对模型的作用很像这一层。


先看一个“直接答”和“链式答”的对比

Section titled “先看一个“直接答”和“链式答”的对比”

下面这个例子不会调用 LLM, 但它会非常清楚地演示:

  • 为什么“直接做一个粗糙映射”容易错
  • 为什么“先拆步骤再算”更稳
import re
problem = "支持队列有18张未处理工单,4张是重复工单需要合并,然后又来了7张紧急工单,最后需要分诊多少张?"
def bad_direct_answer(text):
numbers = list(map(int, re.findall(r"\d+", text)))
open_tickets, duplicates, urgent = numbers
# 常见错误:把重复工单当成新增工单,而不是先去掉
return open_tickets + duplicates + urgent
def chain_reason_answer(text):
open_tickets, duplicates, urgent = map(int, re.findall(r"\d+", text))
steps = []
unique_tickets = open_tickets - duplicates
steps.append(f"先去掉重复工单:{open_tickets} - {duplicates} = {unique_tickets}")
final_count = unique_tickets + urgent
steps.append(f"再加上紧急工单:{unique_tickets} + {urgent} = {final_count}")
return final_count, steps
print("problem:", problem)
print("bad direct answer:", bad_direct_answer(problem))
answer, steps = chain_reason_answer(problem)
print("\nchain reasoning steps:")
for step in steps:
print("-", step)
print("final answer:", answer)

预期输出:

Terminal window
problem: 支持队列有18张未处理工单,4张是重复工单需要合并,然后又来了7张紧急工单,最后需要分诊多少张?
bad direct answer: 29
chain reasoning steps:
- 先去掉重复工单:18 - 4 = 14
- 再加上紧急工单:14 + 7 = 21
final answer: 21

它说明:

  • 直接映射很容易误解题意
  • 显式拆步骤后,错误更容易被暴露

例如这里:

  • “4 张重复工单”到底是 +4 还是 -4

只要你把这一步写出来, 错误就不容易藏起来。

为什么 CoT 常常对数学、逻辑、规划类任务特别有用?

Section titled “为什么 CoT 常常对数学、逻辑、规划类任务特别有用?”

因为这些任务通常都具备:

  • 明确中间变量
  • 明确步骤顺序
  • 明确局部依赖

这和链式推理天然契合。

为什么 CoT 不是所有任务都该开?

Section titled “为什么 CoT 不是所有任务都该开?”

因为不是所有问题都需要分步。 例如:

  • “法国首都是哪里?”

这种问题更像检索,不需要拉长推理链。

所以 CoT 不是默认越多越好, 而是:

  • 在多步问题上更值钱

很多 Agent 任务里,CoT 不一定直接用来算数, 而是用来回答:

  • 先做什么
  • 后做什么
  • 哪一步需要工具

例如:

  1. 识别问题类型
  2. 决定先查政策还是先查库存
  3. 拿到观察后再组织结论

也可以变成更结构化的“推理槽位”

Section titled “也可以变成更结构化的“推理槽位””

在生产环境里,不一定非要让模型输出一大段自然语言思维过程。 很多系统会改成更短、更结构化的格式,例如:

  • facts
  • subtasks
  • decision
  • next_action

这类结构往往更容易:

  • 校验
  • 记录
  • 调试

一种很常见的增强方式是:

  1. 先推导
  2. 再检查关键步骤
  3. 最后输出答案

这样可以降低部分粗心错误。

链式推理与自检结构图


例如:

  • 多步计算
  • 条件筛选
  • 组合决策
  • 复杂规则判断

例如:

  • 为什么推荐这个方案
  • 为什么不能执行这个请求
  • 为什么这个回答符合规则

当系统不仅要给结论,还要给理由时, 显式中间过程很有价值。

如果问题一旦算错或判断错, 后果比较严重, 那显式步骤通常更值得。


如果问题本身不需要分步, 硬让模型输出长过程,通常只是:

  • 更慢
  • 更长
  • 更贵

推理链太长,可能自己把自己绕晕

Section titled “推理链太长,可能自己把自己绕晕”

链太长时,模型可能会出现:

  • 早期步骤对,后面漂移
  • 重复解释
  • 中间状态前后不一致

也就是说,CoT 不是无限拉长就更好。

对外展示时可能不适合原样暴露

Section titled “对外展示时可能不适合原样暴露”

在很多产品里,更合理的做法是:

  • 内部有推理结构
  • 对用户只展示精炼解释

因为用户真正需要的往往是:

  • 清晰结论
  • 必要理由

而不是冗长草稿。


下面这个示例展示一种更适合 Agent 的写法:

  • 不输出一大段自由文本
  • 而是分成固定槽位
ticket = {
"question": "退款队列有18张未处理工单,4张是重复工单需要合并,然后又来了7张紧急工单,最后需要分诊多少张?",
"policy": "重复支持工单应先合并,再进入分诊。",
}
def structured_reasoning(ticket):
facts = [
"重复支持工单应先合并,再进入分诊",
"队列先有 18 张未处理工单,去掉 4 张重复工单,再加入 7 张紧急工单",
]
calculation = ["18 - 4 = 14", "14 + 7 = 21"]
decision = "团队最后需要分诊 21 张工单。"
return {
"facts": facts,
"calculation": calculation,
"decision": decision,
}
result = structured_reasoning(ticket)
print(result)

预期输出:

Terminal window
{'facts': ['重复支持工单应先合并,再进入分诊', '队列先有 18 张未处理工单,去掉 4 张重复工单,再加入 7 张紧急工单'], 'calculation': ['18 - 4 = 14', '14 + 7 = 21'], 'decision': '团队最后需要分诊 21 张工单。'}

这种格式的优点是:

  • 更容易读
  • 更容易测
  • 更容易做后处理

误区一:CoT 就是让模型啰嗦一点

Section titled “误区一:CoT 就是让模型啰嗦一点”

不是。 核心是:

  • 把中间结构显式化

误区二:所有任务都该默认用 CoT

Section titled “误区二:所有任务都该默认用 CoT”

不对。 是否启用,要看问题是否真的多步。

误区三:有了 CoT,答案就一定可靠

Section titled “误区三:有了 CoT,答案就一定可靠”

也不对。 链式推理会提升稳定性, 但不会自动消灭所有错误。


学完这一页,至少保留这张证据卡:

任务目标
Agent 想要解决什么
计划或轨迹
推理步骤、计划、ReAct 轨迹或执行图
观察
每次操作后发生了什么变化
失败检查
虚构步骤、过时观察、循环或未经验证的结论
评估动作
与期望结果对比并修正计划

这节最重要的,不是记住 Chain-of-Thought 这个英文名, 而是建立一个实用判断:

当问题依赖多步中间状态时,让模型先显式拆步骤,往往能提升稳定性;但 CoT 的价值在于结构化中间过程,不在于无限拉长输出。

只要这层理解清楚了, 你后面再看:

  • ReAct
  • Plan-and-Execute
  • 自检与评估

都会更容易明白它们是在 CoT 之上继续做组织化。


  1. 把示例中的工单队列题换成你自己的多步运营问题,比较 bad_direct_answerchain_reason_answer
  2. 为什么说 CoT 的核心价值在“显式中间结构”而不是“输出更长”?
  3. 想一个不适合 CoT 的简单问题,解释原因。
  4. 如果你要把 CoT 用在产品里,你会更倾向自由文本还是结构化槽位?为什么?
参考实现与讲解
  1. chain 版本应该展示每个子结果,而 bad direct 版本常常会把假设或算术错误藏在最终答案里。
  2. CoT 的价值在于任务存在依赖关系,需要被显式跟踪;没有结构的长文本只是啰嗦。
  3. 像“日本首都是哪里?”这样的简单查询不需要 CoT,因为中间推理只会增加噪声和成本。
  4. 产品里通常更适合结构化槽位,因为它更容易校验、记录、评测,也更容易在必要时对用户隐藏。