Router replay worked only with vLLM generation. The SingleController setup rejected router replay with Megatron generation
(setup.py:1196, before).
This PR
Reshapes the expert routes from Megatron Inference (MInf) into the same per-call rows vLLM already writes, so the rest of the pipeline reads them unchanged.
Status
Proposed â open PR into #4129, under review.
Two pages on this PR, one question each â this one: how the new MInf path compares with the vLLM path.
Router replay makes the trainer use the same experts, per token and per MoE layer, that the
generation engine picked, so the two do not disagree on routing. MInf records one route row per token
except the last: shape [T-1, L, K] for T tokens, L MoE layers and top-K experts
(inference_request.py:917).
But each model call in a multi-turn rollout stores only its new tokens: rows prev_len to T, where
prev_len is the length the earlier turns already stored. So the PR adds one all -1 row and cuts off the
first prev_len rows
(_delta_align_minf_routing_indices).
vLLM also gives [T-1, L, K]; its NeMo-RL worker already adds a final row (filled with experts 0âŠK-1)
and cuts rows the same way. The two paths differ only in where that row is added and what goes in it.
Two engines, one staging row
The same 2-turn rollout through both
Call 1: a 3-token prompt, 4 generated tokens, 7 in all. Call 2 continues it: those 7, then 5 new user tokens
(a 12-token prompt), then 9 generated tokens, 21 in all. The model has 2 MoE layers and picks the top 8 experts.
# call 2 â prev_len = 7 (call 1's whole length), T = 21, so 14 new tokens
MInf routing_indices [20, 2, 8] int16 # one row per token except the last
add one all -1 row â [21, 2, 8] # tq_token_sink.py:451-458
keep rows [7:] â [14, 2, 8] # :459
vLLM routed_experts [20, 2, 8] # also one row per token except the last, utils.py:261
add one 0âŠ7 row â [21, 2, 8] # utils.py:310-322
keep rows [7:] â [14, 2, 8] # vllm_worker_async.py:634
both TQTokenSink.stage: 14 rows == 14 new tokens â staged # tq_token_sink.py:305
Why keep both? vLLM stays the usual generation engine. MInf lets a run generate with
Megatron itself, and until this PR such a run could not use router replay at all. In exchange, the MInf path
is stricter â one bad route costs the whole rollout â and it has no deferred mode yet.
What this means for you. Router replay now works with generation.backend: megatron on the
SingleController + Gym token-capture path, and once the routes are staged the two engines share every line of code.
Before you switch, keep defer_routed_experts_to_policy: false, and expect missing routes to show up as
rejected rollouts rather than warnings. The token at each turn boundary (column 6) gets no replayed route on either
engine; MInf lets the trainer's router choose there, while vLLM forces experts 0âŠ7.