Agentic RL
Published:
当前大模型后训练主要是通过RL来实现的,所以这个博客主要介绍一些agentic RL相关的知识。以下是AI总结的内容。每一个内容我自己也会写点总结。
1️⃣ RL 在 LLM 后训练中的核心目标
LLM 后训练中使用 RL 的核心目的通常是:
Align LLM with Human Preferences(HRA / RLHF)
- 调整模型输出,使其更符合人类价值观、道德规范或偏好。
- 核心思路:使用 RL 优化 reward model 得分,而非直接最大化语言模型对数似然。
控制输出风格或约束
- 避免毒性内容(toxicity)、敏感信息泄露或不符合安全策略的生成。
- 通过 RL 奖励合规输出、惩罚违规输出。
改善任务完成度与实用性
- 在复杂任务中,例如代码生成、推理、多步决策,RL 可以鼓励更高效或更正确的输出。
2️⃣ 主要 RL 方法分类
2.1 RLHF(Reinforcement Learning from Human Feedback)
流程:
- 用人工标注的示例训练 Reward Model (RM)。
- 让 LLM 生成输出,RM 对输出评分。
- 用 RL 优化 LLM,使其生成更高 RM 分数的输出。
常用算法:
- PPO (Proximal Policy Optimization):OpenAI GPT 系列常用。
- A2C / TRPO / REINFORCE:早期研究中也有使用。
关键文献:
- Christiano et al., 2017, Deep Reinforcement Learning from Human Preferences
- OpenAI Blog, 2022, Training language models to follow instructions with human feedback
注意点:
- Reward Hacking 风险:模型可能找到投机取巧策略。
- RLHF 主要在“后训练”阶段,不改变原始预训练权重结构。
2.2 RLAIF(RL from AI Feedback)
- 思路:使用 AI 模型(而非人类)生成奖励信号,减少人工成本。
方法:
- 使用强大 LLM 作为“评判模型”,对候选输出打分。
- RL 训练主模型优化分数。
- 应用:可用于代码生成、文案生成、对话优化。
参考:
- Bai et al., 2023, Training a Helpful and Harmless Assistant with RL from AI Feedback
2.3 RL for Safety / Toxicity Avoidance
- 目标:让模型主动避免生成不安全或有毒内容。
方法:
- 构建奖励函数:正向奖励安全输出,负向惩罚违规输出。
- 可与 RLHF 结合。
参考:
- OpenAI, 2023, Aligning Language Models to Avoid Harmful Content
- Perez et al., 2022, Red Teaming Language Models with RL
2.4 RL for Task-Specific Optimization
- 目标:提升特定任务的完成度。
应用案例:
- 代码生成:用 RL 优化生成的代码是否能通过测试用例。
- 数学/逻辑推理:奖励模型给出正确推理步骤。
- 对话任务:奖励连贯性、信息量或用户满意度。
方法:
- Reward 可以是自动化程序(如单元测试)、评分模型或模拟环境反馈。
参考:
- Nakano et al., 2021, WebGPT: Browser-assisted question answering with human feedback
- Hendrycks et al., 2021, Aligning AI with human values via benchmarks and RL
2.5 Agentic / Intrinsic Motivation RL in LLMs
思路:
给 LLM 添加 自主探索能力:
- 自主生成问题 → 自我回答 → 自我奖励。
- 内在奖励:信息增益、好奇心、能力提升。
目标:
- 增强模型在稀疏反馈环境下学习能力。
- 可用于多步任务、规划型对话。
参考:
- Gato / DeepMind 多任务 agent 模型
- OpenAI “AutoGPT / Reflexion” 系列探索自主反思 RL
2.6 RL for Multi-Modal / Grounded LLMs
- 目标:让 LLM 在与外部环境交互时做出优化决策。
应用:
- 文本-代码-机器人控制任务
- 文本-图像-交互系统
方法:
- 使用 RL 优化模型与外部环境交互的长期回报。
参考:
- OpenAI, 2023, Training language models to interact with environments with RL
3️⃣ 总结表格(Post-Training RL 在 LLM 的应用)
| 类别 | Reward 来源 | 算法 | 应用 | 核心目标 |
|---|---|---|---|---|
| RLHF | 人类评分 | PPO / TRPO / REINFORCE | 对话、指令遵循 | Align with human preference |
| RLAIF | AI 模型评分 | PPO / REINFORCE | 对话、生成任务 | 降低人工成本,优化输出 |
| Safety RL | 安全检测模型 | PPO / A2C | 去毒性、合规性 | 避免违规内容 |
| Task-Specific RL | 自动化测试/环境反馈 | PPO / REINFORCE | 代码、推理、QA | 提升任务完成度 |
| Agentic RL | 内在奖励(好奇心/empowerment) | PPO / intrinsic reward | 多步任务、自主探索 | 自主性、稀疏奖励学习 |
| Multi-Modal RL | 环境交互反馈 | PPO / Actor-Critic | 文本-代码-环境 | 强化长期决策与规划 |
PPO
采样(Generate batch)
使用当前策略 LLM((\pi_\theta))生成一批 prompt + completion:
- prompt 固定
- completion 是 model 逐 token 生成的 logits (注意这里尽管保留每个logits,但是还是要每次产生确定的token,即整个过程是autoregressive的)
同时,每个 token 的 hidden state 输入 value head → 预测 token-level value (V(s_t))
计算 reward
- Reward model 对整个生成序列打分 → 得到 total reward (r_T)
- 其他 token reward (r_{t<T}=0)
计算折算回报 / advantage(GAE)
- 对每条生成序列,计算 token-level return 或 GAE: \(\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)\) \(A_t = \delta_t + (\gamma \lambda) \delta_{t+1} + ...\)
- 这样即使 reward 稀疏,也能为每个 token 分配梯度信号
计算 PPO loss
- Policy loss:clip probability ratio × advantage \(L_\text{policy} = \mathbb{E}_t[\min(r_t(\theta) A_t, \text{clip}(r_t(\theta),1-\epsilon,1+\epsilon) A_t)]\)
- Value loss:MSE loss between value head output (V(s_t)) 和 GAE target \(L_\text{value} = \frac{1}{T} \sum_t (V(s_t) - \hat{V}_t)^2\)
- KL penalty:限制策略漂移 \(L_\text{KL} = \beta \cdot \text{KL}(\pi_\theta || \pi_\text{SFT})\)
梯度更新
总 loss: \(L_\text{total} = L_\text{policy} + c_1 L_\text{value} - c_2 H + L_\text{KL}\)
- (H) 是 entropy bonus,鼓励探索
- (c_1, c_2) 是超参数
对 LLM 权重做反向传播,更新策略和 value head 参数
循环迭代
- 更新后的 LLM 再生成下一批序列 → 重复步骤 2~5
- reward model 固定(一般不训练)
🔹 工程要点
- prompt 不参与 value loss:只对生成 token 做 loss mask
- reward sparse → GAE 或折扣回报传播优势
- value head 和 policy head 共享 Transformer backbone,计算效率高
- KL penalty 防止模型“为了高 reward”生成奇怪输出
- entropy bonus 防止过早收敛,保证探索多样性
DPO
DPO (Direct Preference Optimization) 是一种基于偏好学习的强化学习方法,旨在直接优化模型在特定偏好下的行为。与传统的 RL 方法不同,DPO 不使用奖励函数,而是直接学习模型在给定偏好下的最优行为。
DPO 的训练流程如下:
收集偏好数据集 $D = {(x_i, y_i, z_i)}_i$, 在用LLM生产数据的时候要保存每个token对应的logits,用来之后计算损失函数。
计算损失函数: \(L_\text{DPO} = \mathbb{E}_{(x, y, z) \sim D} [\log \pi_\theta(y|x) - \log \pi_{\theta}(z|x)]\)
梯度更新: \(\nabla_\theta L_\text{DPO} = \mathbb{E}_{(x, y, z) \sim D} [\nabla_\theta \log \pi_\theta(y|x) - \nabla_\theta \log \pi_{\theta}(z|x)]\)
为了训练的稳定性, 通常会加入一个KL散度约束: \(L_\text{DPO} = \mathbb{E}_{(x, y, z) \sim D} [\log \pi_\theta(y|x) - \log \pi_{\theta}(z|x)] + \beta \cdot \text{KL}(\pi_\theta || \pi_{\theta})\)
梯度更新: \(\nabla_\theta L_\text{DPO} = \mathbb{E}_{(x, y, z) \sim D} [\nabla_\theta \log \pi_\theta(y|x) - \nabla_\theta \log \pi_{\theta}(z|x)] + \beta \cdot \nabla_\theta \text{KL}(\pi_\theta || \pi_{\theta})\)
循环迭代: \(\theta_{t+1} = \theta_t - \alpha \cdot \nabla_\theta L_\text{DPO}\)
GRPO
GRPO 的数学形式
GRPO 的核心 surrogate objective(假设用组优势 + PPO clip + KL 正则)为:
\[\mathcal{J}_\text{GRPO}(\theta) = \sum_{i=1}^G \min\big( r_i A_i, \operatorname{clip}(r_i,1-\epsilon,1+\epsilon) A_i \big) - \beta D_\mathrm{KL}(\pi_\theta | \pi_\text{ref})\] \[r_i = \frac{\pi_\theta(y_i|x)}{\pi_{\theta_\text{old}}(y_i|x)}\]```pythonlog_r = 0 for t, y_t in enumerate(sequence): logits_theta = model_theta.forward(seq[:t]) logits_old = model_old.forward(seq[:t])
p_theta = softmax(logits_theta)[y_t]
p_old = softmax(logits_old)[y_t]
log_r += log(p_theta) - log(p_old)
r = exp(log_r)
$$
A_i = R_i - \bar R
$$
(组内标准化优势,或归一化)
---
## 3️⃣ 两样本 + 奖励为 ±1 时的退化
假设:
1. 组大小 (G = 2)
2. 奖励设为 (R(y_1) = +1, R(y_2) = -1)
3. 没有 clip($(\epsilon\to\infty)$)和 KL 正则 ($(\beta = 0)$)
那么:
* 组平均 $(\bar R = (1 + (-1))/2 = 0)$
* 优势 $(A_1 = 1 - 0 = 1),(A_2 = -1 - 0 = -1)$
代入 GRPO surrogate term:
$$
\mathcal{L}_\text{GRPO} \sim - \big[ r_1 \cdot 1 + r_2 \cdot (-1) \big] = - (r_1 - r_2)
$$
---
### 4️⃣ 用序列概率比表示
如果再把 $(r_i = \pi_\theta(y_i|x)/\pi_\text{ref}(y_i|x))$(假设 $(\pi_{\theta_\text{old}} = \pi_\text{ref})$),则:
$$
\mathcal{L}_\text{GRPO} \sim - \bigg( \frac{\pi_\theta(y_1|x)}{\pi_\text{ref}(y_1|x)} - \frac{\pi_\theta(y_2|x)}{\pi_\text{ref}(y_2|x)} \bigg)
$$
这个形式就是 DPO 的本质目标:**让模型相对参考模型在偏好输出上概率更高**。
如果进一步用 sigmoid 或 log-sigmoid 表示,就完全退化成 DPO:
$$
\mathcal{L}_\text{DPO} = - \log \sigma \Big( \log \frac{\pi_\theta(y_1|x)}{\pi_\text{ref}(y_1|x)} - \log \frac{\pi_\theta(y_2|x)}{\pi_\text{ref}(y_2|x)} \Big)
$$
✅ 所以结论是:
> **当 GRPO 的组大小为 2,奖励取 ±1,并且去掉 clip/KL 正则时,它严格退化为 DPO。**
---
也就是说 GRPO 是 DPO 的一个 **广义推广**:
* 多样化奖励(连续或多维) → GRPO
* 两样本 ±1 偏好 → DPO
## GSPO
GSPO是对GRPO的进一步正则化,核心在于由于长序列中概率连乘积会趋近于0,导致优势函数不稳定。因此GSPO将这个概率
$$
s_i = (\frac{\pi_\theta(y_i|x)}{\pi_{\theta_\text{old}}(y_i|x)})^{1/T}
$$
其中$T$是序列长度。
这样就可以避免概率连乘积趋近于0的问题。 但是问题在于这个并不是无偏的梯度的估计。 但是会极大增加训练的稳定性。
## PPO代码
1️⃣ 采样
2️⃣ reward + KL
3️⃣ GAE advantage
4️⃣ PPO loss
---
### 1 数据结构
一条 sample:
```text
prompt: x
completion: y = [y1 ... yT]
logprob_old[t] # old policy log π_old(y_t|s_t)
logprob_ref[t] # reference model log π_ref
value[t] # value head V(s_t)
reward_model_score # RM(x,y)
2 采样阶段
for prompt in batch:
completion, logprob_old, value = model.generate(prompt)
logprob_ref = ref_model.logprob(prompt, completion)
reward = reward_model(prompt, completion)
store(
prompt,
completion,
logprob_old,
logprob_ref,
value,
reward
)
注意这里: we use $\pi_\text{old}$ for pure inference, this combine prefill and decode stages. All logprob_old are saved. Then use the $\pi_\text{ref}$ to compute the logprob_ref. This only need to do prefill stage. No need to save compute graph. (Can this stage use quantized model?)
reward shaping
RLHF 通常先把 KL 加进 reward。
rewards = [0]*T
rewards[T-1] = shaped_reward
4 重新计算当前策略 logprob
PPO update 时需要 新策略概率:
logprob_new = model.logprob(prompt, completion)
注意这里: 计算logprob_new,must use the new model and save compute graph. This need backward!!!(bf16 model need this). Alse the value head are generated per token.
5 GAE 计算 advantage
Generalized Advantage Estimation:
advantages = []
returns = []
gae = 0
for t in reversed(range(T)):
delta = rewards[t] + gamma * values[t+1] - values[t]
gae = delta + gamma * lambda_gae * gae
advantages[t] = gae
returns[t] = advantages[t] + values[t]
通常会做 advantage normalization:
advantages = (advantages - mean) / (std + 1e-8)
6 PPO policy loss
importance ratio:
ratio = exp(logprob_new - logprob_old)
clip:
ratio_clipped = clip(ratio, 1-eps, 1+eps)
policy loss:
loss_policy = -mean(
min(
ratio * advantage,
ratio_clipped * advantage
)
)
7 value loss
loss_value = mean(
(value_new - returns)**2
)
有些实现会 clip value update:
value_clipped = value_old + clip(
value_new - value_old,
-value_clip,
value_clip
)
loss_value = max(
(value_new - returns)^2,
(value_clipped - returns)^2
)
8 entropy bonus
鼓励 exploration:
entropy = -sum(p * log p)
loss_entropy = -entropy_coef * entropy
9 总 loss
loss =
loss_policy
+ c1 * loss_value
+ loss_entropy
+ loss_kl(pi_theta, pi_ref)
注意:
KL 已经在 reward 里。
10 完整 PPO step 伪代码
for batch in rollout_buffer:
logprob_new, value_new = model.forward(batch)
ratio = exp(logprob_new - batch.logprob_old)
ratio_clipped = clip(ratio, 1-eps, 1+eps)
loss_policy = -mean(
min(
ratio * batch.advantage,
ratio_clipped * batch.advantage
)
)
loss_value = mean(
(value_new - batch.return)**2
)
entropy = compute_entropy(logprob_new)
loss_kl = compute_kl(logprob_new, logprob_ref)
loss =
loss_policy \
+ c1 * loss_value \
- c2 * entropy \
+ loss_kl
optimizer.step(loss)
11 LLM PPO 的几个关键工程细节
1 prompt token 不参与 loss
mask = completion_mask
loss *= mask
2 每个 batch 会 update 多次
for epoch in range(K_epochs):
ppo_update()
常见:
K_epochs = 4
3 adaptive KL coefficient
目标:
target KL ≈ 0.1
动态调整:
if kl > target:
beta *= 1.5
else:
beta /= 1.5
12 RLHF PPO pipeline 总流程
SFT model
│
▼
generate samples
│
▼
reward model scoring
│
▼
KL penalty
│
▼
GAE advantage
│
▼
PPO update
│
▼
repeat
细节:
用专用的inference engine 来rollout和计算pi_ref。 不用save compute graph,只save logprob_old。这里为了加速pi_ref和pi_old都是低精度!它们可以单独使用gpu进行rollout,和训练gpu形成流水线。
单独用gpu来算reward model,这个模型可以用一个小模型。
用主要的gpu来存放训练模型,训练模型要求计算value head和logprob_new。
┌─────────────────────────────────────────────────────────────────┐
│ Driver / Actor Trainer(控制流) │
└─────────────────────────────────────────────────────────────────┘
│
│ 1. prompts(list[str] 或 token_ids)
▼
┌─────────────────┐ Ray.remote() / ray.put() ┌──────────────┐
│ Rollout (vLLM) │ ◄───────────────────────────────│ Prompt 池 │
│ GPU 0,1 │ │ (可来自 │
└────────┬────────┘ │ DataLoader)│
│ └──────────────┘
│ 2. completion, logprob_old(序列化后放入 Ray Object Store)
▼
┌─────────────────┐ ray.get() / .remote() ┌──────────────┐
│ Ref Model │ ◄──────────────────────────────│ completions │
│ GPU 2 │ (prompt + completion) │ + prompts │
└────────┬────────┘ └──────────────┘
│
│ 3. logprob_ref
▼
┌─────────────────┐ .remote(prompt, completion) ┌──────────────┐
│ Reward Model │ ◄───────────────────────────────│ 同一批数据 │
│ GPU 3 │ │ │
└────────┬────────┘ └──────────────┘
│
│ 4. reward scores
▼
┌─────────────────┐
│ Replay Buffer │ ← 汇总:prompt, completion, logprob_old,
│ (CPU / 共享) │ logprob_ref, value, reward
└────────┬────────┘
│
│ 5. 采样 batch,送入 PPO
▼
┌─────────────────┐
│ Actor + Critic │ 训练 GPU(可单独一组,如 GPU 4,5,6,7)
│ (DeepSpeed) │ - forward:logprob_new, value_new
│ │ - backward:更新策略和 value head
└─────────────────┘
我把我们这段对话里涉及的 TRL、PPO、异步RLHF系统、rollout/训练开销、reward model瓶颈等内容整理成一份 结构化笔记。 我尽量把逻辑重新组织了一下,让它像一份 RLHF系统设计 notes,而不是简单的问答记录。
RLHF / PPO / TRL / OpenRLHF 系统笔记
1 TRL PPO 的基本机制
1.1 PPO 的理论公式
PPO优化目标:
[ r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{old}(a_t|s_t)} ]
[ L = \min(r_t A_t, \text{clip}(r_t, 1-\epsilon,1+\epsilon)A_t) ]
其中:
- πθ:当前策略
- πold:采样时策略
- At:advantage
1.2 工程实现中的 π_old
在工程实现中:
π_old 并不会以模型形式保存
只保存:
old_logprob
计算方式:
ratio = exp(new_logprob - old_logprob)
因此:
π_old ≈ rollout 时记录的 logprob
不需要维护第二个 policy 模型。
2 TRL PPO 的训练流程
2.1 两个阶段
TRL PPO 是 同步训练:
rollout
↓
update
伪代码:
for iteration:
# rollout
responses = model.generate(prompts)
old_logprob = compute_logprob(responses)
reward = reward_model(responses)
store experience
# PPO update
for epoch:
new_logprob = model(responses)
ratio = exp(new - old)
optimize PPO loss
特点:
- rollout 与 update 串行
- 同一 policy
- 不支持异步 pipeline
2.2 rollout 阶段保存的内容
buffer 中通常包含:
prompt
response tokens
old_logprob
value
reward
update 时重新计算:
new_logprob
3 TRL vs OpenRLHF
3.1 TRL 架构
single trainer
rollout
↓
update
↓
rollout
特点:
- 同步
- 实验友好
- 实现简单
3.2 OpenRLHF 架构
OpenRLHF 使用 actor-learner 架构:
Actor workers (rollout)
↓
experience queue
↓
Learner (PPO update)
结构:
+---------+
| learner |
+---------+
↑
experience queue
↑
+------+ +------+ +------+
|actor1| |actor2| |actor3|
+------+ +------+ +------+
4 异步 PPO 的关键思想
4.1 不需要同步 policy
每个 rollout worker:
pull weights
freeze as π_old
rollout
send experience
experience 包含:
prompt
response
old_logprob
reward
learner 不需要 actor 的模型参数。
4.2 不同 worker 的 π_old 可以不同
例如:
actor1 rollout using π_t
actor2 rollout using π_t-5
actor3 rollout using π_t-10
只要:
old_logprob 正确
PPO ratio 仍然成立:
ratio = exp(new_logprob - old_logprob)
4.3 policy lag
异步系统会产生:
π_actor ≠ π_current
例如:
actor rollout: π_100
learner update: π_108
ratio 实际为:
π_108 / π_100
PPO clipping 可以缓解。
4.4 为什么不频繁同步参数
大模型参数很大:
7B model ≈ 14GB
频繁同步成本高。
解决方案:
periodic weight sync
例如:
每 N step refresh
5 RLHF rollout vs training 的计算成本
5.1 rollout 的复杂度
生成 N token:
N × forward
例如:
response length = 128
→ 128 forward
原因:
autoregressive generation
5.2 training 的复杂度
训练时:
sequence forward + backward
复杂度:
≈ 3 × forward
5.3 理论 FLOPs
示例:
rollout: 128 forward
train: 3 forward
所以:
rollout FLOPs > training FLOPs
6 rollout 的优化
现代 RLHF 系统常见优化:
vLLM inference
INT8 / INT4 quantization
KV cache
continuous batching
speculative decoding
这可以大幅提高 rollout 吞吐量。
7 reward model 为什么可能成为瓶颈
7.1 reward model 无法 KV cache
rollout generation:
attention complexity ≈ O(T)
因为:
KV cache
reward model:
full sequence forward
复杂度:
O(T²)
例如:
512 × 512 attention
7.2 reward model 必须完整序列
输入:
[prompt + response]
不能 streaming。
必须等待:
response complete
7.3 batching 不稳定
rollout:
continuous batching
reward:
variable sequence length
padding overhead
7.4 reward model 通常较大
常见配置:
policy = 7B
reward = 7B
甚至:
reward = 13B
7.5 reward 不易量化
reward ranking 对精度敏感:
过度量化 → ranking collapse
通常使用:
bf16 / fp16
8 RLHF PPO 为什么 policy forward 次数少
很多人误以为:
update 也要 generate
其实不是。
8.1 rollout 已经生成 trajectory
rollout 得到:
prompt
response
old_logprob
value
8.2 update 使用 teacher forcing
输入:
prompt + response
只需要:
一次 sequence forward
得到:
new_logprob
value
8.3 PPO ratio
ratio = exp(new_logprob - old_logprob)
8.4 forward 次数对比
示例:
batch = 256
response = 128
ppo_epoch = 4
rollout:
256 × 128 = 32768 forward
update:
256 × 4 = 1024 forward
差距:
~32×
9 PPO reward 的 token-level 传播
RLHF 通常:
reward 只在最后 token
例如:
sequence reward = 0.8
通过:
GAE / return propagation
得到:
token-level advantage
因此:
整条序列都能训练
10 RLHF 系统的真实计算分布
典型 profile:
policy rollout ~35%
reward model ~35%
policy update ~20%
value update ~10%
很多时候:
trainer GPU 等 rollout
总结
RLHF PPO 的关键系统设计:
1 PPO 实现
π_old ≈ old_logprob
不需要保存 old policy。
2 TRL vs OpenRLHF
TRL:
同步 rollout → update
OpenRLHF:
actor-learner 异步 pipeline
3 异步 RLHF
- rollout workers 可使用不同 π_old
- 只需发送 old_logprob
- learner 定期同步权重
4 rollout vs training
rollout: autoregressive (多 forward)
training: teacher forcing (少 forward)
5 reward model
瓶颈原因:
无 KV cache
O(T²) attention
完整序列 forward
batching 差
6 PPO update
无需重新生成:
sequence forward + backward
大幅减少 compute。