fix(megatron): make linear CE fusion work through VLM wrappers - #3951
Open
dafu-wu wants to merge 1 commit into
Open
fix(megatron): make linear CE fusion work through VLM wrappers#3951dafu-wu wants to merge 1 commit into
dafu-wu wants to merge 1 commit into
Conversation
dafu-wu
force-pushed
the
fix/linear-ce-fusion-vlm-wrapper
branch
from
September 1, 2026 18:38
c5363f9 to
4e48f03
Compare
patch_gpt_model_forward_for_linear_ce_fusion() rebinds GPTModel.forward,
and model_forward() then passes return_logprobs_for_linear_ce_fusion to
the top-level module. For checkpoints that load as a VLM wrapper the
top-level module is not the patched GPTModel, so that kwarg reaches a
forward() that does not accept it:
TypeError: Gemma4VLModel.forward() got an unexpected keyword argument
'return_logprobs_for_linear_ce_fusion'
Gemma-4 is one such case: the HF checkpoint is
Gemma4ForConditionalGeneration, so the top-level module is Gemma4VLModel
and GPTModel is only its inner .language_model. This also affects
text-only runs, where the wrapper is otherwise inert.
The failure surfaces in the first forward pass, i.e. after the full
allocation and model load, and its message names neither the config knob
nor the reason.
Validate right after get_model(), next to where the patch is applied, and
raise NotImplementedError naming the offending module type and the knob
to change. The walk unwraps Float16Module/DDP-style .module chains so
ordinary wrapped models keep working.
Signed-off-by: dafu-wu <wuchengyi2006@163.com>
dafu-wu
force-pushed
the
fix/linear-ce-fusion-vlm-wrapper
branch
from
September 1, 2026 18:49
4e48f03 to
51f3aad
Compare
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.
What does this PR do ?
Makes linear CE fusion usable for checkpoints whose top-level module wraps the
GPTModel(VLM wrappers), instead of failing in the first forward pass with an opaqueTypeError.Changelog
nemo_rl/models/megatron/train.pyfind_linear_ce_fusion_target(): returns the innerGPTModelwhen a wrapper hides it, andNonewhen the invoked module already is the patchedGPTModel(afterFloat16Module/DDP-style.moduleunwrapping) or when noGPTModelis reachable. The walk checks.language_modelat each level before descending, and is depth-bounded._armed_linear_ce_fusion(): sets a per-instance flag on that inner model for the duration of the call and always restores it in afinally, so it cannot leak into later non-fused forwards.model_forward()now passes the kwarg as before for unwrapped models, and arms the inner model instead when a wrapper is in the way.nemo_rl/distributed/model_utils.py: the patched forward honors the per-instance flag.nemo_rl/models/megatron/setup.py: keep a startup guard, but only reject models where noGPTModelis reachable at all -- those would silently never run the fused path.Background
patch_gpt_model_forward_for_linear_ce_fusion()rebindsGPTModel.forward, andmodel_forward()passesreturn_logprobs_for_linear_ce_fusionto the module it invokes. When a checkpoint loads as a VLM wrapper, that module is not the patchedGPTModel:Gemma-4 is one such case: the HF checkpoint is
Gemma4ForConditionalGeneration, so the invoked module isGemma4VLModelandGPTModelis only its.language_model. Fused logprobs were therefore unusable there -- including for text-only runs, where the wrapper is otherwise inert. That matters at scale, since the fused path exists specifically to avoid materializing the[B, S, vocab]fp32 logits tensor.Why arming rather than forwarding the kwarg
The wrapper already forwards everything the fused path needs (
labels,decoder_input,packed_seq_params) to the inner model -- only the request could not get through.return_logprobs_for_linear_ce_fusionis introduced by this repo's monkey-patch, not part of the upstreamGPTModelAPI, so teaching every wrapper to declare it would push that coupling into models NeMo-RL does not own. Arming the instance keeps it here.Unwrapped models are unaffected: they keep receiving the kwarg directly.
GitHub Actions CI
A NVIDIA developer will need to approve and trigger the CI for external contributors.
Before your PR is "Ready for review"
Pre checks: