[Bug]: ignore_eos_token keeps EOS in DPO length normalization

Author: primorLeeCreated Aug 22, 2026Updated Aug 22, 2026

软件环境

  • paddlepaddle: 3.3.1 (CPU)
  • paddleformers: current develop
  • Python: 3.12.10

重复问题

  • I have searched the existing issues

错误描述

paddleformers.nn.criterion.dpo_loss.dpo_logps excludes one EOS token from each chosen/rejected log-prob sum when ignore_eos_token=True, but the average_log_prob and normalize_logps branches still divide/scale by response lengths that include that excluded token.

This makes the normalized policy and reference log-probs internally inconsistent. It directly changes the objectives that enable average_log_prob (simpo, ipo, and or), and also affects explicit normalize_logps=True. Because chosen and rejected responses can have different lengths, the error does not cancel in their log-ratio.

稳定复现步骤 & 代码

For a packed pair with boundaries [0, 0, 3, 7], suppose the per-token negative log-probs are:

chosen:  [-1, -2, EOS]
rejected: [-3, -4, -5, EOS]

With ignore_eos_token=True, the aggregated log-probs are -3 and -12. Their effective token counts are therefore 2 and 3, so averaging should return -1.5 and -4.0.

The current implementation divides by the original lengths 3 and 4 and instead returns -1.0 and -3.0. The same stale lengths are used by normalize_logps.

I have a focused fix and regression coverage ready that reuse EOS-adjusted chosen/rejected lengths in both normalization branches.

Source: PaddlePaddle/PaddleFormers