feat(rl): add SAO synchronous training baseline with skip-observation GAE, DIS policy loss and value critic ``` - #269
Open
xxyyrr598 wants to merge 5 commits into
Open
Conversation
tpx818
reviewed
Aug 25, 2026
tpx818
reviewed
Aug 25, 2026
| self.model.set_output_embeddings(value_head) | ||
| self.model.config.tie_word_embeddings = False | ||
|
|
||
| @remote_function(dispatch='all', collect='first', lazy_collect=False) |
Collaborator
There was a problem hiding this comment.
这部分代码能否兼容qwen3.5系列的混合注意力模型
Contributor
Author
There was a problem hiding this comment.
原实现仅识别 self_attn/attn,会遗漏 Qwen3.5 混合注意力架构中的 linear_attn(GatedDeltaNet)层,现已将其加入冻结范围并补充测试,确保 full attention 和 linear attention 均被冻结,而 MLP/FFN 与 value head 保持可训练。
tpx818
reviewed
Aug 27, 2026
| self.epsilon_low = epsilon_low | ||
| self.detach_importance_weight = detach_importance_weight | ||
|
|
||
| def _compute_per_token_loss( |
Collaborator
There was a problem hiding this comment.
DIS计算的部分是否可以拆成一个可复用的插件,让其与GRPO可组合
Contributor
Author
There was a problem hiding this comment.
已将 SAO Loss 中的 DIS 计算拆分为独立的内部 PolicyObjective 组件,并由 SAOLoss 组合调用;本次重构未改变原有计算逻辑和数值结果。该接口也可以扩展实现 PPO Clip 等策略目标,从而与 GRPO 等优势估计方式组合使用,但本次 PR 暂未修改 PPO/GRPO,后续如有需要可统一接入。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Summary
This PR adds a complete implementation of the SAO (Skip-Observation Advantage) synchronous correctness baseline to twinkle, including all core algorithmic components plus a GSM8K training example. SAO is an asynchronous RL algorithm designed for Agent / multi-turn reasoning (paper parameters are documented in
cookbook/rl/sao/README.md§11). This PR first lands the full algorithm formulas and a synchronous rollout baseline to validate correctness, providing a clean foundation for a future asynchronous pipeline.Implemented components: Single-Rollout, Direct Double-Sided Importance Sampling (DIS) policy loss, strict double-sided trust region, an independent value critic, Faster Value Update (K=2), a Frozen-Attention critic, Skip-Observation token-level GAE, and length-adaptive policy lambda.
Motivation
The latest
mainalready defines theold_logpsinterface, ragged logp alignment,token-meanaggregation, value model, and GAE semantics. This PR reimplements SAO on top of thatmainfollowing these principles:old_logps; no redundant parameters are introduced.PPOLossand the defaultGAEAdvantagebehavior remain unchanged.Major Changes
New algorithm components
src/twinkle/advantage/sao_gae.pySAOGAEAdvantage: skip-observation token-level GAE. Positions withaction_masks=Trueform the Bellman chain, skipping observation/prompt/padding tokens; supports terminal/truncated semantics (truncated requires a bootstrap value); length-adaptive λ = 1 − 1/(α·l)src/twinkle/loss/sao.pySAOLoss: DIS policy loss. Tokens whose ratio falls outside the strict double-sided trust region (ε_low=0.3 / ε_high=5.0) get zero weight (no gradient); importance weight is detached by default; token-mean aggregationsrc/twinkle/loss/value.pySAOValueLoss: masked MSE critic loss, reusing the PPO/GRPO common alignment codeExtensions & registration
src/twinkle/model/transformers/value_model.py: addsfreeze_attention_for_value_training(freezes attention, trains only MLP + value head) andtrainable_parameter_summary(parameter accounting).src/twinkle/metric/grpo.py: addsSAOMetric— trust-rejection statistics that are unconditional on advantage sign, with closed interval boundaries matching the strict trust region ofSAOLoss.src/twinkle/advantage/__init__.py/loss/__init__.py/metric/__init__.py: registerSAOGAEAdvantage,SAOLoss,SAOValueLoss,SAOMetric.src/twinkle/cli/cli.py: adds SAO args (epsilon_low,detach_importance_weight,critic_updates_per_actor_update,sao_alpha,sao_policy_lambda_adaptive,sao_critic_lambda,freeze_critic_attention).Example & documentation
cookbook/rl/sao/sao_sync.py: GSM8K synchronous training loop (single rollout → save vLLM logps → critic computes fixed returns → K critic updates → recompute advantage → one actor update).cookbook/rl/sao/sao_sync.sh: default launch script (4 policy + 4 critic + 4 sampler GPUs).cookbook/rl/sao/README.md: ~1300-line delivery doc (paper comparison, algorithm principles, line-by-line code walkthrough, log interpretation, experiment protocol, known limitations).Tests (4 new files, +140 lines)
tests/advantage/test_sao_gae.py: observation skipping, zero bootstrap on terminal, bootstrap required on truncated, no cross-batch linking, length-adaptive λ.tests/loss/test_sao.py: strict trust-region boundaries, zero gradient outside the region, detached ratio gradient, ragged alignment and token-mean denominator.tests/model/test_value_model.py: MLP/value head remain trainable after attention freeze.tests/cli/test_cli.py: new field parsing.Correctness Constraints (DIS prerequisites)
SAO's importance ratio requires the rollout and learner log-probs to describe the same distribution, so the training script enforces:
--num-generations 1,--temperature 1.0,--top-p 1.0,--top-k -1,--repetition-penalty 1.0. It also validates at runtime that token/logprob/action-label counts are aligned, and raises otherwise.Known Limitations / Future Work
stop_reason=lengthresponses are treated as terminal (an engineering simplification — no truncated bootstrap).main.Training Results
How to Test
# Run the new unit tests pytest tests/advantage/test_sao_gae.py tests/loss/test_sao.py \ tests/model/test_value_model.py tests/cli/test_cli.py