深度解析安德烈·卡帕斯 nanochat 中的 GRPO 强化学习循环

作者
  • avatar
    姓名
    Nino
    职业
    Senior Tech Editor

安德烈·卡帕斯(Andre Karpathy)最近发布了 nanochat,这是一个展示如何在 8×H100 节点上、仅需 4 小时和约 100 美元成本就能训练出一个类 ChatGPT 模型的项目。虽然“速度赛跑”是其主要卖点,但最值得技术人员关注的部分其实隐藏在 scripts/chat_rl.py 中。这 300 行左右的代码实现了一个简化版的 GRPO(Group Relative Policy Optimization,组相对策略优化),即 DeepSeek 在其 R1 和 DeepSeek-V3 模型中使用的核心算法。

在 LLM 开发过程中,获取稳定且高速的 API 接口是实验的关键。通过 n1n.ai 这样的平台,开发者可以轻松调用包括 DeepSeek 系列在内的顶级模型,从而验证强化学习的实际效果。本文将深入剖析 Karpathy 的 GRPO 实现,探讨其背后的逻辑以及对现代 AI 开发的启示。

SFT 与推理能力的差距

标准的监督微调(SFT)能够让模型学会对话的“语气”和“格式”。在 SFT 之后,模型可以遵循工具调用语法,表现得像一个合格的助手。然而,面对 GSM8K 这样的数学应用题,SFT 模型往往能列出正确的方程,但在最后的算术步骤上出错。预训练提升了框架感,但 RL(强化学习)才是解决“最后一公里”准确性的关键。

nanochat 的 RL 步骤专门针对这一差距。它选择 GSM8K 是因为其答案是机器可校验的:每个条目都以 #### 42 格式结尾。这意味着奖励函数(Reward Function)只需要一个正则表达式、一次字符串比较和一个浮点数转换。不需要奖励模型,不需要人工偏好标签,这极大降低了实现的复杂度。

简化的 GRPO 配方

DeepSeek 在 DeepSeekMath 论文中引入了 GRPO,旨在取消 PPO(近端策略优化)中传统的“评论家”(Critic)模型。Karpathy 的实现则更进一步,将 GRPO 简化为带有均值基准的 REINFORCE 算法。

核心的奖励提取逻辑如下:

# nanochat 中的奖励函数实现
GSM_RE = re.compile(r"#### (\-?[0-9\.\,]+)")

def extract_answer(completion):
    match = GSM_RE.search(completion)
    if match:
        return match.group(1).strip().replace(",", "")
    return None

如果模型输出的数字与真实答案一致,奖励为 1,否则为 0。这种非黑即白的监督信号足以驱动模型准确率的显著提升。在 n1n.ai 上测试经过此类优化后的模型,你会发现逻辑推理的严密性有了质的飞跃。

训练循环的三个核心步骤

对于每一个问题,训练循环执行以下操作:

  1. 分词(Tokenization):将提示词处理成模型可理解的 token。
  2. 批量生成:使用 Engine.generate_batch 同时生成 16 个回答(即“组”的概念)。
  3. 计算优势(Advantage):对每个回答评分,减去组平均值,结果即为优势值。
# 优势值计算逻辑
rewards = torch.tensor(rewards, dtype=torch.float, device=device)
mu = rewards.mean()
advantages = rewards - mu

这就是 GRPO 的精髓:如果没有一个回答是正确的(均值为 0),或者所有回答都是正确的(均值为 1),那么优势值均为 0,模型不进行更新。只有当组内出现“好坏之分”时,梯度才会产生。这种基于组的对比取代了 PPO 中复杂的价值函数预测。

nanochat 与完整版 GRPO 的对比

Karpathy 在文档中明确指出,他的实现是“精简版”。为了保持代码的简洁性,他去掉了一些在生产环境(如 DeepSeek-V3 训练)中必不可少的“安全护栏”。

功能特性完整版 GRPO (DeepSeek)nanochat 实现
KL 散度惩罚与参考模型对比,防止漂移无(无锚点)
PPO 裁剪比例裁剪以保证稳定性仅在线策略,无裁剪
优势归一化使用 z-score (r - μ) / σ仅减去均值 (r - μ)
信任区域复杂的数学约束依赖于明确的机器校验奖励

对于使用 n1n.ai 构建 RAG 系统或自动化代理的开发者来说,理解这些差异至关重要。如果你的奖励函数是模糊的人工评分,缺少这些护栏会导致模型迅速坍塌或学会“作弊”;但如果奖励是像正则匹配这样明确的信号,这些护栏确实是可选的。

梯度更新的底层逻辑

其目标函数是 20 世纪 90 年代教科书级的 REINFORCE 更新,但在现代 PyTorch 框架下实现:

# 核心优化代码块
logp = -model(inputs, targets, loss_reduction='none').view_as(inputs) # \{B, T\}
pg_obj = (logp * advantages.unsqueeze(-1)).sum()
num_valid = (targets >= 0).sum().clamp(min=1)
pg_obj = pg_obj / (num_valid * num_passes * examples_per_rank)
loss = -pg_obj
loss.backward()

这段代码计算 log 似然乘以优势值,求和后取负作为损失函数。它没有 KL 项,没有比例计算。这证明了在奖励明确的情况下,算法的复杂性并不是成功的唯一决定因素。

为什么这改变了我们对 RL 的看法?

自从 2025 年初 DeepSeek R1 爆火以来,“我们使用了 GRPO” 成了许多 AI 项目的标配口号。Karpathy 的 nanochat 揭示了一个真相:GRPO 的强大不在于它的数学复杂度,而在于它如何利用“组”的信息来消除对 Critic 模型的依赖。

如果你能定义一个清晰的、可编程的奖励函数,你就可以在极低的成本下提升模型的逻辑推理能力。这对于企业级应用尤为重要,因为我们可以针对特定的业务逻辑(如 SQL 生成、JSON 格式校验)编写奖励函数,从而训练出垂直领域的“推理模型”。

开发者实战建议

  1. 奖励函数的设计是核心:在 RL 训练中,模型会极其敏锐地捕捉奖励函数的漏洞。如果你的正则匹配不够严谨,模型可能会学会输出乱码但包含正确答案标记的技巧。建议在 n1n.ai 提供的多种模型上进行对抗测试,寻找最优的 Reward 策略。
  2. Pass@k 指标优于 Accuracy:在评估逻辑模型时,关注 pass@k(即生成 k 个样本中至少有一个正确的概率)。这能更真实地反映模型解决难题的潜力,也是 Karpathy 在 nanochat 中使用的核心评估指标。
  3. 小步快跑:先进行充分的 SFT,确保模型掌握了基础的对话能力,再开启 RL 步骤。RL 应该被视为一种“对齐”手段,而不是“学习新知识”的手段。

总结

Karpathy 的 nanochat 是一份珍贵的教学礼物。它告诉我们,强化学习并不总是需要成千上万个 GPU 和复杂的算法框架。通过 300 行代码和明确的奖励信号,我们就能触及推理模型的门槛。随着 n1n.ai 等 API 聚合平台的普及,开发者现在可以更轻松地获取强大的基础模型,并应用这些精简而高效的 RL 技术来打造属于自己的智能应用。

Get a free API key at n1n.ai