Skip to content

fix(algorithms): honour the configured KL clamps in the reward-side KL - #3853

Open
tianyi-zhang-02 wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
tianyi-zhang-02:fix-reward-kl-clamp
Open

fix(algorithms): honour the configured KL clamps in the reward-side KL#3853
tianyi-zhang-02 wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
tianyi-zhang-02:fix-reward-kl-clamp

Conversation

@tianyi-zhang-02

Copy link
Copy Markdown
Contributor

What does this PR do ?

Makes the reward-side KL use the clamp values that are configured for it, instead of falling back to calculate_kl's defaults.

Issues

None to close.

Usage

No new config. loss_fn.kl_input_clamp_value / loss_fn.kl_output_clamp_value now reach the reward-side KL as well as the loss-side one.

Before your PR is "Ready for review"

Pre checks:

  • Make sure you read and followed Contributor guidelines
  • Did you write any new necessary tests?
  • Did you run the unit tests and functional tests locally? Visit our Testing Guide for how to run tests (unit only)
  • Did you add or update any necessary documentation? Visit our Document Development Guide for how to write, build and test the docs.

Additional Information

GeneralizedAdvantageEstimator and ReinforcePlusPlusAdvantageEstimator both take a ClippedPGLossConfig and read three things off it:

self.use_kl_in_reward = loss_config.use_kl_in_reward
self.kl_coef = loss_config.reference_policy_kl_penalty
self.kl_type = loss_config.reference_policy_kl_type

The same config also carries kl_input_clamp_value and kl_output_clamp_value, and ClippedPGLossFn passes both into calculate_kl. The estimators did not, so with use_kl_in_reward the configured bounds were silently replaced by the function's own defaults, 20.0 and 10.0.

Same config, same KL approximation, two different bounds depending on which side of the algorithm reads it — and no error either way.

On the tests. Getting them to assert anything took one non-obvious step worth flagging for review: both estimators normalize the advantage globally at the end, so a KL that is constant across the batch normalizes away to all-zeros no matter what the clamp does. My first version of these tests passed with the fix reverted for exactly that reason. The reference logprobs have to diverge by a different amount at each position before the clamp is observable at all.

Mutation-tested: dropping the two kwargs from either call site, and hardcoding a clamp back to its old default, each turn one of these red.

Adjacent to my #3512, which wraps these returns in an AdvantageResult — the tests accept a bare tensor, a (advantages, returns) tuple, or the dataclass, so they survive that rebase whichever lands first. :)

Under use_kl_in_reward, GeneralizedAdvantageEstimator and
ReinforcePlusPlusAdvantageEstimator both call calculate_kl without
input_clamp_value / output_clamp_value, so the user's configured values are
silently replaced by the function defaults (20.0 / 10.0).

They already read reference_policy_kl_penalty and reference_policy_kl_type
off the same ClippedPGLossConfig that carries the two clamps, and
ClippedPGLossFn passes both through -- so setting kl_output_clamp_value moves
the loss-side KL and leaves the reward-side one alone. Same config, same
approximation, two different bounds, no error.

Tests are CPU-only. Note what they had to do to be non-vacuous: both
estimators normalize the advantage globally at the end, so a KL that is
constant across the batch normalizes away to zeros whatever the clamp does.
The reference has to diverge by a different amount at each position for the
clamp to be observable at all.

Mutation-tested: dropping the two kwargs from either call site, and hardcoding
a clamp to its old default, each turn one of these red.

Signed-off-by: Tianyi Zhang <zhangtianyi975@gmail.com>
Signed-off-by: Tianyi Zhang <123608656+tianyi-zhang-02@users.noreply.github.com>
@tianyi-zhang-02
tianyi-zhang-02 requested review from a team as code owners August 26, 2026 18:43
@copy-pr-bot

copy-pr-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-maintainers Waiting on maintainers to respond label Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-request waiting-on-maintainers Waiting on maintainers to respond

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants