Chain-of-Thought(思维链)
Chain-of-Thought(CoT) 是最经典、最广泛使用的推理范式,由 Google 于 2022 年提出。其核心思想是让 LLM 在给出最终答案前,先展示推理过程,通过显式的中间推理步骤提升复杂问题的解决准确率。
一、核心原理
1.1 CoT 的设计哲学
CoT 的核心思想源于人类的"逐步思考"模式:
┌─────────────────────────────────────────────────────────────┐
│ CoT 设计哲学 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 传统 LLM 输出: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:小明有 23 个苹果,给了小红 5 个, │ │
│ │ 又买了 12 个,现在有几个苹果? │ │
│ │ │ │
│ │ 答案:30 个 │ │
│ │ │ │
│ │ ❌ 直接给出答案,可能出错 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CoT 模式输出: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:小明有 23 个苹果,给了小红 5 个, │ │
│ │ 又买了 12 个,现在有几个苹果? │ │
│ │ │ │
│ │ 思考过程: │ │
│ │ 1. 小明最初有 23 个苹果 │ │
│ │ 2. 给了小红 5 个,剩下 23 - 5 = 18 个 │ │
│ │ 3. 又买了 12 个,现在有 18 + 12 = 30 个 │ │
│ │ │ │
│ │ 答案:30 个 │ │
│ │ │ │
│ │ ✅ 展示推理过程,减少错误 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘1.2 为什么 CoT 能提升推理能力?
| 原因 | 说明 |
|---|---|
| 减少跳跃推理错误 | 每一步都有明确的中间结果 |
| 提供思考空间 | 中间步骤让模型"慢下来"思考 |
| 符合认知过程 | 模仿人类解决复杂问题的方式 |
| 便于错误定位 | 可以检查每一步是否正确 |
1.3 CoT 核心公式
┌─────────────────────────────────────────────────────────────┐
│ CoT 推理公式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 标准 CoT: │
│ │
│ Output = LLM(Prompt + "Let's think step by step") │
│ │
│ 展开形式: │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 问题 │ → │ 步骤1 │ → │ 步骤2 │ → │ 答案 │ │
│ │ (Q) │ │ (S1) │ │ (S2) │ │ (A) │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 其中: │
│ S1 = LLM(Q) │
│ S2 = LLM(Q + S1) │
│ A = LLM(Q + S1 + S2) │
│ │
└─────────────────────────────────────────────────────────────┘二、CoT 类型
2.1 Zero-shot CoT vs Few-shot CoT
| 类型 | 描述 | 特点 |
|---|---|---|
| Zero-shot CoT | 仅添加提示词,无示例 | 简单易用,无需准备示例 |
| Few-shot CoT | 提供带推理过程的示例 | 效果更好,需要准备示例 |
┌─────────────────────────────────────────────────────────────┐
│ Zero-shot CoT 示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Prompt: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:一个长方形的周长是 24 厘米,长是宽的 2 倍, │ │
│ │ 求这个长方形的面积。 │ │
│ │ │ │
│ │ Let's think step by step. │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Output: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 设宽为 x,则长为 2x │ │
│ │ 2. 周长公式:2(长 + 宽) = 2(2x + x) = 6x │ │
│ │ 3. 6x = 24,所以 x = 4 │ │
│ │ 4. 宽 = 4 厘米,长 = 8 厘米 │ │
│ │ 5. 面积 = 长 × 宽 = 8 × 4 = 32 平方厘米 │ │
│ │ │ │
│ │ 答案:32 平方厘米 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Few-shot CoT 示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Prompt: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 示例 1: │ │
│ │ 问题:小明有 10 元钱,买了 3 支铅笔,每支 2 元, │ │
│ │ 还剩多少钱? │ │
│ │ 思考: │ │
│ │ 1. 3 支铅笔花费:3 × 2 = 6 元 │ │
│ │ 2. 剩余:10 - 6 = 4 元 │ │
│ │ 答案:4 元 │ │
│ │ │ │
│ │ 示例 2: │ │
│ │ 问题:一本书有 120 页,第一天读了 1/3,第二天读了 │ │
│ │ 剩下的 1/2,还剩多少页没读? │ │
│ │ 思考: │ │
│ │ 1. 第一天读了:120 × 1/3 = 40 页 │ │
│ │ 2. 剩余:120 - 40 = 80 页 │ │
│ │ 3. 第二天读了:80 × 1/2 = 40 页 │ │
│ │ 4. 最终剩余:80 - 40 = 40 页 │ │
│ │ 答案:40 页 │ │
│ │ │ │
│ │ 问题:一个长方形的周长是 24 厘米,长是宽的 2 倍, │ │
│ │ 求这个长方形的面积。 │ │
│ │ 思考: │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Output: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 设宽为 x,则长为 2x │ │
│ │ 2. 周长公式:2(2x + x) = 6x = 24 │ │
│ │ 3. 解得 x = 4,所以宽 = 4 厘米,长 = 8 厘米 │ │
│ │ 4. 面积 = 8 × 4 = 32 平方厘米 │ │
│ │ 答案:32 平方厘米 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2.2 Auto-CoT(自动生成示例)
┌─────────────────────────────────────────────────────────────┐
│ Auto-CoT 流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 问题聚类:将相似问题聚类 │
│ │
│ 问题集 ─→ 聚类 ─→ 代表性问题 │
│ │
│ 2. 自动推理:对代表性问题生成推理链 │
│ │
│ 代表性问题 ─→ LLM + CoT ─→ 推理链 │
│ │
│ 3. 示例构建:将推理链作为 Few-shot 示例 │
│ │
│ 推理链 ─→ Few-shot 示例 ─→ 用于新问题 │
│ │
│ 优点: │
│ • 无需人工标注示例 │
│ • 自动适应不同类型问题 │
│ • 降低部署成本 │
│ │
└─────────────────────────────────────────────────────────────┘三、代码实现
3.1 基础 CoT 实现
"""
Chain-of-Thought 基础实现
"""
from typing import Optional
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
class ChainOfThought:
"""
CoT 推理器
支持 Zero-shot 和 Few-shot 两种模式
"""
# Zero-shot CoT 提示词
ZERO_SHOT_TEMPLATE = """
请回答以下问题,并展示你的思考过程。
问题:{question}
请一步一步地思考,然后给出答案。
"""
# Few-shot CoT 提示词
FEW_SHOT_TEMPLATE = """
请参考以下示例,回答问题并展示思考过程。
{examples}
问题:{question}
思考过程:
"""
def __init__(
self,
model_name: str = "gpt-4",
temperature: float = 0,
mode: str = "zero_shot"
):
"""
初始化 CoT 推理器
Args:
model_name: 模型名称
temperature: 温度参数
mode: 模式,"zero_shot" 或 "few_shot"
"""
self.llm = ChatOpenAI(
model=model_name,
temperature=temperature
)
self.mode = mode
self.examples = []
def add_example(self, question: str, reasoning: str, answer: str):
"""添加 Few-shot 示例"""
self.examples.append({
"question": question,
"reasoning": reasoning,
"answer": answer
})
def _format_examples(self) -> str:
"""格式化示例"""
formatted = ""
for i, example in enumerate(self.examples, 1):
formatted += f"""
示例 {i}:
问题:{example['question']}
思考过程:
{example['reasoning']}
答案:{example['answer']}
"""
return formatted
def reason(self, question: str) -> dict:
"""
执行 CoT 推理
Args:
question: 问题文本
Returns:
包含推理过程和答案的字典
"""
if self.mode == "zero_shot":
prompt = self.ZERO_SHOT_TEMPLATE.format(question=question)
else:
examples = self._format_examples()
prompt = self.FEW_SHOT_TEMPLATE.format(
examples=examples,
question=question
)
# 调用 LLM
response = self.llm.invoke(prompt)
return {
"question": question,
"reasoning": response.content,
"mode": self.mode
}
# 使用示例
if __name__ == "__main__":
# Zero-shot CoT
cot_zero = ChainOfThought(mode="zero_shot")
result = cot_zero.reason(
"小明有 100 元,买了 3 本书,每本 25 元,还剩多少钱?"
)
print("Zero-shot CoT 结果:")
print(result["reasoning"])
print("\n" + "="*50 + "\n")
# Few-shot CoT
cot_few = ChainOfThought(mode="few_shot")
# 添加示例
cot_few.add_example(
question="小红有 50 元,买了 2 支钢笔,每支 15 元,还剩多少钱?",
reasoning="""
1. 2 支钢笔的总价:2 × 15 = 30 元
2. 剩余金额:50 - 30 = 20 元
""",
answer="20 元"
)
result = cot_few.reason(
"小明有 100 元,买了 3 本书,每本 25 元,还剩多少钱?"
)
print("Few-shot CoT 结果:")
print(result["reasoning"])3.2 结构化 CoT 实现
"""
结构化 Chain-of-Thought 实现
输出标准化的推理步骤
"""
from pydantic import BaseModel
from typing import List
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import ChatPromptTemplate
class ReasoningStep(BaseModel):
"""单个推理步骤"""
step_number: int # 步骤编号
description: str # 步骤描述
calculation: Optional[str] = None # 计算过程(如有)
result: Optional[str] = None # 中间结果
class CoTResult(BaseModel):
"""CoT 推理结果"""
question: str # 原始问题
reasoning_steps: List[ReasoningStep] # 推理步骤
final_answer: str # 最终答案
confidence: float # 置信度
class StructuredCoT:
"""
结构化 CoT 推理器
输出标准化的推理步骤
"""
def __init__(self, model_name: str = "gpt-4"):
self.llm = ChatOpenAI(model=model_name, temperature=0)
self.parser = PydanticOutputParser(pydantic_object=CoTResult)
def reason(self, question: str) -> CoTResult:
"""执行结构化 CoT 推理"""
prompt = ChatPromptTemplate.from_messages([
("system", """你是一个逻辑推理助手。请一步步分析问题,给出详细的推理过程。
{format_instructions}
要求:
1. 每个步骤都要清晰明确
2. 如果涉及计算,要写出完整的计算过程
3. 最后给出明确的答案和置信度
"""),
("user", "问题:{question}")
])
chain = prompt | self.llm | self.parser
result = chain.invoke({
"question": question,
"format_instructions": self.parser.get_format_instructions()
})
return result
# 使用示例
if __name__ == "__main__":
structured_cot = StructuredCoT()
result = structured_cot.reason(
"一个水池有进水管和出水管,进水管 3 小时注满,出水管 4 小时放完。"
"如果同时打开两个管子,多少小时能注满水池?"
)
print(f"问题:{result.question}")
print("\n推理步骤:")
for step in result.reasoning_steps:
print(f" 步骤 {step.step_number}: {step.description}")
if step.calculation:
print(f" 计算: {step.calculation}")
if step.result:
print(f" 结果: {step.result}")
print(f"\n最终答案:{result.final_answer}")
print(f"置信度:{result.confidence}")3.3 自我一致性 CoT(Self-Consistency CoT)
"""
Self-Consistency CoT 实现
通过多次采样和投票提升准确率
"""
from collections import Counter
from typing import List
import re
class SelfConsistencyCoT:
"""
自我一致性 CoT
核心思想:多次采样,投票选择最常见的答案
"""
def __init__(
self,
model_name: str = "gpt-4",
num_samples: int = 5, # 采样次数
temperature: float = 0.7 # 较高温度增加多样性
):
self.llm = ChatOpenAI(
model=model_name,
temperature=temperature
)
self.num_samples = num_samples
def _extract_answer(self, text: str) -> str:
"""从推理结果中提取答案"""
# 尝试匹配 "答案是..." 或 "答案:..." 等模式
patterns = [
r"答案[是为:]\s*(.+)",
r"最终答案[是为:]\s*(.+)",
r"所以[是为:]\s*(.+)",
]
for pattern in patterns:
match = re.search(pattern, text)
if match:
return match.group(1).strip()
# 如果没找到,返回最后一句
sentences = text.strip().split('。')
return sentences[-1].strip() if sentences else text.strip()
def reason(self, question: str) -> dict:
"""
执行自我一致性推理
Args:
question: 问题文本
Returns:
包含所有推理路径和最终答案的字典
"""
prompt = f"""
问题:{question}
请一步步思考,然后给出答案。
每一步都要清晰地写出你的思考过程。
最后用"答案:"开头给出最终答案。
"""
# 多次采样
reasoning_paths = []
answers = []
for i in range(self.num_samples):
response = self.llm.invoke(prompt)
content = response.content
answer = self._extract_answer(content)
reasoning_paths.append({
"path_id": i + 1,
"reasoning": content,
"answer": answer
})
answers.append(answer)
# 投票选择最常见答案
answer_counts = Counter(answers)
most_common_answer, count = answer_counts.most_common(1)[0]
# 找到得到最多票数的推理路径
best_path = next(
p for p in reasoning_paths if p["answer"] == most_common_answer
)
return {
"question": question,
"reasoning_paths": reasoning_paths,
"answer_votes": dict(answer_counts),
"final_answer": most_common_answer,
"confidence": count / self.num_samples,
"best_reasoning": best_path["reasoning"]
}
# 使用示例
if __name__ == "__main__":
sc_cot = SelfConsistencyCoT(num_samples=5, temperature=0.7)
result = sc_cot.reason(
"小明有一些糖果,如果他每天吃 3 颗,8 天吃完;"
"如果他每天吃 4 颗,几天吃完?"
)
print(f"问题:{result['question']}")
print(f"\n投票结果:{result['answer_votes']}")
print(f"最终答案:{result['final_answer']}")
print(f"置信度:{result['confidence']:.0%}")
print(f"\n最佳推理路径:\n{result['best_reasoning']}")四、适用场景
4.1 最佳适用场景
| 场景类型 | 具体示例 | CoT 优势 |
|---|---|---|
| 数学计算 | 算术、代数、几何问题 | 逐步计算,避免计算错误 |
| 逻辑推理 | 三段论、条件推理 | 显式推理过程,逻辑清晰 |
| 常识问答 | 多步骤推理问题 | 分步思考,降低跳跃错误 |
| 代码生成 | 复杂算法实现 | 先分析后编码,逻辑清晰 |
4.2 场景详解
┌─────────────────────────────────────────────────────────────┐
│ CoT 典型应用场景 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 数学计算场景 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:一个圆柱体底面半径 3 厘米,高 10 厘米, │ │
│ │ 求它的体积(π 取 3.14)。 │ │
│ │ │ │
│ │ 思考过程: │ │
│ │ 步骤 1:回顾圆柱体体积公式 V = πr²h │ │
│ │ 步骤 2:代入数值 r = 3,h = 10 │ │
│ │ 步骤 3:计算底面积 πr² = 3.14 × 3² = 3.14 × 9 │ │
│ │ = 28.26 平方厘米 │ │
│ │ 步骤 4:计算体积 V = 28.26 × 10 = 282.6 立方厘米 │ │
│ │ │ │
│ │ 答案:282.6 立方厘米 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 逻辑推理场景 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:所有猫都是动物,所有动物都需要食物, │ │
│ │ 所以什么? │ │
│ │ │ │
│ │ 思考过程: │ │
│ │ 步骤 1:分析前提关系 │ │
│ │ 前提 1:所有猫 → 动物 │ │
│ │ 前提 2:所有动物 → 需要食物 │ │
│ │ 步骤 2:建立推理链 │ │
│ │ 猫 → 动物 → 需要食物 │ │
│ │ 步骤 3:得出结论 │ │
│ │ 所有猫都需要食物 │ │
│ │ │ │
│ │ 答案:所有猫都需要食物 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 常识推理场景 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 问题:小明从家出发去学校,先向东走 500 米, │ │
│ │ 再向北走 300 米到达学校。 │ │
│ │ 如果他想走最短路线,应该怎么走? │ │
│ │ │ │
│ │ 思考过程: │ │
│ │ 步骤 1:分析当前位置关系 │ │
│ │ 家在学校西南方向 │ │
│ │ 步骤 2:计算直线距离 │ │
│ │ 最短路线是直线,构成直角三角形 │ │
│ │ 斜边 = √(500² + 300²) = √(250000 + 90000) │ │
│ │ = √340000 ≈ 583 米 │ │
│ │ 步骤 3:确定方向 │ │
│ │ 方向 = arctan(300/500) ≈ 31° │ │
│ │ 应该向东北方向走约 583 米 │ │
│ │ │ │
│ │ 答案:向东北方向走约 583 米 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘4.3 不适用场景
| 场景 | 原因 | 推荐替代方案 |
|---|---|---|
| 简单问题 | 不需要中间推理 | 直接回答 |
| 需要回溯的问题 | 线性结构不支持回退 | ToT(思维树) |
| 多路径探索 | 只能探索一条路径 | ToT 或 GoT |
| 创意写作 | 不需要逻辑推理 | 直接生成 |
五、CoT 的局限性
5.1 主要局限性
| 局限性 | 描述 | 影响 |
|---|---|---|
| 线性推理 | 只能按顺序思考 | 无法处理需要回溯的问题 |
| 单路径限制 | 无法并行探索多种方案 | 可能错过更优解 |
| 错误传播 | 前序错误影响后续 | 一步错导致全错 |
| Token 消耗 | 中间步骤消耗大量 Token | 成本增加 |
5.2 改进方向
┌─────────────────────────────────────────────────────────────┐
│ CoT 改进方向 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Self-Consistency(自我一致性) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 多次采样 + 投票 │ │
│ │ 解决:单一推理路径可能出错 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. Tree-of-Thought(思维树) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 树状结构 + 搜索算法 │ │
│ │ 解决:线性推理无法回溯 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. Chain-of-Verification(验证链) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 推理 + 验证步骤 │ │
│ │ 解决:错误传播问题 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. Least-to-Most Prompting │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 从简单到复杂逐步推理 │ │
│ │ 解决:复杂问题一步到位困难 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘六、与其他推理范式的关系
6.1 CoT 在推理范式中的位置
┌─────────────────────────────────────────────────────────────┐
│ 推理范式演进关系 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 直接输出 │ │
│ │ │ │ │
│ │ ↓ 添加推理过程 │ │
│ │ Chain-of-Thought (CoT) ────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ 扩展为树结构 │ │ │
│ │ ↓ │ │ │
│ │ Tree-of-Thought (ToT) ───────────────────────┐ │ │ │
│ │ │ │ │ │ │
│ │ │ 扩展为图结构 │ │ │ │
│ │ ↓ ↓ │ │ │
│ │ Graph-of-Thought (GoT) Self-Consistency CoT │ │ │
│ │ │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ CoT 是基础,ToT/GoT 是扩展 │
│ Self-Consistency 是增强 │
│ │
└─────────────────────────────────────────────────────────────┘6.2 范式对比
| 维度 | CoT | ToT | GoT |
|---|---|---|---|
| 结构 | 线性链 | 树 | 图 |
| 回溯 | ❌ 不支持 | ✅ 支持 | ✅ 支持 |
| 多路径 | ❌ 单路径 | ✅ 多路径 | ✅ 多路径 |
| 聚合分解 | ❌ 不支持 | ❌ 不支持 | ✅ 支持 |
| 复杂度 | 低 | 中 | 高 |
七、面试高频问题
Q1: CoT 为什么能提升推理能力?
答案要点:
- 减少跳跃推理错误:显式的中间步骤避免了从问题直接跳跃到答案的错误
- 提供思考空间:中间步骤让模型"慢下来"进行推理
- 符合认知过程:模仿人类解决复杂问题的分步思考方式
- 便于错误定位:可以检查每一步推理是否正确
Q2: Zero-shot CoT 和 Few-shot CoT 如何选择?
答案要点:
-
Zero-shot CoT:
- 简单易用,只需添加"Let's think step by step"
- 适用于通用场景,无需准备示例
- 效果略逊于 Few-shot
-
Few-shot CoT:
- 效果更好,示例引导模型输出格式
- 需要人工准备高质量示例
- 适用于特定领域或需要特定推理格式
Q3: Self-Consistency CoT 的原理是什么?
答案要点:
- 多次采样生成多个推理路径(温度 > 0)
- 从每个推理路径中提取答案
- 投票选择最常见的答案
- 提升准确率,但增加成本
Q4: CoT 的主要局限性是什么?
答案要点:
- 线性推理:只能按顺序思考,无法回溯
- 单路径限制:无法并行探索多种方案
- 错误传播:前序错误会影响后续所有步骤
- Token 消耗:中间步骤消耗大量 Token
Q5: 如何在 Agent 中应用 CoT?
答案要点:
- 在 ReAct 架构中,Thought 就是 CoT 推理
- 在 Plan-and-Execute 中,规划阶段使用 CoT 生成步骤
- 结合工具调用,每步推理后执行相应操作
- 可以与 Self-Consistency 结合提升可靠性
八、小结
| 概念 | 一句话总结 | 面试关键词 |
|---|---|---|
| CoT | 让模型展示推理过程,Step by Step | 思维链、逐步推理 |
| Zero-shot CoT | 仅添加提示词,无需示例 | Let's think step by step |
| Few-shot CoT | 提供带推理过程的示例 | 示例引导、格式学习 |
| Self-Consistency | 多次采样投票,提升准确率 | 多路径、投票机制 |
一句话总结:CoT 是最基础的推理范式,通过显式展示推理过程显著提升复杂问题的解决准确率。
最后更新:2026年3月19日