3.3.3 Chain of Thought:让 AI "想一想"再回答
经过本节学习,你将掌握
- Chain of Thought(CoT)的定义和原理
- 两种触发 CoT 的方式
- CoT 真正有效的场景(基于最新研究)
- 如何写出有效的 CoT 提示词
- CoT 的局限性和注意事项
什么是 Chain of Thought
Chain of Thought(思维链,简称 CoT)的核心思想是:让 AI 把推理过程写出来,而不是直接给答案。
就像数学考试要求「写出解题步骤」一样,当 AI 被要求展示思考过程时,往往能得到更准确的答案。
❌ 直接问:
这个函数的时间复杂度是多少?
✅ 用 CoT:
请分析这个函数的时间复杂度。
首先,识别代码中的循环结构;
然后,分析每个循环的执行次数;
最后,计算总的时间复杂度。核心洞见:CoT 并非万能
"Chain of Thought 主要在数学和符号推理任务上有显著效果,对其他类型任务的收益有限。" —— 2024 年论文《To CoT or not to CoT?》
这个研究结论很重要。它告诉我们:
| 任务类型 | CoT 效果 | 原因 |
|---|---|---|
| 数学计算 | ✅ 显著提升 | 需要多步推理,步骤分解有帮助 |
| 逻辑推理 | ✅ 明显提升 | 复杂逻辑需要逐步梳理 |
| 代码分析 | ✅ 有帮助 | 涉及多层嵌套和条件判断 |
| 文本生成 | ⚠️ 收益有限 | 创意任务不需要严格推理 |
| 简单分类 | ❌ 可能更慢 | 增加不必要的步骤 |
实践建议:不要对所有任务都用 CoT,只在需要推理的场景使用。
两种触发方式
方式一:魔法咒语
最简单的方式,只需在提示词末尾加一句话:
请分析这段代码的性能瓶颈。
Let's think step by step.或者中文版:
请分析这段代码的性能瓶颈。
让我们一步一步来思考。这种方式简单,但 AI 的推理步骤可能不够结构化。
方式二:显式步骤分解
更可控的方式,直接告诉 AI 该怎么分步:
请分析这段代码的性能瓶颈。
分析步骤:
1. 首先,识别代码中的循环和递归结构
2. 然后,找出可能的重复计算
3. 接着,检查数据结构的选择是否合理
4. 最后,给出优化建议及预期效果这种方式的输出更结构化,适合需要特定分析角度的场景。
差提示词 vs 好提示词
场景:分析表单验证逻辑
❌ 差提示词
这个表单验证逻辑有问题吗?
function validateForm(data) {
if (data.email && data.password && data.password.length >= 6) {
if (data.email.includes('@')) {
return true;
}
}
return false;
}问题:AI 可能只给一个笼统的结论,遗漏一些边界情况。
✅ 好提示词(使用 CoT)
请审查这个表单验证函数,检查是否有遗漏的验证场景。
function validateForm(data) {
if (data.email && data.password && data.password.length >= 6) {
if (data.email.includes('@')) {
return true;
}
}
return false;
}
分析步骤:
1. 首先,列出这个函数当前检查了哪些条件
2. 然后,思考常见的表单验证需要检查什么
3. 接着,对比找出遗漏的验证项
4. 最后,给出改进建议好提示词的 AI 输出
分析过程:
1. 当前检查的条件:
- email 存在且非空
- password 存在且非空
- password 长度 >= 6
- email 包含 @ 符号
2. 常见表单验证需要检查:
- email 格式完整性(@前后都要有内容,要有域名后缀)
- password 强度(大小写、数字、特殊字符)
- 防止 SQL 注入和 XSS
- 空白字符处理
3. 遗漏的验证项:
- email 格式不完整:"@" 或 "a@" 或 "@b" 都能通过
- password 只检查长度,没检查强度
- 没有处理首尾空格
- 没有验证 email 的域名后缀(如 .com)
4. 改进建议:
- 使用正则表达式验证 email 格式
- 添加密码强度检查
- 对输入做 trim() 处理适用场景决策表
| 场景 | 是否使用 CoT | 理由 |
|---|---|---|
| 计算时间/空间复杂度 | ✅ 使用 | 需要分析循环嵌套 |
| 审查代码逻辑 | ✅ 使用 | 需要考虑多个分支和边界 |
| 设计数据库表结构 | ✅ 使用 | 需要分析实体关系 |
| 调试错误原因 | ✅ 使用 | 需要逐步排查 |
| 简单代码格式转换 | ❌ 不用 | 直接转换即可 |
| 写一段文案 | ❌ 不用 | 创意任务不需要严格推理 |
| 重命名变量 | ❌ 不用 | 任务过于简单 |
实战示例:待办清单项目
小李想让 AI 帮他分析一个 Bug:任务删除后,有时候页面没有更新。
CoT 提示词
我的待办清单应用有一个 Bug:删除任务后,页面有时候不更新。
以下是相关代码:
// 任务列表状态
const [tasks, setTasks] = useState([]);
// 删除任务
const deleteTask = (id) => {
tasks.splice(tasks.findIndex(t => t.id === id), 1);
setTasks(tasks);
}
请帮我分析问题原因。
分析步骤:
1. 首先,理解 React 状态更新的机制
2. 然后,检查这段代码的状态更新方式
3. 接着,找出导致不更新的原因
4. 最后,给出修复方案AI 输出
分析过程:
1. React 状态更新机制:
React 通过对比新旧状态的引用来决定是否重新渲染。
如果状态对象的引用没变,React 认为状态没有改变。
2. 当前代码的问题:
- splice() 直接修改了原数组
- setTasks(tasks) 传入的还是同一个数组引用
- React 对比发现引用相同,不触发重新渲染
3. 问题根因:
直接修改原数组(mutation)而非创建新数组(immutation)
4. 修复方案:
使用 filter 创建新数组:
const deleteTask = (id) => {
setTasks(tasks.filter(t => t.id !== id));
}
或者使用展开运算符:
const deleteTask = (id) => {
const newTasks = [...tasks];
newTasks.splice(newTasks.findIndex(t => t.id === id), 1);
setTasks(newTasks);
}Concise CoT:简洁版
如果你希望节省 token,可以用简洁版 CoT:
请简要分析这个函数的时间复杂度,用 2-3 句话说明推理过程,然后给出结论。研究表明,Concise CoT 可以减少约 50% 的输出长度,同时保持大部分推理准确性。
CoT 的局限性
| 局限 | 表现 | 应对方法 |
|---|---|---|
| 增加输出长度 | Token 消耗增加 20-80% | 用 Concise CoT 或限制字数 |
| 某些任务反而变差 | 简单任务强行分步可能出错 | 根据场景选择是否使用 |
| 推理可能出错 | 某一步错了,后续全错 | 配合 Self-Critique 检查 |
可复制模板
代码分析 CoT 模板
markdown
请分析以下代码的 [分析目标:性能/安全性/可维护性]:
[代码]
分析步骤:
1. 首先,[第一步分析角度]
2. 然后,[第二步分析角度]
3. 接着,[第三步分析角度]
4. 最后,给出结论和建议问题排查 CoT 模板
markdown
问题描述:[问题现象]
相关代码/配置:
[代码或配置]
请帮我分析问题原因。
排查步骤:
1. 首先,理解正常情况下应该如何工作
2. 然后,检查当前代码的执行流程
3. 接着,定位可能导致问题的环节
4. 最后,给出修复方案简洁 CoT 模板
markdown
请分析 [任务]。
用 2-3 句话说明你的推理过程,然后给出结论。本节要点
✓ CoT 的本质:让 AI 展示推理过程,而非直接给答案
✓ 有效场景:数学计算、逻辑推理、代码分析、问题排查
✓ 两种触发方式:魔法咒语(简单)vs 显式步骤分解(可控)
✓ 不要滥用:简单任务不需要 CoT,反而会降低效率
✓ Concise CoT:在需要节省 token 时使用简洁版
下一节,我们学习如何让 AI 探索多条路径——Tree of Thoughts。
