nemo_rl.models.generation.megatron.megatron_worker#
Module Contents#
Classes#
A Bridge import task and its mutable inference destination. |
|
One HF-local shard and the Megatron destination region it populates. |
|
Engine lifecycle, coordinator, HTTP server, and finish-generation machinery. |
|
Refit collective, weight transfer, and engine suspend/resume around refits. |
Functions#
Build the generic GPT layer spec backed by MCore inference linears. |
|
Select MCore inference linears for a Bridge generic-GPT provider. |
|
Resolve the MXFP8 storage required by the grouped-GEMM backend. |
|
Sampling defaults for HTTP requests that omit temperature, top_p or top_k. |
|
Effective DP-coordinator routing policy for this generation config. |
|
Forward configured optional MCore inference settings with validated types. |
|
Apply the optional CUDA graph scope to the engine model. |
API#
- nemo_rl.models.generation.megatron.megatron_worker._inference_optimized_transformer_layer_spec(
- config: Any,
Build the generic GPT layer spec backed by MCore inference linears.
- nemo_rl.models.generation.megatron.megatron_worker._configure_inference_optimized_layer_spec(
- model_provider: Any,
Select MCore inference linears for a Bridge generic-GPT provider.
Only the generic path needs this. Model-specific providers (DeepSeek, MiniMax, GLM, …) install
get_gpt_decoder_block_spec, which already dispatchestransformer_impl='inference_optimized'itself and — unlike the uniform spec built here — gives dense and MoE layers different specs. Overwriting those would rebuild amoe_layer_freqmodel’s dense layers as MoE layers, so leave any non-default spec alone.Non-GPT providers are left alone too. Hybrid/Mamba stacks (Nemotron-H via
HybridModelProvider) are notGPTModelProvidersubclasses and resolveinference_optimizedthrough their own stack spec, so this is a no-op for them rather than an error.
- nemo_rl.models.generation.megatron.megatron_worker._resolve_mxfp8_refit_backend(model_config: Any) str#
Resolve the MXFP8 storage required by the grouped-GEMM backend.
- class nemo_rl.models.generation.megatron.megatron_worker._MegatronRefitTask#
A Bridge import task and its mutable inference destination.
- conversion_task: Any#
None
- destination: Any#
None
- target_id: int#
None
- property param_name: str#
- property cache_key: tuple[int | None, str]#
Stable identity across Bridge task rebuilds.
- property dependencies: tuple[str, ...]#
- property expected_shape: torch.Size#
- property is_mxfp8: bool#
- property is_quantized: bool#
- class nemo_rl.models.generation.megatron.megatron_worker._MegatronBulkRefitPiece#
One HF-local shard and the Megatron destination region it populates.
- spec: Any#
None
- shape: torch.Size#
None
- device: torch.device#
None
- destination: torch.Tensor | None#
None
- nemo_rl.models.generation.megatron.megatron_worker._http_sampling_defaults(
- generation_cfg: Mapping[str, Any],
Sampling defaults for HTTP requests that omit temperature, top_p or top_k.
Training recomputes log probabilities with the configured generation sampling parameters. Without explicit server defaults, an omitted request field falls back to the server’s hardcoded value or to the model’s generation_config.json, so the request would sample off-policy.
- nemo_rl.models.generation.megatron.megatron_worker._resolve_coordinator_policy(
- mcore_generation_config,
Effective DP-coordinator routing policy for this generation config.
Resolved in one place so the engine and the HTTP frontends cannot disagree: if the engine routes on prefix affinity but the frontends skip hashing, the coordinator silently sees no hashes and degrades to load balancing.
- nemo_rl.models.generation.megatron.megatron_worker._apply_optional_inference_config_kwargs(
- inference_config_kwargs: dict[str, Any],
- mcore_generation_config: dict[str, Any],
Forward configured optional MCore inference settings with validated types.
- nemo_rl.models.generation.megatron.megatron_worker._apply_inference_cuda_graph_scope(
- engine_model: megatron.core.transformer.MegatronModule,
- mcore_generation_config: dict[str, Any],
Apply the optional CUDA graph scope to the engine model.
- class nemo_rl.models.generation.megatron.megatron_worker.MegatronGenerationMixin#
Engine lifecycle, coordinator, HTTP server, and finish-generation machinery.
The host class must provide:
model: the megatron module.
cfg: policy config (TypedDict).
rank: global rank (used for logging).
tokenizer: HF tokenizer.
megatron_tokenizer: tokenizer for inference.
processor: optional multimodal processor.
is_generation_colocated: Whether colocated or distributed.
_reserved_http_server_port: driver-reserved server port, or None.
- processor: Optional[Any]#
None
- inference_model#
None
- _colocated_reshard_plan#
None
- _image_preprocessing_config: Optional[Any]#
None
- _gen_model() megatron.core.transformer.MegatronModule#
The model the inference engine wraps.
Returns the dedicated inference-layout model when one exists (colocated reshard), otherwise the shared training model.
- _init_inference_engine_state() None#
Reset all inference-engine attributes to their uninitialized state.
- _get_megatron_inference_wrapper_cls() Optional[type]#
Resolve the configured Megatron inference wrapper, if any.
- Returns:
The wrapper class, or None when no wrapper is configured.
- static _wrapper_supports_modality(
- inference_wrapper_cls: Optional[type],
- modality: str,
Whether the configured inference wrapper advertises
modalitysupport.
- _inference_model_and_media_parts(inference_wrapper_cls=None)#
Return the language model and its optional multimodal parent.
- _vision_pixel_dtype() torch.dtype#
The dtype the vision encoder casts pixels to before encoding them.
Read from the encoder’s own parameters rather than the policy dtype: a config may keep the vision tower in fp32 under a bf16 language model.
- _build_image_preprocessing_config(
- generation_config: dict[str, Any],
Build raw-image preprocessing settings.
- _setup_colocated_cuda_graph_managers() None#
Create inference CUDA-graph managers for shared-model colocated generation.
Colocated policies build the shared training model without CUDA graphs. But CUDA graphs configs MUST be in-place at initialization.
Must run at worker init: colocated reshard is detected via the pending reshard plan (its dedicated inference model is built later, with graphs enabled); the plan is consumed on the first generation cycle.
- get_inference_cuda_graph_capture_count() int#
Inference CUDA graphs captured in this worker process (0 = eager decode).
- _initialize_inference_engine(mcore_generation_config: dict) None#
Initialize the persistent inference engine and client.
- async _start_inference_coordinator()#
Start the inference coordinator and engine loop.
- _sleep() None#
Pause + suspend the engine. No-op if already asleep.
- async _sleep_engine()#
- _wake() None#
Resume + unpause the engine. No-op if already awake.
- async _wake_engine()#
- _start_inference_loop_thread()#
Start a background thread with a persistent event loop for inference.
- _setup_openai_api_server() str#
Start the OpenAI-compatible HTTP server on this worker.
- _run_async_coordinator_start()#
Start the coordinator and engine loop in the background thread.
- finish_generation(*, release_gpu: bool = True) None#
Wind down a generation cycle.
- Parameters:
release_gpu – the caller needs the GPUs for itself (a training step or a checkpoint save), so even a colocated engine must fully stand down. Pass False between generation phases (e.g. after validation) to let a colocated engine keep serving; tearing it down there would discard KV/prefix caches and CUDA graphs for no reason. For non-colocated engines this body reduces to a rotary-cache clear (their engine pause happens in suspend_for_refit).
- prepare_for_generation(tags=None, **kwargs) None#
Enter inference mode and start (or wake) the inference engine.
Idempotent wake: a plain call (no tags) on an already-serving engine returns immediately. Refit-protocol calls (tags) are never skipped.
Called in both colocated and non-colocated setups. Even in non-colocated mode, Megatron’s engine has to be intentionally paused before a refit (and its weights are not detachable), so we have to switch modes around every refit.
- report_dp_openai_server_base_url() Optional[str]#
Return this worker’s OpenAI server base URL (None if not the leader).
- setup_token_capture(
- dp_cfg: nemo_rl.data_plane.interfaces.DataPlaneConfig,
- staging_partition: str,
- *,
- capture_media: bool = False,
Install canonical TQ capture on each MInf model-parallel leader.
capture_mediabuilds the sink/source against the media-enabled staging schema so the stager can hand the engine’s media tensors to TQ beside each call’s tokens. Returns the media column spec the coordinator pinned the staging column to (Nonefor text-only capture and on followers, which host no hooks).
- set_rollout_weight_version(version: int) None#
Stamp subsequent MInf requests with the trainer weight version.
- _build_sampling_params(
- greedy: bool,
- stop_words: Optional[list[str]],
- *,
- return_prompt_tokens: bool = False,
Build mcore SamplingParams for a single request.
- _merge_stop_strings(
- batch_stop_strings: Optional[list[Optional[list[str]]]],
Union the config’s stop_strings with the given per-sample stop strings.
- _sample_vision_tensors(data, index: int)#
Return one sample’s vision tensors from RL PackedTensors.
- _build_prompt_and_multimodal_data(data, index: int)#
Build one pre-expanded token prompt and optional MCore media payload.
- _prepare_data_for_generation(
- data: nemo_rl.distributed.batched_data_dict.BatchedDataDict[nemo_rl.models.generation.interfaces.GenerationDatumSpec],
- greedy: bool = False,
Build prompts, optional media payloads, and sampling parameters.
- _parse_result_to_batched_data_dict(
- data: nemo_rl.distributed.batched_data_dict.BatchedDataDict[nemo_rl.models.generation.interfaces.GenerationDatumSpec],
- result: list,
Pack DynamicInferenceRequest results into a GenerationOutputSpec batch.
- generate(
- *,
- data: nemo_rl.distributed.batched_data_dict.BatchedDataDict[nemo_rl.models.generation.interfaces.GenerationDatumSpec],
- greedy: bool = False,
Synchronous batched generation via the mcore data-parallel coordinator.
- Parameters:
data – BatchedDataDict containing input_ids and input_lengths tensors
greedy – Whether to use greedy decoding instead of sampling
- Returns:
output_ids: input + generated token IDs with proper padding
logprobs: Log probabilities for tokens
generation_lengths: Lengths of each response
unpadded_sequence_lengths: Lengths of each input + generated sequence
- Return type:
BatchedDataDict conforming to GenerationOutputSpec
- async generate_async(
- data: nemo_rl.distributed.batched_data_dict.BatchedDataDict[nemo_rl.models.generation.interfaces.GenerationDatumSpec],
- greedy: bool = False,
Streaming generation: yield
(index, batch)tuples as they complete.- Parameters:
data – BatchedDataDict with input_ids and input_lengths
greedy – Whether to use greedy decoding instead of sampling
- Yields:
Tuple of (original_index, BatchedDataDict conforming to GenerationOutputSpec for the single sequence)
- async _generate_with_persistent_engine(
- prompts: list[list[int]],
- multi_modal_data_list: list[Optional[Any]],
- sampling_params: list[megatron.core.inference.sampling_params.SamplingParams],
Submit requests through the persistent inference client (rank 0 only).
- class nemo_rl.models.generation.megatron.megatron_worker.MegatronGenerationRefitMixin#
Refit collective, weight transfer, and engine suspend/resume around refits.
- _init_generation_refit_state() None#
Reset every refit attribute to its unprepared state.
Declaring these up front keeps
prepare_refit_inforeadiness a value check rather than anhasattrprobe, and makes the full set visible to anyone adding a__getstate__.
- init_collective_mcore_generation(
- ip: str,
- port: int,
- world_size: int,
- rank_offset: int,
- refit_execution_batch_bytes: int | None,
- refit_backend: str,
Initialize the refit collective for non-colocated weight transfer.
- Parameters:
ip – IP address for the process group rendezvous.
port – Port for the process group rendezvous.
world_size – Total world size (train + inference workers).
rank_offset – Offset for this side’s ranks (
train_world_sizefor inference).refit_execution_batch_bytes – Configured native MCore staging limit. None uses NeMo-RL’s dynamic collective-refit default.
refit_backend – Copy-service backend (“gloo”, “nccl”, or “nccl_m2n”; “nvshmem” is currently broken, see the issue below).
- preinit_nvshmem_collective() None#
Initialize NVShmem collectively before any weight transfer.
Must be called on ALL participating ranks (training + inference) simultaneously, outside CUDA graph capture. Lazy initialization during graph recording or replay can corrupt CUDA graph state.
- swap_weights_via_reshard(is_source: bool) bool#
Transfer weights using Megatron’s
swap_model_weightsAPI.- Parameters:
is_source – True for training workers (senders), False for inference workers (receivers).
- Returns:
True on success.
- init_nccl_reshard_comm_groups_generation(
- *,
- pp_ips: list[str],
- pp_ports: list[int],
- pp_size: int,
- train_ranks_per_stage: int,
- sub_world_size: int,
- rank_prefix: Optional[int] = None,
Join every training PP stage’s M-to-N communicator as a gen rank.
- _commit_megatron_bulk_refit_piece(
- piece: nemo_rl.models.generation.megatron.megatron_worker._MegatronBulkRefitPiece,
- tensor: torch.Tensor,
Commit one received HF-local weight to its inference destination.
- _build_destination_hf_to_local_param_map(
- refit_info: dict[str, Any],
- tasks: list[nemo_rl.models.generation.megatron.megatron_worker._MegatronRefitTask],
Map canonical HF FFN shards onto local Megatron destinations.
- _prepare_mxfp8_refit( ) None#
Install persistent MCore MXFP8 destinations before engine initialization.
- _refresh_flashinfer_mxfp8_weights() None#
Refresh derived FlashInfer expert storage after canonical weights change.
- _build_generation_refit_tasks() tuple[list[torch.nn.Module], list[nemo_rl.models.generation.megatron.megatron_worker._MegatronRefitTask]]#
Resolve Bridge import tasks against the persistent inference model.
- _install_generation_refit_plan(
- *,
- model_chunks: list[torch.nn.Module],
- tasks: list[nemo_rl.models.generation.megatron.megatron_worker._MegatronRefitTask],
- state_dict_info: dict[str, Any],
Install the packed-broadcast subset of a Bridge receive plan.
- _prepare_destination_refit_info(
- state_dict_info: dict[str, Any],
Build the local HF-to-Megatron receive plan before the first refit.
- _prepare_destination_nccl_reshard_refit_info(
- refit_info: dict[str, Any],
Prepare Megatron as the destination of NCCL M-to-N reshard refit.
- _destination_nccl_reshard_refit(
- refit_timeout_s: Optional[float] = None,
Receive bulk FFN shards via M-to-N, then import packed misc weights.
- _write_generation_refit_weight(
- task: nemo_rl.models.generation.megatron.megatron_worker._MegatronRefitTask,
- converted_weight: torch.Tensor,
Copy one converted weight into its persistent inference destination.
copy_rather than rebinding: an MXFP8 destination quantizes in place and keeps its storage address, which is what already-captured CUDA graphs point at.- Parameters:
task – The Bridge import task owning the destination tensor.
converted_weight – The assembled weight in the destination’s layout.
- Raises:
ValueError – If the converted weight does not match the destination shape, which means the refit plan and the model disagree.
- _load_generation_refit_batch(
- weights: list[tuple[str, torch.Tensor]],
Import every Bridge task whose HF inputs have now all arrived.
Called once per
packed_broadcast_consumerbatch. Weights arrive in HF order, but a task may fuse several of them (gate/up, stacked experts), so each tensor is buffered until its task’s dependency count reaches zero, then the task is converted and written in task order. Buffered tensors record their producing stream so the conversion can wait on it before reading across streams.- Parameters:
weights –
(hf_name, tensor)pairs unpacked from this batch.
- _update_destination_weights_from_collective(
- refit_timeout_s: Optional[float] = None,
- *,
- refresh_mxfp8: bool = True,
Receive packed HF tensors and import them into the Megatron model.
- _onload_inference_model() None#
Restore the colocated inference weights to GPU before resharding / generation.
- _offload_inference_model() None#
Offload the colocated inference weights to CPU while training runs.
- _reshard_into_inference_model() None#
Reshard current training weights into the colocated inference-layout model.
- suspend_for_refit() None#
Pause+suspend the inference engine before a weight refit.
- resume_after_refit() None#
Resume+unpause the inference engine after a weight refit.