AReaL 中的 PPO/GRPO 算法家族:从 GRPO 到 DAPO、SAPO、GSPO 的配置切换与源码原理
2026/9/17 20:38:21 网站建设 项目流程

AReaL 中的 PPO/GRPO 算法家族:从 GRPO 到 DAPO、SAPO、GSPO 的配置切换与源码原理

【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple & Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL

本文以 docs/en/algorithms/grpo_series.md 为骨架,系统讲解 AReaL(The RL Bridge for LLM-based Agent Applications)中对 PPO 一族强化学习算法的支持:Vanilla PPO、GRPO、Dr.GRPO、LitePPO、RLOO、DAPO、SAPO、GSPO,以及可任意组合的 IcePop / KPop token 掩码策略。读者将掌握这些算法在 AReaL 中「同一份执行代码、仅靠 YAML 参数切换」的使用方法、NormConfig/PPOActorConfig等核心配置项的语义,以及 GAE 时间步、动态 GAE lambda 与turn_ids协议等源码级实现细节,从而能针对自己的 RL 任务快速实验不同算法组合。

算法家族全景

AReaL 将下列 PPO-like 算法统一收敛到同一个基目标函数上,它们之间的差异主要体现为:优势/奖励的归一化策略(mean_level/std_level/mean_leave1out)、裁剪机制(对称 / 非对称 / 软门控)、重要性采样层级(token 级 / sequence 级)、以及是否使用解耦损失与 token 掩码等。正因为差异被收敛到少数几个配置参数上,在 AReaL 中只需修改 YAML 配置即可在不同算法之间切换:

  • Vanilla PPO:使用学习到的价值函数(critic)通过 GAE 估计优势;
  • GRPO(DeepSeekMath):去掉 critic,用组内奖励均值/标准差做基线;
  • Dr.GRPO:组内做均值归一化、关闭 std 缩放;
  • LitePPO:组内均值归一化、batch 级 std 缩放;
  • RLOO:leave-one-out 基线;
  • DAPO:非对称裁剪 + 动态采样 + 超长惩罚;
  • SAPO:用软 sigmoid 门控替代硬裁剪;
  • GSPO(Qwen3):sequence 级重要性采样比率;
  • IcePop:基于重要性比率的 token 掩码(可与上述任一算法组合);
  • KPop:基于双向二值 KL 散度的 token 掩码(可与上述任一算法组合)。

所有算法共享同一套 rollout / trainer 执行管线,对应入口为 examples/math/gsm8k_rl.py。

快速上手:统一的执行模式与配置切换

所有算法使用完全相同的执行方式,官方推荐直接修改配置文件(YAML)中的参数,而不是修改代码:

后端命令
localpython3 examples/math/gsm8k_rl.py --config examples/math/gsm8k_<algo>.yaml scheduler.type=local
raypython3 examples/math/gsm8k_rl.py --config examples/math/gsm8k_<algo>.yaml scheduler.type=ray
slurmpython3 examples/math/gsm8k_rl.py --config examples/math/gsm8k_<algo>.yaml scheduler.type=slurm

<algo>替换为:ppogrpodrgrpolitepporloogspodapo_dynamic_bssapoicepopkpop,即可命中examples/math/下对应的现成配置文件。scheduler.type通过命令行覆盖选择本地多进程、Ray 集群或 Slurm 调度。

通过 CLI 覆盖切换算法

不修改 YAML,直接用命令行参数覆盖也可以实现算法切换:

# 从 GRPO 配置切到 Dr.GRPO python3 examples/math/gsm8k_rl.py \ --config examples/math/gsm8k_grpo.yaml \ scheduler.type=local \ actor.adv_norm.mean_level=group \ actor.adv_norm.std_level=null # 从 GRPO 配置切到 GSPO python3 examples/math/gsm8k_rl.py \ --config examples/math/gsm8k_grpo.yaml \ scheduler.type=local \ +actor.importance_sampling_level=sequence # 从 GRPO 配置切到 SAPO python3 examples/math/gsm8k_rl.py \ --config examples/math/gsm8k_grpo.yaml \ scheduler.type=local \ +actor.use_sapo_loss=true \ +actor.sapo_tau_pos=1.0 \ +actor.sapo_tau_neg=1.05 \ actor.use_decoupled_loss=false

注意:当覆盖的键不存在于原 YAML中时,需要使用+前缀(如+actor.use_sapo_loss=true);对已存在的键直接赋值即可。

核心配置参数

所有配置均在 areal/api/cli_args.py 中定义,主要位于PPOActorConfig(约 L1715 起)与NormConfig(约 L46 起)两个 dataclass 中。完整的参数说明可参考 CLI 配置参考。

奖励与优势归一化(actor.reward_normactor.adv_norm

NormConfig控制奖励(reward)与优势(advantage)的归一化方式,核心字段如下:

参数类型取值说明
mean_levelstr | None"batch""group"None计算均值(居中)的层级
std_levelstr | None"batch""group"None计算标准差(缩放)的层级
mean_leave1outbooltruefalse是否使用 leave-one-out 均值(剔除当前样本)
std_unbiasedbooltruefalse是否使用无偏标准差计算(默认true
epsfloat-除标准差时避免除零的小常数(默认1e-5
group_sizeint-组级归一化时的组大小

从 cli_args.py 的源码可见,mean_levelstd_level__post_init__中会校验取值必须为"batch""group"None;同时NormConfig.uses_group_statistics属性判断是否任一字段为group(组内统计),这一属性在后续批量组筛选逻辑中会被复用。

语义上,"batch" 层级在整个全局 batch 上计算均值/标准差,而 "group" 层级在组内计算(例如共享同一 prompt 的多条轨迹)。组边界来源于 rollout 批次的元数据TrajBatchMeta.traj_group_sizes而非group_size,因此当组内样本被过滤导致各组大小不等时,仍然按 prompt 逐组归一化;group_size仅在元数据缺失时作为固定步长的回退方案。将mean_levelstd_level设为None分别跳过均值减法或标准差缩放。

如果整个字段被省略(例如 YAML 中写adv_norm: null),则不执行任何归一化。示例:

actor: adv_norm: null reward_norm: mean_level: group std_level: group group_size: ${gconfig.n_samples}

AReaL 默认实践:默认配置使用std_level: batch做优势归一化。这是 AReaL 团队在多种 RL 应用(从 StarCraft 等游戏 AI 到 LLM 的 RLHF、推理、Agent 场景)中一贯的标准做法。虽然 Dr.GRPO 建议std_level: null以获得潜在的性能提升,AReaL 为保持向后兼容仍保留std_level: batch;想要 Dr.GRPO 风格行为的用户应设置actor.adv_norm.std_level=null

裁剪策略(actor.eps_clip*

参数类型默认值说明
eps_clipfloat0.2下界裁剪:比率被裁剪到[1-eps_clip, ...]
eps_clip_higherfloat | NoneNone上界裁剪:设置后比率被裁剪到[1-eps_clip, 1+eps_clip_higher]

eps_clip_higherNone时使用对称裁剪:$\text{clip}(r, 1-\epsilon, 1+\epsilon)$。

当设置eps_clip_higher(DAPO 风格)时使用非对称裁剪:$\text{clip}(r, 1-\epsilon_{\text{low}}, 1+\epsilon_{\text{high}})$。

在 cli_args.py 中,eps_clip_higher的注释还说明:当设置eps_clip_higher时,eps_clip作为下界值使用。此外源码还暴露了c_clip(dual clipping factor,必须大于 1.0,None表示禁用)这一相关参数。

重要性采样层级(actor.importance_sampling_level

参数类型取值说明
importance_sampling_levelstr"token""sequence"计算重要性比率的层级
  • "token"(默认):标准的逐 token 重要性比率(GRPO、PPO 等);
  • "sequence"(GSPO):逐 token 比率的 sequence 级几何平均。

算法配置矩阵

下表给出各算法在 AReaL 中对应的推荐参数设置(同一列即为该算法的配置签名):

算法adv_norm.mean_leveladv_norm.std_leveladv_norm.mean_leave1outimportance_sampling_level特殊设置
PPObatchbatchfalsetoken需要 critic 模型
GRPObatchbatchfalsetoken-
Dr.GRPOgroupnullfalsetoken-
LitePPOgroupbatchfalsetoken-
RLOOgroupnulltruetoken-
GSPObatchbatchfalsesequence-
DAPObatchbatchfalsetoken非对称裁剪、动态采样
SAPObatchbatchfalsetokenuse_sapo_loss=true
IcePopbatchbatchfalsetokenrejection_sampling.metric=ratio
KPopbatchbatchfalsetokenrejection_sampling.metric=binary_kl

注意:表中的 "GRPO" 行反映的是 DeepSeekMath 原始论文的公式;AReaL 默认的 GRPO 配置已移除长度归一化项(详见下文「AReaL 实现要点」),例如 examples/math/gsm8k_grpo.yaml 实际使用reward_norm: {mean_level: group, std_level: group}adv_norm: {mean_level: batch, std_level: batch}的组合。

这些配置在examples/math/下均有现成文件可对照,例如 gsm8k_liteppo.yaml 中reward_norm.std_level: batch、gsm8k_rloo.yaml 中adv_norm.mean_leave1out: true、gsm8k_gspo.yaml 中actor.importance_sampling_level: sequence

算法详解与专属选项

Vanilla PPO

Vanilla PPO 使用学习到的价值函数(critic)通过 GAE 估计优势,其关键配置差异在于需要独立的critic:配置段(包含自己的模型与优化器)。完整配置示例见 examples/math/gsm8k_ppo.yaml。

GRPO(DeepSeekMath)

GRPO 目标函数为:

$$ J_{\text{GRPO}}(\theta) = \mathbb{E}{\substack{q \sim P(Q), \ {o_i}{i=1}^G \sim \pi_{\theta_{\text{old}}}(O \mid q)}} \left[ \frac{1}{G} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \min\left( r_{i,t}(\theta) \hat{A}{i,t}, \text{clip}\left( r{i,t}(\theta), 1-\epsilon, 1+\epsilon \right) \hat{A}{i,t} \right) - \beta D{\mathrm{KL}}\left[ \pi_\theta \middle| \pi_{\text{ref}} \right] \right] $$

其中:

$$ r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,<t})}, \quad \hat{A}{i,t} = \frac{r_i - \text{mean}({r_i}{i=1}^G)}{\text{std}({r_i}_{i=1}^G)}. $$

与 PPO 相比,GRPO 不需要 critic:同一 prompt 采样出 G 条响应,组内奖励均值/标准差即作为优势基线。

RLOO(REINFORCE Leave-One-Out)

RLOO 通过求取其他采样响应的奖励均值(剔除当前响应)来估计基线:

$$ J_{\text{RLOO}}(\theta) = \mathbb{E}{\substack{q \sim P(Q), \ {o_i}{i=1}^G \sim \pi_{\theta_{\text{old}}}(O \mid q)}} \left[ \frac{1}{G} \sum_{i=1}^G \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} \min\left( r_{i,t}(\theta) \hat{A}{i,t}, \text{clip}\left( r{i,t}(\theta), 1-\epsilon, 1+\epsilon \right) \hat{A}_{i,t} \right) \right] $$

其中:

$$ \hat{A}{i,t} = r_i - \frac{1}{G-1} \sum{j \neq i} r_j. $$

在 AReaL 中,仅需设置actor.adv_norm.mean_leave1out=true即可实现该 leave-one-out 基线(见 gsm8k_rloo.yaml)。

GSPO(Group Sequence Policy Optimization)

GSPO 在 sequence 级而非 token 级计算重要性采样比率:

  • 标准 PPO(token 级)

$$ r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,<t})} $$

  • GSPO(sequence 级)

$$ r_i(\theta) = \exp\left(\frac{1}{|o_i|}\sum_{t=1}^{|o_i|} \log\frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,<t})}\right) $$

即对逐 token 比率取对数平均后再指数化(几何平均)。配置上只需设置actor.importance_sampling_level: sequence,见 gsm8k_gspo.yaml。

SAPO(Soft Adaptive Policy Optimization)

SAPO 用软 sigmoid 门控替代 PPO 的硬裁剪,提供平滑梯度与非对称控制:

  • 标准 PPO:$L^{\text{PPO}} = -\mathbb{E}_t[\min(r_t A_t, r_t^{\text{clip}} A_t)]$
  • SAPO(软门控)
    • 正优势:$g_t^+ = \frac{4}{\tau_{\text{pos}}} \sigma(\tau_{\text{pos}} (r_t - 1))$
    • 负优势:$g_t^- = \frac{4}{\tau_{\text{neg}}} \sigma(\tau_{\text{neg}} (r_t - 1))$
    • 损失:$L^{\text{SAPO}} = -\mathbb{E}_t[g_t A_t]$,其中 $g_t = g_t^+$(若 $A_t > 0$),否则 $g_t^-$
参数类型默认值说明
actor.use_sapo_lossboolfalse启用 SAPO 损失以替代 PPO 裁剪
actor.sapo_tau_posfloat1.0正优势的温度
actor.sapo_tau_negfloat1.05负优势的温度

注意:SAPO 要求actor.use_decoupled_loss=false(cli_args.py 中use_sapo_loss的注释也明确它与 PPO 裁剪互斥)。

actor: use_sapo_loss: true sapo_tau_pos: 1.0 sapo_tau_neg: 1.05 use_decoupled_loss: false

完整示例见 gsm8k_sapo.yaml,其中同时通过recompute_logprob: falseuse_decoupled_loss: false显式关闭了解耦损失路径。

DAPO

DAPO 引入非对称裁剪与动态采样(dynamic sampling):当某 prompt 下所有响应全对或全错时,该组样本被排除在训练之外。

$$ J_{\text{DAPO}}(\theta) = \mathbb{E}{\substack{(q,a) \sim \mathcal{D}, \ {o_i}{i=1}^G \sim \pi_{\theta_{\text{old}}}(o \mid q)}} \left[ \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \min\left( r_{i,t}(\theta) \hat{A}{i,t}, \text{clip}\left( r{i,t}(\theta), 1-\epsilon_{\text{low}}, 1+\epsilon_{\text{high}} \right) \hat{A}_{i,t} \right) \right] $$

其中 $\hat{A}{i,t}$ 是组归一化优势,$r{i,t}(\theta)$ 是 token 级策略比率。

非对称裁剪参数:

参数类型默认值说明
actor.eps_clipfloat0.2下界裁剪值
actor.eps_clip_higherfloat-上界裁剪值(设置后启用非对称)

gsm8k_dapo_dynamic_bs.yaml 中使用eps_clip: 0.2eps_clip_higher: 0.28构成非对称裁剪区间。

超长惩罚参数:

参数类型默认值说明
actor.overlong_reward_penaltyboolfalse对超长响应启用惩罚
actor.overlong_tokensint-视为超长的尾部 token 数量
actor.overlong_penalty_factorfloat-应用于超长响应的惩罚因子

动态采样:

AReaL 通过传入PPOTrainer.train()dynamic_filter_fn支持动态采样。该函数接收从同一 prompt 采样的分组轨迹,返回布尔值表示是否接受该组进入训练:

trainer.train( workflow=..., dynamic_filter_fn=lambda x: 0 < x["rewards"].mean() < 1 )

默认情况下,AReaL 使用固定 batch size + 动态过滤:持续等待直到收集满batch_size个被接受的样本才进行训练。这与部分 DAPO 实现(先收集一整批样本再统一过滤)的动态 batch size 方案不同。控制 batch 大小的参数如下:

参数类型默认值说明
dynamic_bsboolfalse启用动态 batch size

gsm8k_dapo_dynamic_bs.yaml 顶层即设置了dynamic_bs: true

IcePop

IcePop 将重要性比率 $r_{i,t} = \frac{\pi_\theta(o_{i,t} \mid q, o_{i,<t})}{\pi_{\theta_\text{old}}(o_{i,t} \mid q, o_{i,<t})}$($\pi_\theta$ 为当前训练策略,$\pi_{\theta_\text{old}}$ 为 rollout 使用的行为策略)落在可配置区间 $[\alpha, \beta]$ 之外的 token 从损失中掩码掉——比率过低或过高的 token 都被排除。

IcePop 通过rejection_sampling配置实现,metric=ratio

actor: use_decoupled_loss: true rejection_sampling: level: token action: mask metric: ratio lower: 0.5 upper: 5.0
参数类型默认值说明
actor.rejection_sampling.metricstr-设为ratio即 IcePop
actor.rejection_sampling.lowerfloat0.5重要性比率下界
actor.rejection_sampling.upperfloat5.0重要性比率上界

注意:IcePop 要求actor.use_decoupled_loss=true,否则rejection_sampling不生效。完整示例见 examples/math/gsm8k_icepop.yaml(其中lower: 0.5upper: 5.0level: tokenaction: mask均与上表一致)。

KPop

KPop 掩码掉双向二值 KL 散度超过阈值的 token。对每个 token 计算:

$$\text{KL}{\text{fwd}} = \text{KL}(P\theta | P_{\theta_\text{old}}), \quad \text{KL}{\text{rev}} = \text{KL}(P{\theta_\text{old}} | P_\theta)$$

其中每个 token 的概率被看作一个 Bernoulli 参数:$\text{KL}(P | Q) = p \log \frac{p}{q} + (1-p) \log \frac{1-p}{1-q}$。满足 $\max(\text{KL}{\text{fwd}}, \text{KL}{\text{rev}}) > \phi$ 的 token 被掩码(这里的 $\phi$ 对应actor.rejection_sampling.upper)。

KPop 通过rejection_sampling配置实现,metric=binary_kl

actor: use_decoupled_loss: true rejection_sampling: level: token action: mask metric: binary_kl upper: 2.0
参数类型默认值说明
actor.rejection_sampling.metricstr-设为binary_kl即 KPop
actor.rejection_sampling.upperfloat2.0KL 散度阈值($\phi$)

注意:KPop 仅支持action=mask(不支持clamp),且binary_kl不使用lower;KPop 同样要求actor.use_decoupled_loss=true,否则rejection_sampling不生效。完整示例见 examples/math/gsm8k_kpop.yaml(metric: binary_klupper: 2.0)。

核心概念:Rewards、Advantages 与 GAE

Rewards:AReaL 假设基于结果的奖励(outcome-based rewards)。每条轨迹(可能由拼接的 LLM 输入-输出对组成)在sequence 级获得单个标量奖励,而非 token 级。

Advantages:AReaL 为轨迹中每个输出 token 计算逐 token 优势。PPO 将结果奖励视为最后一个 token 的奖励,前面所有 token 的奖励为 0;随后通过广义优势估计(GAE)做标准折扣与 TD-error 反向传播得到每个 token 的优势。在默认的 token 级时间步递归下,当discount=1gae_lambda=1、critic 值为零且禁用 KL 正则时,最终结果奖励实际上被广播给每个生成 token。

GAE 时间步单位(actor.gae_timestep_unit

actor.gae_timestep_unit决定 GAE 是在生成 token上推进还是在**生成轮次(turn)**上推进。prompt、工具、padding 及其他被掩码的位置不消耗 GAE 时间步。该参数在 cli_args.py 中定义,取值"token""turn"

Token 级 GAE

token是默认值,保留 AReaL 的原始行为。对连续活跃的生成 token:

$$ \delta_t = r_t + \gamma V_{t+1} - V_t, \qquad A_t = \delta_t + \gamma \lambda A_{t+1}, \qquad G_t = A_t + V_t, $$

其中 $\gamma$ 是actor.discount,$\lambda$ 是由actor.gae_lambda解析出的每条轨迹的值。奖励 $r_t$ 包含结果奖励增量与 token 级 KL 惩罚。以 EOS 结束的轨迹使用零终端 bootstrap,而无 EOS 的被截断轨迹则从最终价值估计处 bootstrap。

Turn 级 GAE

turn将每个非空生成轮次视为一个宏时间步。对轮次 $u$,AReaL 将其任务奖励增量求和为 $r_u^{\mathrm{task}}$,并取该轮次第一个活跃动作 token 位置的 $V_u$,然后计算:

$$ \delta_u^{\mathrm{task}} = r_u^{\mathrm{task}} + \gamma V_{u+1} - V_u, \qquad A_u^{\mathrm{task}} = \delta_u^{\mathrm{task}} + \gamma \lambda A_{u+1}^{\mathrm{task}}. $$

任务优势 $A_u^{\mathrm{task}}$ 与 critic 目标 $G_u=A_u^{\mathrm{task}}+V_u$ 被广播给该轮次内的每个活跃 token。token 级 KL 被有意排除在 turn 递归与 critic 目标之外:在可选的actor.adv_norm之前,轮次 $u$ 中 token $j$ 的 actor 优势为 $A_{u,j}=A_u^{\mathrm{task}}+r_{u,j}^{\mathrm{KL}}$。这避免了把一轮的 KL 惩罚求和后再广播回每个 token 的做法。

动态 GAE lambda

actor.gae_lambda既接受静态 float,也接受指向可调用对象的点分路径(dotted path)。actor.gae_lambda_kwargs向该可调用对象传递关键字参数,静态 float 时被忽略。可调用对象接收一个 context,内含三个形状为[B]的 tensor:

  • effective_token_lengths:活跃生成 token 数(含活跃的 EOS);
  • turn_counts:非空生成轮次数,token 模式下无turn_ids时为 0;
  • timestep_lengths:由gae_timestep_unit选定的长度 $L$。

可调用对象必须为每条本地轨迹返回一个有限的浮点 lambda,即同设备上形状为[B]的 tensor,且该返回值用于该轨迹的所有选定时间步。

AReaL 内置两个长度感知函数(实现在 areal/trainer/ppo/lambda_fn.py):

函数路径Kwargs定义
areal.trainer.ppo.lambda_fn.vapo_length_adaptive_gaealpha > 0$\lambda=\max(0, 1 - 1/(\alpha L))$($L>0$);$L=0$ 时取 0
areal.trainer.ppo.lambda_fn.relative_position_gae_lambda0 < q <= 1$\lambda=q^{1/(L-1)}$($L\ge2$);$L=1$ 取 1,$L=0$ 取 0。相对保持(relative-retention)解释假设 $\gamma=1$

从源码看,vapo_length_adaptive_gae会校验alpha必须为正数,对长度做clamp_min(1.0)后计算并clamp_min(0.0)relative_position_gae_lambda会校验q必须是 $(0,1]$ 内的有限数。二者都由resolve_gae_lambda_fn统一解析:静态 float 走constant_gae_lambda快速路径,字符串则通过import_from_string动态导入。

示例配置:

actor: gae_timestep_unit: turn gae_lambda: areal.trainer.ppo.lambda_fn.relative_position_gae_lambda gae_lambda_kwargs: q: 0.5

自定义 workflow 的turn_ids契约

Turn 级 GAE 要求 workflow 返回原始、与 token 对齐turn_ids;actor 内部会将其与 next-token 预测掩码对齐。该 tensor 必须满足:

  • input_idsloss_mask形状相同(batch 为[B, S]);
  • 使用整数 dtype(建议使用有符号整数,因为需要-1哨兵值);
  • 给每个活跃生成 token 分配[0, S)内的 ID;
  • 保持活跃 ID 在时间上非递减,同一 assistant 轮次内的所有 token 使用同一个 ID;
  • 对 prompt、user、tool、padding 及其他非损失位置使用-1

编号允许有空洞且不消耗 GAE 时间步,但仍建议从 0 开始连续编号。自定义 workflow 可以按如下方式构造该字段(不要在 workflow 中 roll 它):

turn_ids += [-1] * input_len + [turn_idx] * resp.output_len result["turn_ids"] = torch.tensor(turn_ids, dtype=torch.int32).unsqueeze(0)

AReaL 实现要点:与原始论文的差异

AReaL 的 GRPO 实现与 DeepSeekMath 原始论文相比有两处关键差异:

长度归一化(Length Normalization):AReaL 从原始 GRPO 目标中移除了逐 token 长度归一化项。这与 Dr.GRPO 的建议一致,消除了优势估计中的偏差。

KL 正则化(KL Regularization):AReaL 不直接将 KL 散度项加进目标函数,而是采用 PPO 风格、将 KL 正则并入 actor 优势,由actor.kl_ctl控制(cli_args.py 中默认kl_ctl=0.1,可选k1/k2/k3估计器)。在 token 模式下,KLEstimator惩罚在 GAE 之前被加入逐 token 奖励;在 turn 模式下,它保持为 token 局部的 actor 惩罚,不进入 turn 递归与 critic 目标。

实践建议与延伸阅读

  • 以 GRPO 为起点:多数实验可以从 examples/math/gsm8k_grpo.yaml 出发,通过命令行覆盖逐步叠加 Dr.GRPO、GSPO、SAPO 等变体,避免复制粘贴大量重复配置。
  • IcePop / KPop 是可组合的:二者本质是 token 掩码策略,可与列表中任一 RL 算法组合使用,但都要求use_decoupled_loss=true(SAPO 除外,它要求use_decoupled_loss=false)。
  • 多轮/Agent 场景:当处理多轮 agent 轨迹时,优先考虑gae_timestep_unit: turn配合动态 GAE lambda(如relative_position_gae_lambda),并确保自定义 workflow 按上文契约输出turn_ids
  • 源码入口:算法相关配置定义在 areal/api/cli_args.py,GAE lambda 内置函数在 areal/trainer/ppo/lambda_fn.py,GAE 计算与 actor 损失实现可继续阅读 areal/trainer/ppo/gae.py 与 areal/trainer/ppo/actor.py;配置参数全量说明见 CLI 配置参考。

【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple & Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询