深入理解 Chain-of-Thought (CoT):让大模型学会"思考"
1. Chain-of-Thought 的引入
1.1 大模型为什么不会”思考”?
长期以来,深度学习模型在处理需要多步骤推理的任务时表现不佳:
- 简单的算术题:模型可能给出错误答案
- 复杂逻辑推理:模型常常”跳步”推理
- 多约束优化:模型难以分解问题
核心问题:
大语言模型本质上是”下一个 token 预测器”——它们直接生成答案,而不展示思考过程。
这就像一个学生不展示任何计算过程,直接写出最终答案——你无法判断他是真的理解了,还是在瞎猜。
1.2 CoT 的核心思想
Chain-of-Thought (CoT,思维链) 是 Wei et al. (2022) 在 Google Brain 提出的突破性技术:
不要直接问模型答案,而是让模型”一步一步地思考”——展示推理过程,答案自然浮现。
直觉类比:
普通提问: "12 × 15 等于多少?" 模型直接回答: "180" ← 可能是对的,也可能是错的
CoT 提问: "12 × 15 等于多少?请一步一步计算" 模型回答: "12 × 15 = 12 × 10 + 12 × 5 = 120 + 60 = 180" ← 推理过程透明,更可能正确1.3 CoT 发展简史
2020: GPT-3 时代 │ 大模型展现强大的 few-shot 能力 │ 但推理能力仍然有限 │2022.1: Chain-of-Thought Prompting (Wei et al.) │ Google Brain 首次提出 CoT 概念 │ 在算术、常识、符号推理任务上取得突破 │2022.3: Zero-Shot CoT (Kojima et al.) │ 仅用一句"让我们一步一步思考"就能激发推理 │2022.4: Self-Consistency (Wang et al.) │ 多个推理路径投票,提高鲁棒性 │2022.9: Tree of Thoughts (Yao et al.) │ 将推理组织成树形搜索 │2022.10: ReAct (Yao et al.) │ 推理 + 行动,与工具结合 │2023: Auto-CoT, Active-Prompt │ 自动选择最有信息量的演示样例 │2023-2024: CoT + 工具使用 │ Toolformer, PAL, Program-aided Reasoning │2024-2025: 多模态 CoT │ 视觉 + 语言的协同推理 │2025+: 推理模型崛起 │ OpenAI o1, DeepSeek-R1, Claude 3.7 │ CoT 训练进模型权重1.4 CoT 的革命性意义
CoT 是大模型推理能力的第一次重大飞跃:
| 维度 | 直接回答 | CoT |
|---|---|---|
| 准确率 | 中等 | 显著提升 |
| 可解释性 | 黑盒 | 推理过程透明 |
| 错误定位 | 难以调试 | 可以定位错误步骤 |
| 复杂问题 | 容易失败 | 可以分解处理 |
| 推理深度 | 浅层 | 多步骤深度推理 |
2. CoT 的核心原理
2.1 为什么 CoT 有效?
2.1.1 认知负荷理论
CoT 通过分解复杂任务来降低认知负荷:
直接回答: [困难推理 + 直接输出] └─────── 高认知负荷 ──────┐ ▼ 可能失败
CoT 分解: 步骤1: 提取关键信息 ── 低负荷 步骤2: 应用规则 ── 低负荷 步骤3: 推导中间结果 ── 低负荷 步骤4: 得出最终答案 ── 低负荷 └─────── 总负荷可管理 ──────┐ ▼ 高成功率2.1.2 显式中间表示
CoT 在回答过程中生成显式的中间 token,这些 token:
- 为后续推理提供”工作记忆”
- 引导模型走向正确答案
- 让复杂的”思维”成为可能的”思考路径”
2.1.3 计算假设
Transformer 中的 CoT 实际上相当于增加了计算深度:
想象一个 L 层 Transformer:
- 直接回答:使用 L 层计算直接预测答案
- CoT:使用 L 层生成 k 个推理 token,再用 k 层计算预测答案
- 有效计算量从 L 增加到 L + k!
2.2 CoT 的形式化定义
给定一个问题 和 few-shot 演示 ,其中 是思维链, 是最终答案。
CoT 模型生成的输出:
其中 是推理步骤, 是最终答案。
2.3 CoT 的理论基础
2.3.1 涌现能力 (Emergent Ability)
CoT 是典型的涌现能力:
- 小模型 (< 10B):CoT 几乎无效果,甚至有害
- 中等模型 (10B-50B):CoT 开始展现优势
- 大模型 (> 50B):CoT 带来巨大提升
性能提升││ ● 大模型 + CoT││ ● 大模型 (无 CoT)││ ● 小模型 + CoT ≈ 小模型 (无 CoT)│└────────────────────────────────────── 小模型 中模型 大模型2.3.2 CoT 的数学解释
从理论上讲,CoT 可以被理解为:
- 隐式计算:每个中间 token 都是一次”软计算”
- 信息瓶颈:通过中间表示将复杂问题分解
- 递归分解:每一步将问题降维
# 简化的 CoT 计算模型def cot_recursive_decomposition(problem, max_depth=5): """ CoT 作为递归问题分解 """ if max_depth == 0 or is_simple(problem): return solve_directly(problem)
# 分解问题 sub_problems = decompose(problem)
# 递归求解每个子问题 sub_answers = [] for sub_p in sub_problems: sub_answer = cot_recursive_decomposition(sub_p, max_depth - 1) sub_answers.append(sub_answer)
# 组合答案 final_answer = combine(sub_answers) return final_answer3. CoT 的基础方法
3.1 Few-Shot CoT (原始方法)
Few-Shot CoT 是 Wei et al. 提出的原始方法,通过手工设计的演示激发 CoT:
# Few-Shot CoT Prompt 示例
prompt = """问题:小明有 5 个苹果。他又买了 3 袋苹果,每袋 4 个。现在小明一共有多少个苹果?
推理:小明原来有 5 个苹果。他买了 3 袋,每袋 4 个,所以新买了 3 × 4 = 12 个苹果。总共:5 + 12 = 17 个苹果。
答案:17 个苹果
问题:一本书有 240 页。小红第一天读了 1/3,第二天读了剩下的 1/4。第三天她需要读多少页才能读完?
推理:小红第一天读了 240 × 1/3 = 80 页。剩下 240 - 80 = 160 页。第二天她读了剩下 160 × 1/4 = 40 页。最后剩下 160 - 40 = 120 页。
答案:120 页
问题:{用户问题}
推理:"""关键要素:
- 多个示例:3-8 个 few-shot 示例
- 推理过程:每个示例都有完整的思维链
- 格式一致:保持答案格式的一致性
3.2 Zero-Shot CoT (零样本)
Zero-Shot CoT 是 Kojima et al. (2022) 的重大发现:
只需要在 prompt 中加一句”让我们一步一步思考”,模型就会自动进行 CoT 推理!
# Zero-Shot CoT
prompt_direct = "12 × 15 等于多少?"# 输出: "180" (可能错误)
prompt_cot = "12 × 15 等于多少?让我们一步一步思考。"# 输出: "12 × 15 = 12 × 10 + 12 × 5 = 120 + 60 = 180" (更准确)经典触发短语:
- 中文:“让我们一步一步思考”
- 英文:“Let’s think step by step”
- “Take a deep breath and work through this step by step”
- “Think through this carefully”
3.3 对比:Few-Shot vs Zero-Shot
| 维度 | Few-Shot CoT | Zero-Shot CoT |
|---|---|---|
| 是否需要演示 | 是(3-8 个) | 否 |
| 设计成本 | 高 | 低 |
| 推理质量 | 高(取决于演示质量) | 中等 |
| 适用场景 | 生产环境 | 快速原型 |
| 灵活性 | 低(受演示影响) | 高 |
3.4 Auto-CoT (自动化)
Auto-CoT 自动选择或生成演示样例:
class AutoCoT: """ 自动思维链:自动选择/生成多样化的演示 """ def __init__(self, llm, dataset): self.llm = llm self.dataset = dataset
def sample_diverse_questions(self, n=8): """ 使用聚类选择多样化的代表性问题 """ # 1. 编码所有问题 embeddings = self.embed_questions(self.dataset.questions)
# 2. K-means 聚类 clusters = self.kmeans(embeddings, n_clusters=n)
# 3. 从每个聚类中心选择代表问题 diverse_questions = [] for cluster_id in range(n): center = clusters[cluster_id].center closest = self.find_closest_question(center, embeddings) diverse_questions.append(closest)
return diverse_questions
def generate_cot_for_question(self, question): """使用 Zero-Shot CoT 生成推理链""" prompt = f"{question}\n让我们一步一步思考。" reasoning = self.llm.generate(prompt) return reasoning
def build_prompt(self, user_question): """构建 Auto-CoT prompt""" # 选择多样化问题 diverse_qs = self.sample_diverse_questions()
# 为每个问题生成 CoT demonstrations = [] for q in diverse_qs: cot = self.generate_cot_for_question(q) demonstrations.append({ 'question': q, 'reasoning': cot })
# 构建最终 prompt prompt = self.format_demonstrations(demonstrations) prompt += f"\n问题:{user_question}\n推理:"
return prompt3.5 Self-Consistency (自一致性)
Self-Consistency 通过多次采样 + 投票提高 CoT 的鲁棒性:
class SelfConsistency: """ 自一致性:从多个推理路径中投票 """ def __init__(self, llm, num_samples=10, temperature=0.7): self.llm = llm self.num_samples = num_samples self.temperature = temperature
def generate(self, question): """生成多个推理路径并投票""" # 1. 生成多个 CoT 推理 reasoning_paths = [] for i in range(self.num_samples): prompt = self._build_prompt(question) response = self.llm.generate( prompt, temperature=self.temperature, do_sample=True ) reasoning_paths.append(self._extract_answer(response))
# 2. 多数投票 answer_counts = Counter(reasoning_paths) final_answer = answer_counts.most_common(1)[0][0]
return { 'answer': final_answer, 'reasoning_paths': reasoning_paths, 'confidence': answer_counts[final_answer] / self.num_samples }
def _extract_answer(self, response): """从响应中提取最终答案""" # 多种答案提取策略 patterns = [ r'答案是[::]\s*(.+?)(?:\n|$)', r'答案[::]\s*(.+?)(?:\n|$)', r'####\s*(.+?)(?:\n|$)', ] for pattern in patterns: match = re.search(pattern, response) if match: return match.group(1).strip() return response.strip()自一致性的优势:
- 不依赖单一推理路径:即使某个推理出错,多数投票仍能选出正确答案
- 置信度估计:可以给出答案的可信度
- 与 Temperature 配合:高 temperature 增加多样性
推理路径 1: A → B → C → 答案 X推理路径 2: A → D → E → 答案 Y ← 多数推理路径 3: A → F → G → 答案 Y ← 多数推理路径 4: A → H → I → 答案 Y ← 多数推理路径 5: A → J → K → 答案 X
多数投票结果: Y (3 票)4. 高级 CoT 方法
4.1 Tree of Thoughts (ToT)
Tree of Thoughts (ToT) 将 CoT 扩展为树形搜索:
class TreeOfThoughts: """ 树形思维:探索多个推理路径 """ def __init__(self, llm, branching_factor=3, max_depth=5): self.llm = llm self.branching_factor = branching_factor self.max_depth = max_depth self.tree = ThoughtTree()
def generate_thoughts(self, state): """在当前状态下生成多个可能的下一步""" prompt = f""" 当前状态:{state}
请提出 {self.branching_factor} 个可能的下一步推理: """ response = self.llm.generate(prompt) thoughts = self.parse_thoughts(response) return thoughts
def evaluate_state(self, state): """评估当前状态的优劣""" prompt = f""" 状态:{state}
这个状态距离最终答案有多远?评估(1-10): """ score = int(self.llm.generate(prompt).strip()) return score
def search(self, problem): """使用 BFS/DFS 搜索最佳推理路径""" # 初始化 root = ThoughtNode(state=problem, depth=0) self.tree.add(root)
for depth in range(self.max_depth): current_nodes = self.tree.get_nodes_at_depth(depth) new_nodes = []
for node in current_nodes: # 生成多个下一步 thoughts = self.generate_thoughts(node.state)
for thought in thoughts: new_state = node.state + " → " + thought score = self.evaluate_state(new_state)
new_node = ThoughtNode( state=new_state, parent=node, depth=depth + 1, score=score ) new_nodes.append(new_node)
# 剪枝:保留 top-k 最佳节点 new_nodes.sort(key=lambda x: x.score, reverse=True) top_nodes = new_nodes[:self.branching_factor]
for node in top_nodes: self.tree.add(node)
# 选择最佳路径 best_path = self.tree.get_best_path() return best_pathToT 适用场景:
- 数学证明(需要回溯)
- 战略游戏(需要规划)
- 谜题求解(需要探索)
4.2 Graph of Thoughts (GoT)
Graph of Thoughts 将推理建模为图结构,允许合并和重用推理路径:
class GraphOfThoughts: """ 图思维:在推理图中合并、重用 """ def __init__(self, llm): self.llm = llm self.graph = ThoughtGraph()
def transform(self, nodes, operation): """ 图操作:生成、聚合、改进、验证 """ if operation == 'aggregate': # 合并多个想法 prompt = f"合并这些想法:{nodes}" new_node = self.llm.generate(prompt) return [new_node]
elif operation == 'improve': # 改进单个想法 prompt = f"改进这个想法:{nodes[0]}" return [self.llm.generate(prompt)]
elif operation == 'generate': # 生成新想法 prompt = f"基于:{nodes}\n生成新想法:" return [self.llm.generate(prompt) for _ in range(3)]
def solve(self, problem): """通过图操作解决""" # 添加初始节点 initial = self.graph.add(problem)
# 生成多个思路 thoughts = self.transform([initial], 'generate')
# 聚合思路 merged = self.transform(thoughts, 'aggregate')
# 改进思路 refined = self.transform(merged, 'improve')
return refined[0]4.3 ReAct (Reasoning + Acting)
ReAct 将 CoT 与工具使用结合:
class ReActAgent: """ ReAct: 推理 + 行动 """ def __init__(self, llm, tools): self.llm = llm self.tools = tools self.memory = []
def think(self, observation): """思考下一步行动""" prompt = self._build_prompt(observation) thought = self.llm.generate(prompt) return thought
def act(self, thought): """根据思考执行行动""" # 解析行动 action_name, action_input = self.parse_action(thought)
if action_name in self.tools: result = self.tools[action_name](action_input) return f"Observation: {result}" else: return f"Unknown action: {action_name}"
def step(self, question): """执行一步 ReAct""" # 思考 thought = self.think(question) self.memory.append(f"Thought: {thought}")
# 行动 if "Final Answer" in thought: return self.extract_answer(thought)
observation = self.act(thought) self.memory.append(observation)
return None
def solve(self, question, max_steps=10): for step in range(max_steps): result = self.step(question) if result: return result return "Failed to find answer"ReAct 的 prompt 模板:
问题:{question}
Thought 1: 我需要查找 X 信息Action 1: Search[X]Observation 1: ...
Thought 2: 基于观察,我需要进一步查询 YAction 2: Lookup[Y]Observation 2: ...
Thought 3: 现在我有了足够信息,可以给出答案Action 3: Finish[答案]4.4 Self-Refine
Self-Refine 让模型自我评估并改进:
class SelfRefine: """ 自我精炼:迭代评估和改进 """ def __init__(self, llm, max_iterations=3): self.llm = llm self.max_iterations = max_iterations
def generate_initial(self, question): """初始生成""" return self.llm.generate(question + "\n让我们一步一步思考。")
def critique(self, response): """自我评估""" prompt = f""" 以下是对问题的回答: {response}
请评估这个回答,指出: 1. 推理中是否有错误? 2. 是否遗漏了重要步骤? 3. 如何改进?
评估: """ return self.llm.generate(prompt)
def improve(self, response, critique): """根据评估改进""" prompt = f""" 原回答:{response} 评估:{critique}
请根据评估改进原回答: """ return self.llm.generate(prompt)
def solve(self, question): """通过自我精炼求解""" response = self.generate_initial(question)
for i in range(self.max_iterations): critique = self.critique(response)
if self._is_satisfied(critique): break
response = self.improve(response, critique)
return response4.5 各种 CoT 方法对比
| 方法 | 复杂度 | 准确性 | 适用场景 | 计算成本 |
|---|---|---|---|---|
| Direct | 低 | 低 | 简单问题 | 1× |
| Zero-Shot CoT | 低 | 中 | 一般推理 | 1.2× |
| Few-Shot CoT | 中 | 高 | 生产环境 | 1.5× |
| Self-Consistency | 中 | 高 | 关键任务 | 10× |
| ToT | 高 | 很高 | 复杂规划 | 10-100× |
| ReAct | 高 | 高 | 工具使用 | 5-20× |
| Self-Refine | 中 | 高 | 优化质量 | 3-5× |
5. CoT 的工程实现
5.1 Prompt 工程最佳实践
class CoTPromptBuilder: """ 高质量的 CoT Prompt 构建器 """ def __init__(self): self.templates = {}
def build_math_cot_prompt(self, question): """数学推理的 CoT prompt""" template = """你是一位数学专家。请通过清晰的步骤解决问题。
问题: {question}
让我们一步一步思考:- 第一步: 提取已知信息- 第二步: 确定解题方法- 第三步: 应用公式或定理- 第四步: 计算中间结果- 第五步: 验证答案
推理:""" return template.format(question=question)
def build_logic_cot_prompt(self, question): """逻辑推理的 CoT prompt""" template = """请分析这个逻辑问题,展示完整推理过程。
问题: {question}
推理框架:1. 识别前提2. 列出约束条件3. 推导可能结论4. 排除矛盾选项5. 得出最终答案
推理:""" return template.format(question=question)
def build_code_cot_prompt(self, question): """代码生成的 CoT prompt""" template = """请编写解决以下问题的代码,并解释思路。
问题: {question}
步骤:1. 理解问题需求2. 设计算法3. 编写代码4. 测试边界条件
代码与解释:""" return template.format(question=question)5.2 答案提取
class AnswerExtractor: """ 从 CoT 响应中提取结构化答案 """ def __init__(self): self.patterns = [ # 中文模式 r'答案是[::]?\s*(.+?)(?:\n|$)', r'最终答案[::]?\s*(.+?)(?:\n|$)', r'结论[::]?\s*(.+?)(?:\n|$)', r'所以[,,]?\s*(.+?)(?:\n|$)',
# 英文模式 r'[Tt]he answer is\s*[::]?\s*(.+?)(?:\n|$)', r'[Ff]inal [Aa]nswer\s*[::]?\s*(.+?)(?:\n|$)', r'[Tt]herefore[,,]?\s*(.+?)(?:\n|$)', r'####\s*(.+?)(?:\n|$)',
# LaTeX boxed r'\\boxed\{(.+?)\}', ]
def extract(self, response): """从响应中提取答案""" for pattern in self.patterns: match = re.search(pattern, response) if match: return match.group(1).strip()
# 如果没有匹配,尝试使用 LLM 提取 return self._extract_with_llm(response)
def extract_with_confidence(self, response): """提取答案并给出置信度""" candidates = [] for pattern in self.patterns: matches = re.findall(pattern, response) for match in matches: candidates.append(match.strip())
if not candidates: return None, 0.0
# 选择最后一个或最常出现的 from collections import Counter counts = Counter(candidates) most_common = counts.most_common(1)[0]
confidence = most_common[1] / len(candidates) if candidates else 0 return most_common[0], confidence5.3 推理评估
class CoTEvaluator: """ CoT 推理质量评估器 """ def __init__(self, llm): self.llm = llm
def evaluate_correctness(self, question, reasoning, answer, expected): """评估答案正确性""" # 1. 精确匹配 if str(answer).strip() == str(expected).strip(): return 1.0
# 2. 数值比较(对数学题) try: if abs(float(answer) - float(expected)) < 1e-6: return 1.0 except (ValueError, TypeError): pass
# 3. 语义相似度(使用 LLM 判断) prompt = f""" 预期答案:{expected} 实际答案:{answer} 这两个答案在语义上是否等价? 回答:是/否 """ response = self.llm.generate(prompt).strip() return 1.0 if "是" in response or "yes" in response.lower() else 0.0
def evaluate_reasoning_quality(self, reasoning): """评估推理质量""" criteria = { 'logical_consistency': '推理步骤是否逻辑一致?', 'step_clarity': '每一步是否清晰?', 'completeness': '是否包含所有必要步骤?', 'efficiency': '是否高效,没有冗余步骤?' }
scores = {} for criterion, question in criteria.items(): prompt = f"推理过程:{reasoning}\n\n{question}(评分 1-10)" score = self.llm.generate(prompt) try: scores[criterion] = float(score.strip().split()[0]) / 10 except (ValueError, IndexError): scores[criterion] = 0.5
return sum(scores.values()) / len(scores)6. CoT 与工具的结合
6.1 PAL (Program-Aided Language Models)
PAL 让 LLM 生成代码来辅助推理:
class PAL: """ Program-Aided Reasoning """ def __init__(self, llm, code_executor): self.llm = llm self.executor = code_executor
def solve(self, question): """通过生成代码来求解""" prompt = f""" 问题:{question}
请生成 Python 代码来解决这个问题。代码应该包含推理过程。
代码: ```python """ code = self.llm.generate(prompt)
# 执行代码 result = self.executor.execute(code) return resultPAL 示例:
# PAL 解决数学问题
question = "一家餐厅周一卖出 15 个汉堡,周二比周一多卖出 1/3,周三是周二的 80%。三天共卖出多少汉堡?"
# LLM 生成代码generated_code = """# 周一monday = 15# 周二: 周一 + 周一的 1/3tuesday = monday + monday * (1/3)# 周三: 周二的 80%wednesday = tuesday * 0.8# 总数total = monday + tuesday + wednesdayprint(f"周一: {monday}, 周二: {tuesday}, 周三: {wednesday}, 总数: {total}")"""
# 执行得到答案# 输出: 周一: 15, 周二: 20.0, 周三: 16.0, 总数: 51.06.2 Toolformer
Toolformer 让模型学会自动调用工具:
class ToolformerAgent: """ 自主工具调用 """ def __init__(self, llm, tools): self.llm = llm self.tools = tools self.tool_descriptions = self._format_tools(tools)
def decide_tool_use(self, context, question): """决定是否使用工具""" prompt = f""" 可用工具: {self.tool_descriptions}
当前问题: {question}
请判断是否需要使用工具。如果需要,调用工具;如果不需要,直接回答。
决定: """ decision = self.llm.generate(prompt)
if "[Tool:" in decision: tool_call = self.parse_tool_call(decision) return self.execute_tool(tool_call) else: return decision
def execute_tool(self, tool_call): """执行工具调用""" tool_name = tool_call['name'] tool_input = tool_call['input']
if tool_name in self.tools: return self.tools[tool_name](tool_input) return None6.3 RAG + CoT
将检索增强生成 (RAG) 与 CoT 结合:
class RAGWithCoT: """ 检索增强的思维链 """ def __init__(self, llm, retriever): self.llm = llm self.retriever = retriever
def solve(self, question): # 1. 检索相关文档 docs = self.retriever.retrieve(question, top_k=5) context = "\n".join([d.content for d in docs])
# 2. 基于检索的 CoT prompt = f""" 参考资料: {context}
问题:{question}
请基于参考资料,一步一步推理: 1. 提取关键信息 2. 整合多个资料 3. 推导答案 4. 给出最终答案
推理: """ return self.llm.generate(prompt)7. CoT 的训练方法
7.1 CoT 数据生成
class CoTDataGenerator: """ 自动生成 CoT 训练数据 """ def __init__(self, llm, dataset): self.llm = llm self.dataset = dataset
def generate_cot_for_problem(self, problem, solution): """为现有问题生成 CoT""" prompt = f""" 问题:{problem} 答案:{solution}
请生成到达这个答案的详细推理步骤: """ cot = self.llm.generate(prompt) return cot
def bootstrap_cot_data(self, num_samples=1000): """通过 bootstrapping 生成 CoT 数据""" cot_dataset = []
for item in self.dataset.sample(num_samples): # 1. 使用 Zero-Shot CoT 生成初始推理 initial_cot = self.generate_cot_for_problem( item.question, item.answer )
# 2. 验证推理是否正确 is_correct = self.verify_cot( item.question, initial_cot, item.answer )
if is_correct: cot_dataset.append({ 'question': item.question, 'cot': initial_cot, 'answer': item.answer })
return cot_dataset
def verify_cot(self, question, cot, expected_answer): """验证 CoT 是否正确""" # 执行 CoT 中的推理步骤 # 或使用 LLM 验证 prompt = f""" 问题:{question} 推理:{cot} 期望答案:{expected_answer}
这个推理是否正确地推导出期望答案? """ response = self.llm.generate(prompt) return "正确" in response or "correct" in response.lower()7.2 CoT 微调
class CoTFinetune: """ CoT 微调训练 """ def __init__(self, model, tokenizer, cot_dataset): self.model = model self.tokenizer = tokenizer self.dataset = cot_dataset
def prepare_training_data(self): """准备训练数据""" formatted_data = [] for item in self.dataset: # 格式: 问题 + CoT + 答案 text = f""" 问题:{item['question']} 推理:{item['cot']} 答案:{item['answer']} """ formatted_data.append({ 'text': text, 'input_ids': self.tokenizer.encode(text) }) return formatted_data
def train(self, epochs=3, batch_size=8, lr=2e-5): """训练循环""" optimizer = torch.optim.AdamW( self.model.parameters(), lr=lr, weight_decay=0.01 )
for epoch in range(epochs): for batch in self.dataloader(batch_size): outputs = self.model( input_ids=batch['input_ids'], labels=batch['input_ids'] ) loss = outputs.loss
loss.backward() optimizer.step() optimizer.zero_grad()7.3 强化学习与 CoT
class CoTRLHF: """ 使用 RL 优化 CoT 推理 """ def __init__(self, model, reward_model): self.model = model self.reward_model = reward_model
def compute_reward(self, question, cot, answer): """计算 CoT 推理的奖励""" # 1. 答案正确性奖励 correctness_reward = self.reward_model.score(question, answer)
# 2. 推理质量奖励 quality_reward = self.evaluate_reasoning(cot)
# 3. 格式奖励 format_reward = self.evaluate_format(cot)
return ( 0.6 * correctness_reward + 0.3 * quality_reward + 0.1 * format_reward )
def train_step(self, batch): """单步训练""" # 1. 模型生成 CoT generated_cots = self.model.generate(batch['questions'])
# 2. 计算奖励 rewards = [] for q, cot in zip(batch['questions'], generated_cots): answer = self.extract_answer(cot) reward = self.compute_reward(q, cot, answer) rewards.append(reward)
# 3. PPO 更新 loss = self.ppo_loss(batch, generated_cots, rewards) loss.backward() # ... optimizer step8. CoT 在不同任务中的应用
8.1 数学推理
class MathCoT: """ 数学推理的 CoT 优化 """ def __init__(self, llm): self.llm = llm
def build_math_prompt(self, problem): """数学专用 CoT prompt""" template = """解决以下数学问题。展示所有计算步骤。
问题: {problem}
让我们一步步解决:1. 识别已知量和未知量2. 确定适用的公式或定理3. 逐步计算4. 验证答案是否合理
解:""" return template.format(problem=problem)
def solve(self, problem): prompt = self.build_math_prompt(problem) return self.llm.generate(prompt)数学 CoT 的关键:
- 逐步计算:每一步都要明确写出
- 公式引用:使用准确的数学公式
- 单位一致:保持单位的一致性
- 答案验证:通过代入法或估算验证
8.2 常识推理
class CommonsenseCoT: """ 常识推理 CoT """ def __init__(self, llm): self.llm = llm
def solve(self, question): prompt = f""" 问题:{question}
请基于常识进行推理。思考: - 这个情境下的人/物通常会如何反应? - 哪些常识知识可以应用? - 推理过程:
推理: """ return self.llm.generate(prompt)8.3 多步推理 (Multi-Hop QA)
class MultiHopCoT: """ 多跳问答的 CoT """ def __init__(self, llm, retriever): self.llm = llm self.retriever = retriever
def solve(self, question): prompt = f""" 问题:{question}
这是一个需要多步推理的问题。请: 1. 将问题分解为子问题 2. 依次解决每个子问题 3. 整合答案
分解: - 子问题 1: - 子问题 2: - 子问题 3:
推理: """ return self.llm.generate(prompt)8.4 代码生成
class CodeCoT: """ 代码生成的 CoT """ def __init__(self, llm): self.llm = llm
def solve(self, problem): prompt = f""" 编程问题:{problem}
请按以下步骤解决: 1. 理解问题需求 2. 设计算法思路 3. 分析时间/空间复杂度 4. 编写代码 5. 测试边界情况
思路: ```python # 算法思路代码:
# 实现""" return self.llm.generate(prompt)
## 9. CoT 的评估基准
### 9.1 主要基准
| 基准 | 类型 | 难度 | 评估指标 ||------|------|------|----------|| GSM8K | 数学 | 中 | 准确率 || MATH | 数学 | 高 | 准确率 || AQuA-RAT | 数学 | 中 | 准确率 || StrategyQA | 常识 | 中 | 准确率 || HotpotQA | 多跳QA | 高 | F1, EM || HumanEval | 代码 | 中 | Pass@1 || LogiQA | 逻辑 | 中 | 准确率 |
### 9.2 GSM8K 评估示例
```pythonclass GSM8KEvaluator: """ GSM8K 数学基准评估 """ def __init__(self, llm): self.llm = llm
def evaluate(self, num_samples=100): correct = 0 total = 0
for problem, expected_answer in self.load_gsm8k(num_samples): prompt = f""" 问题:{problem.question}
让我们一步一步思考。 """ response = self.llm.generate(prompt) predicted_answer = self.extract_number(response)
if abs(float(predicted_answer) - float(expected_answer)) < 1e-3: correct += 1 total += 1
return { 'accuracy': correct / total, 'correct': correct, 'total': total }9.3 不同方法的基准结果
| 基准 | Direct | CoT | Self-Consistency | ToT |
|---|---|---|---|---|
| GSM8K | 12.5% | 56.5% | 74.4% | - |
| MATH | 5.8% | 32.5% | 50.3% | - |
| StrategyQA | 53.3% | 73.0% | 81.7% | 84.6% |
| HotpotQA | 28.1% | 39.7% | 47.0% | - |
10. CoT 的局限与挑战
10.1 主要局限
| 局限 | 描述 | 缓解方法 |
|---|---|---|
| 幻觉推理 | 模型可能生成看似合理但错误的推理 | Self-Consistency, 验证步骤 |
| 成本增加 | 生成更多 token,增加推理成本 | 选择性 CoT |
| 不稳定的触发 | 不同 prompt 触发效果差异大 | Auto-CoT |
| 不可控的深度 | 模型可能推理过浅或过深 | 指定推理深度 |
| 难以复杂任务 | 超复杂任务仍无法处理 | 分层 CoT |
10.2 CoT 的失败模式
class CoTFailureAnalyzer: """ 分析 CoT 失败的原因 """ def __init__(self): self.failure_types = { 'arithmetic_error': '计算错误', 'logical_fallacy': '逻辑谬误', 'misunderstood_problem': '误解问题', 'incomplete_reasoning': '推理不完整', 'hallucination': '幻觉信息', 'wrong_approach': '方法错误' }
def analyze(self, question, reasoning, expected, predicted): """分析失败类型""" analysis = { 'question': question, 'reasoning': reasoning, 'expected': expected, 'predicted': predicted, 'failure_types': [] }
# 检测各类失败 if self.has_arithmetic_error(reasoning): analysis['failure_types'].append('arithmetic_error')
if self.has_logical_fallacy(reasoning): analysis['failure_types'].append('logical_fallacy')
# ... 更多检查
return analysis10.3 改进方向
- 验证机制:在每一步推理后添加验证
- 混合方法:CoT + 工具 + 搜索
- 过程奖励模型:训练专门的”推理质量评估器”
- 强化学习:通过 RL 优化 CoT 策略
- 多模态 CoT:结合视觉、听觉等多模态信息
11. CoT 与推理模型 (Reasoning Models)
11.1 OpenAI o1 系列
OpenAI o1 是 CoT 训练进模型权重的代表:
传统模型 + CoT Prompt: Input: "问题 + Let's think step by step" Model: 生成推理 token Output: 最终答案
OpenAI o1: Input: "问题" Model: 内部自动进行长 CoT 推理 (上千 token) Output: 最终答案 (CoT 隐藏在内部)o1 的特点:
- 内部进行长链推理(数千 token)
- 不向用户展示推理过程
- 在数学、编程、科学问题上达到博士级水平
11.2 DeepSeek-R1
DeepSeek-R1 是开源推理模型的代表:
| 特性 | 描述 |
|---|---|
| 训练方法 | 纯强化学习 + GRPO |
| 推理能力 | 数学竞赛级别 |
| 开源 | 是(完全开源) |
| 推理 token | 数千到数万 |
11.3 推理模型的训练范式
class ReasoningModelTrainer: """ 推理模型的训练流程 """ def __init__(self, base_model): self.model = base_model
def phase_1_cot_sft(self, cot_dataset): """阶段 1: CoT 监督微调""" print("阶段 1: CoT SFT") # 让模型学会生成 CoT for batch in cot_dataset: loss = self.compute_sft_loss(batch) self.update(loss)
def phase_2_rlhf(self, preference_data): """阶段 2: 人类反馈强化学习""" print("阶段 2: RLHF") # 训练奖励模型 reward_model = self.train_reward_model(preference_data)
# PPO 优化 for batch in preference_data: response = self.model.generate(batch.question) reward = reward_model.score(batch.question, response) loss = self.compute_ppo_loss(batch, response, reward) self.update(loss)
def phase_3_distillation(self, teacher_model): """阶段 3: 蒸馏到小模型""" print("阶段 3: 蒸馏") # 用大推理模型生成训练数据 distilled_data = teacher_model.generate_cot_dataset()
# 训练小模型 self.phase_1_cot_sft(distilled_data)12. 核心概念总结
12.1 CoT 的关键 Prompt 模式
# 模式 1: Zero-Shot CoT"Let's think step by step."
# 模式 2: 中文 Zero-Shot"让我们一步一步思考。"
# 模式 3: Few-Shot CoT"""示例 1: 问题 → 推理 → 答案示例 2: 问题 → 推理 → 答案问题: {用户问题}推理:"""
# 模式 4: Self-Consistency"""[生成多个推理路径][投票选择最常见答案]"""
# 模式 5: ToT"""[维护推理树][评估和搜索最佳路径]"""12.2 CoT 的核心数学表达
- CoT 输出形式:
其中 是推理步骤, 是最终答案。
- Self-Consistency 投票:
- CoT 的有效计算深度:
其中 是 CoT 生成的 token 数。
- ToT 评分函数:
13. 实践建议
13.1 选择合适的 CoT 方法
def choose_cot_method(task_type, budget, accuracy_need): """ 根据任务选择合适的 CoT 方法 """ if budget == 'low' and accuracy_need == 'low': return 'direct' # 直接回答
if budget == 'low' and accuracy_need == 'medium': return 'zero_shot_cot' # Zero-Shot CoT
if budget == 'medium' and accuracy_need == 'high': return 'few_shot_cot' # Few-Shot CoT
if budget == 'high' and accuracy_need == 'high': return 'self_consistency' # Self-Consistency
if task_type == 'planning' or task_type == 'search': return 'tot' # Tree of Thoughts
if task_type == 'tool_use': return 'react' # ReAct
return 'few_shot_cot' # 默认13.2 CoT 设计的最佳实践
- 演示质量 > 数量:精心设计的 3 个示例胜过随意的 10 个
- 推理要清晰:每一步都要明确
- 格式要一致:保持答案格式的一致性
- 验证是必需的:对关键任务使用 Self-Consistency
- 成本要权衡:CoT 增加推理成本,需评估性价比
13.3 常见错误及避免
| 常见错误 | 解决方案 |
|---|---|
| 演示过于复杂 | 使用简单、清晰的演示 |
| 推理跳步 | 强调”每一步都要明确” |
| 答案格式不统一 | 强制使用特定格式(如 #### ) |
| 演示与问题不匹配 | 选择与目标问题相似的演示 |
| 忽略验证 | 添加答案验证步骤 |
14. 总结与展望
CoT 的核心价值
- 激活大模型潜能:CoT 让大模型的推理能力”涌现”
- 可解释性:推理过程透明,可调试
- 灵活性:适用于多种推理任务
- 可扩展性:可以与各种技术结合
CoT 的未来方向
- 训练即推理:将 CoT 能力训练进模型权重(OpenAI o1)
- 多模态 CoT:结合视觉、听觉等多模态信息
- 自适应 CoT:根据问题难度自动调整推理深度
- 协同 CoT:多个模型协同推理
- 可验证 CoT:自动验证推理正确性
学习路径建议
- 基础:理解 Few-Shot CoT 和 Zero-Shot CoT
- 进阶:掌握 Self-Consistency 和 ToT
- 实践:在实际项目中应用 CoT
- 深入:研究 CoT 的理论解释
- 前沿:关注推理模型的发展
CoT 是大模型推理能力的重要里程碑。从简单的 prompt 技巧到 OpenAI o1 这样的推理模型,CoT 思想已经深刻地改变了 AI 领域。掌握 CoT 是理解现代大模型推理能力的关键。
参考资料
- Wei, J., et al. (2022). “Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.” NeurIPS.
- Kojima, T., et al. (2022). “Large Language Models are Zero-Shot Reasoners.” NeurIPS.
- Wang, X., et al. (2022). “Self-Consistency Improves Chain of Thought Reasoning in Language Models.” ICLR.
- Yao, S., et al. (2023). “Tree of Thoughts: Deliberate Problem Solving with Large Language Models.” NeurIPS.
- Yao, S., et al. (2022). “ReAct: Synergizing Reasoning and Acting in Language Models.” ICLR.
- Zhang, Z., et al. (2022). “Automatic Chain of Thought Prompting in Large Language Models.” arXiv.
- Besta, M., et al. (2023). “Graph of Thoughts: Solving Elaborate Problems with Large Language Models.” AAAI.
- Madaan, A., et al. (2023). “Self-Refine: Iterative Refinement with Self-Feedback.” NeurIPS.
- Gao, L., et al. (2022). “PAL: Program-aided Language Models.” ICML.
- Schick, T., et al. (2023). “Toolformer: Language Models Can Teach Themselves to Use Tools.” NeurIPS.
- Wei, J., et al. (2022). “Emergent Abilities of Large Language Models.” TMLR.
- OpenAI. (2024). “Learning to Reason with LLMs.” OpenAI Blog.
- DeepSeek-AI. (2025). “DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.” arXiv.
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!

