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

- 姓名
- 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 上测试经过此类优化后的模型,你会发现逻辑推理的严密性有了质的飞跃。
训练循环的三个核心步骤
对于每一个问题,训练循环执行以下操作:
- 分词(Tokenization):将提示词处理成模型可理解的 token。
- 批量生成:使用
Engine.generate_batch同时生成 16 个回答(即“组”的概念)。 - 计算优势(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 格式校验)编写奖励函数,从而训练出垂直领域的“推理模型”。
开发者实战建议
- 奖励函数的设计是核心:在 RL 训练中,模型会极其敏锐地捕捉奖励函数的漏洞。如果你的正则匹配不够严谨,模型可能会学会输出乱码但包含正确答案标记的技巧。建议在 n1n.ai 提供的多种模型上进行对抗测试,寻找最优的 Reward 策略。
- Pass@k 指标优于 Accuracy:在评估逻辑模型时,关注
pass@k(即生成 k 个样本中至少有一个正确的概率)。这能更真实地反映模型解决难题的潜力,也是 Karpathy 在 nanochat 中使用的核心评估指标。 - 小步快跑:先进行充分的 SFT,确保模型掌握了基础的对话能力,再开启 RL 步骤。RL 应该被视为一种“对齐”手段,而不是“学习新知识”的手段。
总结
Karpathy 的 nanochat 是一份珍贵的教学礼物。它告诉我们,强化学习并不总是需要成千上万个 GPU 和复杂的算法框架。通过 300 行代码和明确的奖励信号,我们就能触及推理模型的门槛。随着 n1n.ai 等 API 聚合平台的普及,开发者现在可以更轻松地获取强大的基础模型,并应用这些精简而高效的 RL 技术来打造属于自己的智能应用。
Get a free API key at n1n.ai