Skip to content

feat: by-handle payload fields table (TRR weights, score-centering logprobs) - #3904

Closed
faresobeid wants to merge 1 commit into
feat/payload-segmentsfrom
feat/payload-fields
Closed

faresobeid wants to merge 1 commit into
feat/payload-segmentsfrom
feat/payload-fields

Conversation

@faresobeid

@faresobeid faresobeid commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #3902 (by-handle payloads). Parked: only needed for TRR / score centering by handle. Not for review now.

What

Each by-handle per-token field is one line in PAYLOAD_FIELDS (transports/payload.py), so Total Router Recall weights and score-centering mask logprobs can travel by handle when those features come back, with no further reader or packing changes:

PAYLOAD_FIELDS = {
    "routed_experts": PayloadField(0, "inputs"),
    "routed_expert_weights": PayloadField(0.0, "inputs"),
    "sampling_mask": PayloadField(-1, "labels", ragged=True),
    "sampling_mask_logprobs": PayloadField(-math.inf, "sequence", ragged=True),
}

Each entry gives the fill value and the window a trainer rank reads on text micro batches: its CP chunk of inputs (routing), its CP chunk shifted onto labels (masks), or the whole sequence at the tokens' own positions (values the loss reads after the CP gather). Multimodal micro batches read every field whole, as before.

  • Ragged fields: PayloadField.ragged marks sampling_mask and sampling_mask_logprobs. feat: pass router-replay ids and sampling masks by handle on multi-node runs #3902 stores masks as CSR; this generalizes that layout to any ragged field (int32 values for an int fill, float32 for a float fill).
  • Reader (read_field / data._read_payload, called from prepare_micro_batch): dtype-aware (float fields as float32, int fields as int32) and window-driven. Each tensor comes back under the TensorMicroBatch key of the same name and replaces only that inline field.
  • Orchestrator: the last-token row repeat and the drop-on-gap in trajectories._sample_payload apply to every inputs field; dummy batches keep only inputs fields; prepare_sample's cut-out placeholder covers every non-inputs field.

When the features come back

  • Score centering (feat: exact score centering over the sampling mask (arXiv:2609.20807) #3794): it unpacks (ids, logprobs) from the mask in _PackedOutputs. The by-handle writer then adds one line next to the mask:
    arrays.append(("sampling_mask_logprobs", prompt_len, (mask.counts, logprobs)))
    The trainer gets sampling_mask_logprobs over the whole sequence; positions without logprobs are -inf (the inline path uses -9999; both give zero centering weight).
  • TRR (no open prime-rl PR; feat(rl): add experimental Total Router Recall #3509 is closed): write the fp32 weights as routed_expert_weights next to uint8 ids (5 B per layer and top-k slot instead of 8 B for int32 [ids | weight bits]), and concatenate them back into the layout MoE.forward expects after the read. Under P/D the router would stitch this field like routed_experts.

Tests

@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch from a4a98c5 to 0d8d29a Compare October 6, 2026 14:53
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from 92de07d to 84ec215 Compare October 6, 2026 14:53
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch from 0d8d29a to 1ed3731 Compare October 6, 2026 17:29
@faresobeid
faresobeid force-pushed the feat/payload-fields branch 2 times, most recently from a1eeaea to 36b8e7f Compare October 7, 2026 00:39
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch 2 times, most recently from 9b43ad3 to 8e3e321 Compare October 7, 2026 12:43
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from 36b8e7f to b284c19 Compare October 7, 2026 12:43
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch from 8e3e321 to 4f6d3c1 Compare October 7, 2026 13:59
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from b284c19 to 230c022 Compare October 7, 2026 13:59
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch from 4f6d3c1 to 47d764e Compare October 8, 2026 14:40
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from 230c022 to 223a784 Compare October 8, 2026 14:40
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from 223a784 to be77a0e Compare October 8, 2026 19:16
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch from 47d764e to 968669e Compare October 8, 2026 19:16
@faresobeid
faresobeid force-pushed the feat/payload-fields branch from be77a0e to aae02ad Compare October 9, 2026 23:48
@faresobeid
faresobeid force-pushed the feat/payload-by-handle branch 2 times, most recently from 5baf380 to fcfb7f9 Compare October 10, 2026 04:00
@faresobeid
faresobeid changed the base branch from feat/payload-by-handle to feat/payload-segments October 10, 2026 15:11
@faresobeid
faresobeid force-pushed the feat/payload-segments branch from 123233f to a0690a6 Compare October 10, 2026 15:21
@faresobeid
faresobeid force-pushed the feat/payload-fields branch 3 times, most recently from dd7f155 to 9be553c Compare October 10, 2026 16:56
…gprobs)

PAYLOAD_FIELDS declares each by-handle field once with its fill value and
read window: routed_experts and routed_expert_weights (input positions,
CP chunk), sampling_mask (label positions), sampling_mask_logprobs (whole
sequence, consumed after the CP gather). The writer, packing, truncation,
dummy batches and the trainer reader go through the table, so a new field
is one line plus its writer.

Ragged fields (sampling_mask, sampling_mask_logprobs) are marked in the table
and stored as CSR, int32 values for an int fill and float32 for a float fill.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant