nemo_automodel.components.models.qwen3_5_moe.model

View as Markdown

Qwen3.5-MoE (VL) NeMo Automodel support.

Module Contents

Classes

NameDescription
Fp32SafeQwen3_5MoeTextRotaryEmbeddingEnsure inv_freq stays in float32 across .to(dtype) calls.
Fp32SafeQwen3_5MoeVisionRotaryEmbeddingEnsure the vision rotary inv_freq buffer remains float32.
Qwen3_5MoeBlockBlock that uses the Qwen3.5-MoE native GatedDeltaNet (separate in_proj_qkv,
Qwen3_5MoeCausalLMOutputWithPastQwen3.5-MoE output extended with MTP auxiliary hidden states.
Qwen3_5MoeForCausalLMText-only Qwen3.5-MoE causal language model.
Qwen3_5MoeForConditionalGenerationQwen3.5-MoE VL conditional generation model using NeMo backend components.
Qwen3_5MoeMTPSublayerOne full-attention Qwen3.5-MoE MTP sublayer.
Qwen3_5MoeModelThin wrapper that exposes language_model internals as properties
Qwen3_5MoeTextModelBackendQwen3.5-MoE text decoder rebuilt on top of the Qwen3-Next Block.
_Qwen3_5MoeAttentionQwen3.5-MoE full attention with packed block-diagonal CP dispatch.

Functions

NameDescription
_default_init_device-
_freqs_cis_from_rotary-
_make_missing-
_make_mtp_block_config-
_qwen3_5_moe_backendReturn a Qwen3.5-MoE backend with TE fused RoPE disabled.
_resolve_mtp_num_layers-
_rolled_embed_inputs-
_split_qwen3_5_moe_position_ids-
build_mtp_config_from_hfBuild Qwen3.5-MoE MTP runtime config from HF-style config fields.
build_qwen3_5_moe_mtpConstruct Qwen3.5-MoE MTP blocks.

Data

ModelClass

_QWEN3_5_MOE_HF_AVAILABLE

API

class nemo_automodel.components.models.qwen3_5_moe.model.Fp32SafeQwen3_5MoeTextRotaryEmbedding()

Bases: Qwen3_5MoeTextRotaryEmbedding

Ensure inv_freq stays in float32 across .to(dtype) calls.

nemo_automodel.components.models.qwen3_5_moe.model.Fp32SafeQwen3_5MoeTextRotaryEmbedding._apply(
fn: typing.Any,
recurse: bool = True
)
class nemo_automodel.components.models.qwen3_5_moe.model.Fp32SafeQwen3_5MoeVisionRotaryEmbedding()

Bases: Qwen3_5MoeVisionRotaryEmbedding

Ensure the vision rotary inv_freq buffer remains float32.

nemo_automodel.components.models.qwen3_5_moe.model.Fp32SafeQwen3_5MoeVisionRotaryEmbedding._apply(
fn: typing.Any,
recurse: bool = True
)
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeBlock(
layer_idx,
config,
moe_config,
backend
)

Bases: Block

Block that uses the Qwen3.5-MoE native GatedDeltaNet (separate in_proj_qkv, in_proj_z, in_proj_b, in_proj_a)

linear_attn
= CPAwareGatedDeltaNet(config, layer_idx)
self_attn
= _Qwen3_5MoeAttention(config, layer_idx, backend)
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeBlock.forward(
x: torch.Tensor,
freqs_cis: torch.Tensor,
attention_mask: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
position_ids: torch.Tensor | None = None,
attn_kwargs: typing.Any = {}
) -> torch.Tensor

Mirror :meth:Block.forward but thread NEAT-packing kwargs into CPAwareGatedDeltaNet.

The parent Block.forward calls linear_attn with only hidden_states and attention_mask; for packed sequences the gated_delta_rule kernel additionally needs cu_seqlens / indices to reset state at document boundaries (issue #2131). Derived once per forward from the indexed attention mask.

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeBlock.init_weights(
buffer_device: torch.device
)
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeCausalLMOutputWithPast(
mtp_per_depth_h: list[torch.Tensor] | None = None,
mtp_loss_scaling_factor: float | None = None
)
Dataclass

Bases: CausalLMOutputWithPast

Qwen3.5-MoE output extended with MTP auxiliary hidden states.

mtp_loss_scaling_factor
float | None = None
mtp_per_depth_h
list[Tensor] | None = None
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig | None = None,
backend: nemo_automodel.components.models.common.BackendConfig | None = None,
mtp_loss_scaling_factor: float = 0.1,
num_nextn_predict_layers: int | None = None,
kwargs: typing.Any = {}
)

Bases: HFCheckpointingMixin, Module, MoEFSDPSyncMixin

Text-only Qwen3.5-MoE causal language model.

_pp_keep_self_forward
bool = True
backend
= _qwen3_5_moe_backend(backend)
lm_head
model
moe_config
= self.model.moe_config
mtp
mtp_config
pad_token_id
state_dict_adapter
tie_word_embeddings_support
TieSupport = TieSupport.UNTIED_ONLY
vocab_size
= config.vocab_size
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.forward(
input_ids: torch.Tensor | None = None,
attention_mask: torch.Tensor | None = None,
position_ids: torch.LongTensor | None = None,
past_key_values: typing.Any | None = None,
inputs_embeds: torch.FloatTensor | None = None,
labels: torch.LongTensor | None = None,
use_cache: bool | None = None,
logits_to_keep: int | torch.Tensor = 0,
output_hidden_states: bool | None = None,
cache_position: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
kwargs: typing.Any = {}
) -> nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeCausalLMOutputWithPast

Run the text-only causal LM forward pass.

Parameters:

input_ids
torch.Tensor | NoneDefaults to None

Token ids of shape [batch, sequence]. On a non-first pipeline stage where embed_tokens is absent, this argument instead carries hidden states of shape [batch, sequence, hidden] and is routed as inputs_embeds.

attention_mask
torch.Tensor | NoneDefaults to None

Optional mask of shape [batch, sequence] or [batch, 1, sequence, sequence].

position_ids
torch.LongTensor | NoneDefaults to None

Optional M-RoPE positions of shape [axes, batch, sequence] or [batch, sequence].

past_key_values
Any | NoneDefaults to None

Optional KV-cache state; caching is not supported by this backend and a non-None value raises.

inputs_embeds
torch.FloatTensor | NoneDefaults to None

Optional hidden inputs of shape [batch, sequence, hidden].

labels
torch.LongTensor | NoneDefaults to None

Optional labels of shape [batch, sequence]. Accepted for Hugging Face compatibility; loss is computed outside this model.

use_cache
bool | NoneDefaults to None

Whether to use a KV cache; True is unsupported.

logits_to_keep
int | torch.TensorDefaults to 0

0 to project every position, a positive integer to keep the last positions, or indices of shape [kept_sequence].

output_hidden_states
bool | NoneDefaults to None

Whether to include final decoder states in the output for the fused loss path.

cache_position
torch.Tensor | NoneDefaults to None

Optional token positions of shape [sequence].

padding_mask
torch.Tensor | NoneDefaults to None

Optional padding mask of shape [batch, sequence] where True marks padding.

**kwargs
AnyDefaults to {}

Additional attention and packed-sequence metadata forwarded to the decoder and optional MTP layers.

Returns: Qwen3_5MoeCausalLMOutputWithPast

A causal-LM output whose logits have shape

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.from_config(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig | None = None,
backend: nemo_automodel.components.models.common.BackendConfig | None = None,
kwargs: typing.Any = {}
)
classmethod
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.from_pretrained(
pretrained_model_name_or_path: str,
model_args: typing.Any = (),
kwargs: typing.Any = {}
)
classmethod
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.get_input_embeddings() -> torch.nn.Module
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.get_output_embeddings() -> torch.nn.Module
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.initialize_weights(
buffer_device: torch.device | None = None,
dtype: torch.dtype = torch.bfloat16
) -> None
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.set_input_embeddings(
value: torch.nn.Module
) -> None
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForCausalLM.set_output_embeddings(
new_embeddings: torch.nn.Module
) -> None
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig | None = None,
backend: nemo_automodel.components.models.common.BackendConfig | None = None,
mtp_loss_scaling_factor: float = 0.1,
num_nextn_predict_layers: int | None = None,
kwargs = {}
)

Bases: HFCheckpointingMixin, HFQwen3_5MoeForConditionalGeneration, MoEFSDPSyncMixin

Qwen3.5-MoE VL conditional generation model using NeMo backend components.

_keep_in_fp32_modules_strict
= ['_fp32_params']
_pp_keep_self_forward
bool = True
lm_head
mtp
mtp_config
pad_token_id
= pad_token_id if pad_token_id is not None else -1
state_dict_adapter
tie_word_embeddings_support
TieSupport = TieSupport.UNTIED_ONLY
vocab_size
= text_config.vocab_size
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration._embed_and_splice_for_cp(
input_ids: torch.Tensor,
pixel_values: torch.Tensor | None,
pixel_values_videos: torch.Tensor | None,
image_grid_thw: torch.Tensor | None,
video_grid_thw: torch.Tensor | None
) -> torch.Tensor

Embed token ids and splice image/video features into the embeddings.

The VLM->LM multimodal scatter runs on the full (unsharded) sequence inside the forward before the CP sequence shard, identical to the pre-CP-refactor pre-embed.

Parameters:

input_ids
torch.Tensor

Token ids [batch, sequence] (full, unsharded).

pixel_values
torch.Tensor | None

Optional packed image patches for HF vision encoding.

pixel_values_videos
torch.Tensor | None

Optional packed video patches.

image_grid_thw
torch.Tensor | None

Per-image [num_images, 3] T/H/W grid.

video_grid_thw
torch.Tensor | None

Per-video [num_videos, 3] T/H/W grid.

Returns: torch.Tensor

inputs_embeds of shape [batch, sequence, hidden] with image /

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration._encode_vision_for_cp(
pixel_values: torch.Tensor,
grid_thw: torch.Tensor,
is_video: bool
) -> torch.Tensor

Encode one modality into flat, entry-ordered visual tokens under CP.

Parameters:

pixel_values
torch.Tensor

Patch rows of shape [total_patch_rows, patch_dim] for all image or video entries, frame-contiguous in entry order.

grid_thw
torch.Tensor

Per-entry temporal/height/width grids of shape [num_entries, 3].

is_video
bool

Whether the replicated fallback uses the video feature helper instead of the image feature helper.

Returns: torch.Tensor

Flat merged-token embeddings of shape [visual_tokens, hidden]

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.forward(
input_ids: torch.Tensor | None = None,
position_ids: torch.Tensor | None = None,
attention_mask: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
inputs_embeds: torch.Tensor | None = None,
cache_position: torch.Tensor | None = None,
logits_to_keep: typing.Union[int, torch.Tensor] = 0,
output_hidden_states: typing.Optional[bool] = None,
kwargs: typing.Any = {}
)

Run Qwen3.5-MoE VLM generation with model-owned CP embedding.

Parameters:

input_ids
torch.Tensor | NoneDefaults to None

Token ids of shape [batch, sequence]. Under CP this remains full-length until multimodal features are spliced.

position_ids
torch.Tensor | NoneDefaults to None

Optional mRoPE positions of shape [axes, batch, sequence]; under CP, sequence is local.

attention_mask
torch.Tensor | NoneDefaults to None

Optional mask of shape [batch, sequence] or [batch, 1, sequence, sequence].

padding_mask
torch.Tensor | NoneDefaults to None

Optional local padding mask of shape [batch, sequence] where True marks padding.

inputs_embeds
torch.Tensor | NoneDefaults to None

Optional embeddings of shape [batch, sequence, hidden].

cache_position
torch.Tensor | NoneDefaults to None

Optional token positions of shape [sequence].

logits_to_keep
Union[int, torch.Tensor]Defaults to 0

Number of trailing logits to retain, or indices of shape [kept_sequence].

output_hidden_states
Optional[bool]Defaults to None

Whether to expose final decoder states for the fused loss path.

**kwargs
AnyDefaults to {}

Model inputs including image/video patch rows of shape [total_patch_rows, patch_dim], their grids of shape [num_entries, 3], and optional packed document ids of shape [batch, sequence].

Returns:

A causal-LM output whose logits have shape

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.from_config(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig | None = None,
backend: nemo_automodel.components.models.common.BackendConfig | None = None,
kwargs = {}
)
classmethod
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.from_pretrained(
pretrained_model_name_or_path: str,
model_args = (),
kwargs = {}
)
classmethod
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.get_pipeline_kwargs_chunk_dims(
kwargs: dict[str, typing.Any]
) -> dict[str, int]

Return model-owned PP microbatch split dims for keyword inputs.

Qwen3.5-MoE mRoPE position ids can arrive as [T/H/W, batch, seq] or [text/T/H/W, batch, seq]. The PP schedule must split that tensor on the batch axis, while all standard batch-major kwargs keep the framework default.

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.get_pipeline_stage_metas(
is_first: bool,
microbatch_size: int,
seq_len: int,
dtype: torch.dtype
) -> tuple[tuple[torch.Tensor, ...], tuple[torch.Tensor, ...]]

Per-stage input/output meta tensors for the PP schedule’s shape inference.

Matches the framework default except that under context parallelism the first stage embeds the full sequence and shards it in forward, so every stage output and later-stage input carries the LOCAL (padded-to-2*cp then //cp) sequence length while the first-stage input stays full-length. At cp_size == 1 this reduces to the default symmetric shapes.

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.initialize_weights(
buffer_device: torch.device | None = None,
dtype: torch.dtype = torch.bfloat16
) -> None
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeForConditionalGeneration.prepare_model_inputs_for_cp(
batch: dict[str, typing.Any],
num_chunks: int = 1
) -> dict[str, typing.Any]

Return a sharder-only CP backend plus the full-sequence mRoPE positions.

Embedding and the VLM->LM multimodal scatter now run inside forward per microbatch (see :meth:_embed_and_splice_for_cp), so this hook only computes the mRoPE position_ids on the full (unsharded) sequence via get_rope_index and returns them with a :class:ContextParallelSharder. Packed SDPA batches select contiguous block-diagonal CP; ordinary batches retain the round-robin sharder. input_ids and media stay in the batch for the forward, while mm_token_type_ids is consumed here (only get_rope_index needs it).

Parameters:

batch
dict[str, Any]

The full-sequence batch. Tensor fields consumed here are input_ids of shape [batch, sequence], optional attention_mask of shape [batch, sequence] or [batch, 1, sequence, sequence], optional position_ids of shape [axes, batch, sequence], and image/video grids of shape [num_entries, 2 or 3].

num_chunks
intDefaults to 1

Accepted for hook-signature parity; unused.

Returns: dict[str, Any]

A mapping containing the selected cp_sharder, full-sequence

class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeMTPSublayer(
layer_idx: int,
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig,
backend: nemo_automodel.components.models.common.BackendConfig,
has_fusion: bool = False,
has_final_norm: bool = False,
dtype: torch.dtype = torch.bfloat16
)

Bases: Qwen3_5MoeBlock

One full-attention Qwen3.5-MoE MTP sublayer.

eh_proj
enorm
final_layernorm
hnorm
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeMTPSublayer.forward(
hidden_states: torch.Tensor,
embed_input: torch.Tensor | None = None,
rotary_emb: torch.nn.Module,
position_ids: torch.Tensor,
attention_mask: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
attn_kwargs: typing.Any = {}
) -> torch.Tensor
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeMTPSublayer.init_weights(
buffer_device: torch.device
) -> None
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeModel()

Bases: HFQwen3_5MoeModel

Thin wrapper that exposes language_model internals as properties expected by the NeMo training loop (e.g. model.layers).

nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeModel.forward(
input_ids = None,
attention_mask = None,
position_ids = None,
past_key_values = None,
inputs_embeds = None,
pixel_values = None,
pixel_values_videos = None,
image_grid_thw = None,
video_grid_thw = None,
cache_position = None,
kwargs = {}
)
class nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeTextModelBackend(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
backend: nemo_automodel.components.models.common.BackendConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig | None = None,
moe_overrides: dict | None = None
)

Bases: Module

Qwen3.5-MoE text decoder rebuilt on top of the Qwen3-Next Block.

embed_tokens
layers
moe_config
= moe_config or MoEConfig(**moe_defaults)
norm
padding_idx
= getattr(config, 'pad_token_id', None)
rotary_emb
vocab_size
= config.vocab_size
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeTextModelBackend.forward(
input_ids: torch.Tensor | None = None,
inputs_embeds: torch.Tensor | None = None,
attention_mask: torch.Tensor | None = None,
position_ids: torch.Tensor | None = None,
cache_position: torch.Tensor | None = None,
padding_mask: torch.Tensor | None = None,
past_key_values: typing.Any | None = None,
use_cache: bool | None = None,
attn_kwargs: typing.Any = {}
) -> transformers.models.qwen3_5_moe.modeling_qwen3_5_moe.Qwen3_5MoeModelOutputWithPast
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeTextModelBackend.get_input_embeddings() -> torch.nn.Module
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeTextModelBackend.init_weights(
buffer_device: torch.device | None = None
) -> None
nemo_automodel.components.models.qwen3_5_moe.model.Qwen3_5MoeTextModelBackend.set_input_embeddings(
value: torch.nn.Module
) -> None
class nemo_automodel.components.models.qwen3_5_moe.model._Qwen3_5MoeAttention(
args: typing.Any = (),
kwargs: typing.Any = {}
)

Bases: Qwen3NextAttention

Qwen3.5-MoE full attention with packed block-diagonal CP dispatch.

_base_attn_func
= self.attn_func
attn_func
= self._dispatch_attention
nemo_automodel.components.models.qwen3_5_moe.model._Qwen3_5MoeAttention._dispatch_attention(
query: torch.Tensor,
key: torch.Tensor,
value: torch.Tensor,
attn_kwargs: typing.Any = {}
) -> torch.Tensor

Route preprocessed QKV through packed CP or the configured backend.

Parameters:

query
torch.Tensor

Query states of shape [batch, heads, local_sequence, head_dim].

key
torch.Tensor

Key states of shape [batch, kv_heads, local_sequence, head_dim].

value
torch.Tensor

Value states with the same layout as key.

**attn_kwargs
AnyDefaults to {}

Keyword arguments produced by the parent attention’s backend preprocessing.

Returns: torch.Tensor

Attention output of shape

nemo_automodel.components.models.qwen3_5_moe.model._default_init_device() -> torch.device
nemo_automodel.components.models.qwen3_5_moe.model._freqs_cis_from_rotary(
rotary_emb: torch.nn.Module,
hidden_states: torch.Tensor,
position_ids: torch.Tensor
) -> torch.Tensor
nemo_automodel.components.models.qwen3_5_moe.model._make_missing(
name: str
)
nemo_automodel.components.models.qwen3_5_moe.model._make_mtp_block_config(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
layer_idx: int
) -> transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig
nemo_automodel.components.models.qwen3_5_moe.model._qwen3_5_moe_backend(
backend: nemo_automodel.components.models.common.BackendConfig | None = None
) -> nemo_automodel.components.models.common.BackendConfig

Return a Qwen3.5-MoE backend with TE fused RoPE disabled.

The Qwen3.5 full-attention blocks reuse Qwen3-Next attention, and VLM/packed execution can present THD-shaped q/k tensors. TE fused RoPE expects 4D inputs in this path, so use non-fused RoPE while preserving the rest of the backend.

nemo_automodel.components.models.qwen3_5_moe.model._resolve_mtp_num_layers(
config: typing.Any,
override: int | None = None
) -> int
nemo_automodel.components.models.qwen3_5_moe.model._rolled_embed_inputs(
inputs_embeds: torch.Tensor,
num_depths: int
) -> tuple[torch.Tensor, ...]
nemo_automodel.components.models.qwen3_5_moe.model._split_qwen3_5_moe_position_ids(
position_ids: torch.Tensor | None,
batch_size: int,
seq_len: int,
device: torch.device,
cache_position: torch.Tensor | None = None
) -> torch.Tensor
nemo_automodel.components.models.qwen3_5_moe.model.build_mtp_config_from_hf(
config: typing.Any,
loss_scaling_factor: float = 0.1,
num_nextn_predict_layers: int | None = None
) -> nemo_automodel.components.models.common.mtp.MTPConfig

Build Qwen3.5-MoE MTP runtime config from HF-style config fields.

nemo_automodel.components.models.qwen3_5_moe.model.build_qwen3_5_moe_mtp(
config: transformers.models.qwen3_5_moe.configuration_qwen3_5_moe.Qwen3_5MoeTextConfig,
mtp_config: nemo_automodel.components.models.common.mtp.MTPConfig,
backend: nemo_automodel.components.models.common.BackendConfig,
moe_config: nemo_automodel.components.moe.layers.MoEConfig,
dtype: torch.dtype
) -> nemo_automodel.components.models.common.mtp.MTPModule

Construct Qwen3.5-MoE MTP blocks.

nemo_automodel.components.models.qwen3_5_moe.model.ModelClass = Qwen3_5MoeForConditionalGeneration
nemo_automodel.components.models.qwen3_5_moe.model._QWEN3_5_MOE_HF_AVAILABLE = True