Skip to content

第 14 章 2025—2026:前沿——思维链、推理模型与多智能体 ​

学习目标 ​

  • 理解思维链(CoT)与推理时缩放(test-time scaling)
  • 理解 2025 年推理模型(DeepSeek-R1、o 系列)的强化学习训练
  • 理解自洽性(self-consistency)多数投票
  • 理解多智能体协作与工具调用

14.1 时代背景:从「会说话」到「会思考」 ​

2023 年的 ChatGPT 会流利地「胡说」;2024 年底到 2025 年,行业把重心转向推理:让模型在回答前「想一想」。标志性事件:

  • OpenAI o1(2024)/ o3(2025):在回答前生成内部思维链;
  • DeepSeek-R1(2025 年 1 月):开源,用 GRPO 强化学习直接训练出推理能力,并以 MIT 协议开源;
  • Claude、Gemini 等全面进入推理模型时代,「推理时缩放」成为与训练缩放并列的第三条增长曲线。

与此同时,多智能体(agent)把大模型从「问答机」变成「行动者」:调用工具、访问网页、写代码、协作完成多步任务。2025 年,OpenAI Operator、Claude Computer Use、Manus 等产品展示了 agent 的雏形。

14.2 思维链:让模型把推理写出来 ​

第 10 章的缩放定律说的是训练时缩放;2024 年后人们发现,推理时也能缩放——给模型更多时间与计算去「想」,准确率会提升。

最简单有效的方法叫思维链(Chain-of-Thought, CoT):在提示里要求模型输出中间步骤,而不是直接给答案。对数学题,先写「设未知数…逐步计算…」再给答案,错误率显著下降。

examples/ch14_cot.py 训练一个字符级 GPT 学习「两位数×一位数」的竖式写法:

CoT 模型参数量:153,935
step 500:loss = 0.6761
step 1000:loss = 0.4405
step 1500:loss = 0.3686
贪心解码(1 次):正确 6/10
单次采样(temp=0.8,5 轮平均):60%
自洽性(16 次采样多数投票):正确 7/10

三个数字讲清推理时缩放:

  • 贪心解码 6/10:一条路走到黑,错了就错;
  • 单次采样 60%:采样有随机性,可能更好可能更差;
  • 自洽性(多数投票) 7/10:采样 16 条推理路径,取出现最多的答案——不同路径的随机错误互相抵消,正确答案胜出。

这就是 2022 年 Wang 等人提出的 self-consistency,也是「推理时缩放」最朴素、最稳健的一种:不训练,只靠采样 + 投票,就能提升准确率。注意差距不大——小模型上推理时缩放的收益有限,这正是当前研究的开放问题。

14.3 推理模型:用强化学习训练「思考」 ​

DeepSeek-R1 的思路:不用人工标注思维链,而是让模型在数学、代码任务上用 GRPO(强化学习) 自己探索推理路径,奖励只看最终答案对不对。模型在试错中发现:写出更长的中间推理,更容易答对,于是自发涌现出「反思、验证、修正」的行为。

与第 12 章 RLHF 的区别:

RLHFGRPO / 推理训练
奖励人类偏好打分最终答案正确性(可自动验证)
目标行为讨好用户推理正确率
代价需要人类标注需要大量计算

推理模型的成本也很直接:o1 回答一个复杂问题可能要「想」几十秒到几分钟——计算量换准确率,这就是推理时缩放的工程形态。

14.4 多智能体:让模型用工具、会协作 ​

单模型再聪明,也有边界:它不能实时查数据、不能操作软件、不能「多个人一起干」。2025 年的 agent 范式:

  1. 工具调用:模型输出结构化的函数调用(如 search("价格")),系统执行并把结果喂回;
  2. 规划-执行循环:模型拆解任务 → 调用工具 → 看结果 → 决定下一步,直到完成;
  3. 多智能体协作:规划者、执行者、审查者分工,一个负责拆解,一个负责调用,一个负责检查。

examples/ch14_agents.py 模拟「规划者 + 执行者」的 agent 循环:

任务:计算 (2+3)×4
  第 1 步 规划者:调用 add(2, 3)
  第 1 步 执行者:add 返回 5
  第 2 步 规划者:调用 mul(5, 4)
  第 2 步 执行者:mul 返回 20
最终答案:20

任务:在 7、12、9 中找最大数
  第 1 步 规划者:调用 compare(7, 12)
  第 1 步 执行者:compare 返回 12
  第 2 步 规划者:调用 compare(12, 9)
  第 2 步 执行者:compare 返回 12
最终答案:12

真实的 agent 用大模型代替这里的「硬编码规划者」:模型读任务、选工具、处理结果,循环直到完成。Claude Computer Use 控制电脑屏幕、Operator 自动订餐购物、DeepResearch 自主查上百个网页写报告——都是这个循环的规模化。

14.5 2026 年的三条主线 ​

回顾 2025—2026,神经网络的前沿不是某个新架构,而是三股力量的合流:

  1. 推理时缩放:思维链、自洽性、搜索树(OpenAI o3、DeepSeek-R1 的规模化);
  2. 多模态:文本、图像、音频、视频统一到一个模型(GPT-4o、Gemini 的路线);
  3. 智能体:模型 + 工具 + 循环 = 能行动的数字员工。

它们全都建立在你前 13 章学过的积木上:感知机、MLP、CNN、RNN、Transformer、扩散模型、大模型对齐。神经网络的历史没有结束,你正站在它的下一个节点上。

完整代码 ​

本章用到的完整示例代码:

examples/ch14_cot.py ​

py
"""第 14 章示例(2025—2026):思维链与推理时缩放。

训练一个字符级 GPT 学习"两位数×一位数"的带步骤竖式写法
(如 34×7=30×7+4×7=210+28=238)。
测试时对比:贪心解码、单次采样、采样 16 次后多数投票(自洽性)。

运行方式:
    uv run python examples/ch14_cot.py
"""
import re
import torch
from torch import nn

torch.manual_seed(0)
device = "cuda" if torch.cuda.is_available() else "cpu"


def make_cot(a, b):
    tens, units = a // 10 * 10, a % 10
    return f"{a}×{b}={tens}×{b}+{units}×{b}={tens * b}+{units * b}={a * b}"


examples = [make_cot(a, b) for a in range(11, 99) for b in range(2, 9)]
corpus = "\n".join(examples)
chars = sorted(set(corpus + "0123456789×+=。"))
stoi = {c: i for i, c in enumerate(chars)}
itos = {i: c for c, i in stoi.items()}
data = torch.tensor([stoi[c] for c in corpus], device=device)
BLOCK, D_MODEL = 32, 64


class Block(nn.Module):
    def __init__(self):
        super().__init__()
        self.ln1 = nn.LayerNorm(D_MODEL)
        self.attn = nn.MultiheadAttention(D_MODEL, 4, batch_first=True)
        self.ln2 = nn.LayerNorm(D_MODEL)
        self.mlp = nn.Sequential(nn.Linear(D_MODEL, 4 * D_MODEL), nn.GELU(), nn.Linear(4 * D_MODEL, D_MODEL))

    def forward(self, x, mask):
        x = x + self.attn(self.ln1(x), self.ln1(x), self.ln1(x), attn_mask=mask)[0]
        return x + self.mlp(self.ln2(x))


class MiniGPT(nn.Module):
    def __init__(self, vocab):
        super().__init__()
        self.tok = nn.Embedding(vocab, D_MODEL)
        self.pos = nn.Embedding(BLOCK, D_MODEL)
        self.blocks = nn.ModuleList([Block() for _ in range(3)])
        self.head = nn.Linear(D_MODEL, vocab)

    def forward(self, x):
        B, T = x.shape
        h = self.tok(x) + self.pos(torch.arange(T, device=x.device))
        mask = torch.triu(torch.full((T, T), float("-inf"), device=x.device), diagonal=1)
        for block in self.blocks:
            h = block(h, mask)
        return self.head(h)


model = MiniGPT(len(chars)).to(device)
opt = torch.optim.AdamW(model.parameters(), lr=1e-3)
print(f"CoT 模型参数量:{sum(p.numel() for p in model.parameters()):,}")

for step in range(1500):
    start = torch.randint(0, len(data) - BLOCK, (32,), device=device)
    xb = torch.stack([data[s:s + BLOCK] for s in start])
    yb = torch.stack([data[s + 1:s + BLOCK + 1] for s in start])
    opt.zero_grad()
    loss = nn.functional.cross_entropy(model(xb).transpose(1, 2), yb)
    loss.backward()
    opt.step()
    if (step + 1) % 500 == 0:
        print(f"step {step + 1}:loss = {loss.item():.4f}")


def sample_answer(prompt, k=1, maxlen=24, temp=0.8):
    """生成 k 条回答,遇到换行符停止,返回每个回答中最后的数字。"""
    seq = torch.tensor([[stoi[c] for c in prompt]], device=device).repeat(k, 1)
    for _ in range(maxlen):
        logits = model(seq)[:, -1, :]
        if k > 1:
            tok = torch.multinomial((logits / temp).softmax(-1), 1)
        else:
            tok = logits.argmax(-1, keepdim=True)
        seq = torch.cat([seq, tok], dim=1)
        if (seq[:, -1] == stoi["\n"]).all():
            break
    answers = []
    for s in seq:
        text = "".join(itos[i.item()] for i in s).split("\n")[0]
        nums = re.findall(r"=(\d+)", text)
        answers.append(nums[-1] if nums else "")
    return answers


test_cases = [(37, 4), (86, 3), (52, 7), (19, 8), (64, 6),
              (43, 5), (78, 2), (29, 9), (91, 4), (56, 8)]
greedy_correct = 0
for a, b in test_cases:
    greedy = sample_answer(f"{a}×{b}=")[0]
    greedy_correct += int(greedy == str(a * b))
print(f"贪心解码(1 次):正确 {greedy_correct}/{len(test_cases)}")

single_correct = 0
for _ in range(5):                       # 5 轮单次采样,估计单次准确率
    for a, b in test_cases:
        single_correct += int(sample_answer(f"{a}×{b}=", k=1, temp=0.8)[0] == str(a * b))
print(f"单次采样(temp=0.8,5 轮平均):{single_correct / (5 * len(test_cases)):.0%}")

self_consistency = 0
for a, b in test_cases:
    votes = sample_answer(f"{a}×{b}=", k=16, temp=0.8)
    majority = max(set(votes), key=votes.count)
    self_consistency += int(majority == str(a * b))
print(f"自洽性(16 次采样多数投票):正确 {self_consistency}/{len(test_cases)}")

examples/ch14_agents.py ​

py
"""第 14 章示例(2025—2026):多智能体协作与工具调用。

模拟"规划者 + 执行者"的 agent 循环:规划者把任务拆成工具调用,
执行者调用工具并把结果返回,循环直到得到最终答案。

运行方式:
    uv run python examples/ch14_agents.py
"""

# 工具注册表:agent 可以调用的函数
TOOLS = {
    "add": lambda a, b: a + b,
    "mul": lambda a, b: a * b,
    "compare": lambda a, b: a if a > b else b,
}


def run_agent_loop(task, plan, max_steps=5):
    """plan: [(工具名, 参数...)];执行并打印轨迹。"""
    print(f"任务:{task}")
    result = None
    for step, (tool, *args) in enumerate(plan, 1):
        if step > max_steps:
            print("  达到最大步数,停止")
            break
        print(f"  第 {step} 步 规划者:调用 {tool}{tuple(args)}")
        result = TOOLS[tool](*args)
        print(f"  第 {step} 步 执行者:{tool} 返回 {result}")
    print(f"最终答案:{result}\n")
    return result


# 场景 1:计算 (2+3)×4,先加后乘
run_agent_loop("计算 (2+3)×4", [("add", 2, 3), ("mul", 5, 4)])

# 场景 2:找出三个数里最大的
run_agent_loop("在 7、12、9 中找最大数", [("compare", 7, 12), ("compare", 12, 9)])

动手实践 ​

  1. 运行 examples/ch14_cot.py,把采样次数从 16 改成 4 和 32,观察自洽性准确率与采样数的关系。
  2. 修改 examples/ch14_cot.py 的温度(0.3 / 1.0),观察「多样性」与「准确率」的权衡。
  3. 在 examples/ch14_agents.py 里加一个 sub 工具,规划「计算 (10-3)×2」的调用序列。
  4. 给 agent 循环加一个「审查者」:执行者返回后,审查者校验结果是否符合预期,不符则重新规划。

常见错误 ​

错误写法现象原因
让模型直接答复杂题错误率高要提示「先写推理步骤」,CoT 是提示工程的基本功
多数投票时答案格式不统一投票分散,无法收敛要求模型输出统一格式(如「答案:数字」)再投票
温度设 0 还做自洽性采样的 16 条完全相同多样性来自温度 > 0
agent 循环没有最大步数无限循环烧钱必须设 max_steps 与终止条件
工具调用结果不反馈给模型agent 重复同一动作每步要把工具结果拼回上下文
把推理模型的「思考时间」当 bug误杀推理时缩放就是要花时间换准确率

章末练习 ​

基础

  1. 思维链为什么能提升推理准确率?
  2. 自洽性多数投票的前提是什么?
  3. agent 循环的基本单元是什么?

提高

  1. 在 examples/ch14_cot.py 中统计:单次采样准确率、5 次、16 次多数投票的准确率,画出采样数-准确率曲线。
  2. 把 CoT 数据改成「直接给答案」格式训练同样的模型,对比两种格式的准确率。
  3. 给 agent 演示加错误重试:工具调用失败后,规划者换一种方式再试。

挑战

  1. 实现简化 GRPO:在 examples/ch14_cot.py 的模型上,用「答案正确 = 奖励 1」做策略梯度训练(类似第 12 章 RLHF),观察训练后准确率提升。
  2. 设计一个双 agent 协作任务:一个 agent 拆解数学题,另一个验证答案,报告协作比单 agent 的准确率。

章末自测 ​

  1. 思维链的核心是?
    • A. 更多参数
    • B. 输出中间推理步骤
    • C. 更大数据集
    • D. 卷积
  2. 自洽性指?
    • A. 模型输出稳定
    • B. 多次采样后多数投票
    • C. 单一答案
    • D. 温度 0
  3. DeepSeek-R1 用强化学习直接优化?
    • A. 人类偏好
    • B. 最终答案正确性
    • C. 生成速度
    • D. 文本长度
  4. 推理时缩放指?
    • A. 增加模型参数
    • B. 推理时花更多计算换准确率
    • C. 减少推理时间
    • D. 数据增强
  5. agent 的工具调用是?
    • A. 模型直接执行代码
    • B. 模型输出结构化调用,系统执行
    • C. 人工操作
    • D. 无需反馈
  6. 多数投票需要答案格式?
    • A. 随意
    • B. 统一可解析
    • C. 必须中文
    • D. 必须英文
  7. GRPO 相比 RLHF 的奖励来源是?
    • A. 人类打分
    • B. 自动可验证的正确性
    • C. 模型自评
    • D. 随机
  8. agent 循环的必要组成是?
    • A. 工具 + 反馈 + 终止条件
    • B. 只有工具
    • C. 只有模型
    • D. 只有提示词
  9. 2025 年开源推理模型的代表是?
    • A. LLaMA
    • B. DeepSeek-R1
    • C. BERT
    • D. LeNet
  10. 本书最后一章强调的「积木」不包括?
    • A. Transformer
    • B. 扩散模型
    • C. 感知机
    • D. 牛顿法