Skip to content

fix(data): scope GLM assistant boundary scan to the current turn - #5753

Merged
cuichenx merged 1 commit into
mainfrom
pruprakash/fix_data_glm_boundary_scan_scope
Oct 6, 2026
Merged

cuichenx merged 1 commit into
mainfrom
pruprakash/fix_data_glm_boundary_scan_scope

Conversation

@pruprakash

Copy link
Copy Markdown
Contributor

What does this PR do ?

Fixes GLM-shaped SFT rows aborting the data pipeline with ValueError: AssistantMaskBoundaryConfig did not match any loss-contributing spans in input_ids whenever any turn quotes a role marker such as <|observation|>.

Changelog

  • src/megatron/bridge/data/conversation_processing.py: _conversation_contains_boundary_tokens gains a keyword-only turns; the non-terminal assistant guard passes turns=[turn].
  • tests/unit_tests/models/test_glm52_kimi_k3_minimax_m3_chat.py: 2 tests covering both branches of the guard.

GitHub Actions CI

See the CI section in the Contributing doc for how to trigger the CI. A Nvidia developer will need to approve and trigger the CI for external contributors.

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 add or update any necessary documentation?
  • Does the PR affect components that are optional to install? (Ex: Numba, Pynini, Apex etc)
    • Reviewer: Does the PR have correct import guards for all optional libraries?

Additional Information

  • Root cause: the guard at conversation_processing.py:1449 scanned every turn's payload, but only the current turn renders between content_start and the next role header. Both True and the unknown None abort, so a marker quoted anywhere vetoed the boundary.
  • Blast radius: GLM-shaped templates expose no {% generation %} mask to fall back to and data/collators/sft.py:230 does not catch, so the row killed the training job instead of degrading.
  • Regression? Yes — introduced by [data] fix: preserve GLM historical answer loss #5633 (2d3733eb, 2026-08-19), which added the guard and widened the GLM marker map to <|system|>/<|user|>/<|observation|>. Before it the row was mis-masked, not unloadable. Fail-closed is preserved when the marker is inside the assistant's own payload.
  • Verification: red-green in nvcr.io/nvidian/nemo:nightly — RED (test patch only) 1 failed; GREEN 19 passed in the file, plus 129 passed across test_conversation_processing.py and test_sft_processing.py.
  • Not included: a separate pre-existing defect (the turn_search_start >= turn_limit window from [data] fix: Preserve assistant mask provenance #5166 collapses for a second non-terminal assistant turn under a history-dependent template) is unfixed here — it needs a different window derivation for all templates, not just GLM.

Before resolving a non-terminal assistant span, the boundary guard scanned
every turn's payload, so a role marker quoted in a user, system or tool
message aborted the whole row. GLM-shaped templates expose no {% generation %}
mask to fall back to, so the row raised ValueError out of the data pipeline
rather than degrading. Only the current turn renders inside the region being
searched, so the scan is now restricted to it.

Adds a unit test covering the change (red-green verified).
Detected by: megatron-bridge QA

Signed-off-by: Pruthviraj Prakash <pruprakash@nvidia.com>
@pruprakash pruprakash added bug Something isn't working area:data Dataset builders, preprocessing, and samplers needs-review PR is ready for code review and waiting on a reviewer qa_rcca_done labels Aug 23, 2026
@copy-pr-bot

copy-pr-bot Bot commented Aug 23, 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.

@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

LGTM

The fix correctly narrows the boundary-token scan to the current turn in the rendered_turn_end_roles branch. Only that turn payload renders between content_start and the next role header, so a marker quoted in any other turn can no longer veto the loss boundary and drop the whole mask. The default whole-conversation scan is preserved for the unrelated guard at line 1772, so no behavior change there. Both failure modes are covered by tests (quoted-in-user-turn still masks; quoted-in-assistant-payload still fails closed), and the tokenizer stub now routes content through encode consistently so multi-token quoted content renders the same way in _assistant_tokens and apply_chat_template.

Minor non-blocking note: the docstring says template kwargs are always scanned. Scanning chat_template_kwargs unconditionally even when turns is restricted matches prior behavior, so it looks deliberate.

Suggested test cases (unit, added/exercised by this diff):

  • test_glm_role_marker_quoted_in_a_user_turn_still_masks_the_historical_answer
  • test_glm_role_marker_quoted_in_an_assistant_turn_still_fails_closed
  • test_glm_history_thinking_truncation_preserves_historical_answer_loss
  • test_model_chat_four_way_rendering_and_loss_boundaries

No perf tests impacted.

@yaoyu-33 yaoyu-33 added the needs-more-tests Requires additional L0 and L1 test coverage before merge label Aug 24, 2026
@pruprakash
pruprakash requested a review from yaoyu-33 August 24, 2026 18:08
@pruprakash pruprakash self-assigned this Aug 24, 2026
@pruprakash

Copy link
Copy Markdown
Contributor Author

/ok to test c18b8de

@cuichenx
cuichenx merged commit f1dd762 into main Oct 6, 2026
131 checks passed
@cuichenx
cuichenx deleted the pruprakash/fix_data_glm_boundary_scan_scope branch October 6, 2026 23:32
@qiaochuz-nv

Copy link
Copy Markdown

Retrospective QA-fix tracking issue: #6395. It records the fix authored by @pruprakash and delivered by this merged PR.

This branch was previously deployed

2 inactive deployments
public — c18b8de3 Deployed Aug 24, 2026 by copy-pr-bot[bot] via release / finalize / publish-docs #4961
test — c18b8de3 Deployed Aug 24, 2026 by copy-pr-bot[bot] via cicd-wait-in-queue #20940
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:data Dataset builders, preprocessing, and samplers bug Something isn't working needs-more-tests Requires additional L0 and L1 test coverage before merge needs-review PR is ready for code review and waiting on a reviewer qa_rcca_done

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants