> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/automodel/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/automodel/_mcp/server.

# nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter

State-dict adapter for Qwen3.5-MoE.

HF Qwen3.5-MoE stores expert weights as **aggregated 3-D tensors**:

model.language\_model.layers.\{L}.mlp.experts.gate\_up\_proj   # \[n\_experts, 2\*moe\_inter, hidden]
model.language\_model.layers.\{L}.mlp.experts.down\_proj      # \[n\_experts, hidden, moe\_inter]

NeMo uses a different naming convention **and transposed layout** (x @ weight):

model.language\_model.layers.\{L}.mlp.experts.gate\_and\_up\_projs  # \[n\_experts, hidden, 2\*moe\_inter]
model.language\_model.layers.\{L}.mlp.experts.down\_projs         # \[n\_experts, moe\_inter, hidden]

Both expert tensors require `.transpose(1, 2)` when converting between formats.

Additionally, the shared expert uses singular in HF and plural in NeMo:

HF:   .mlp.shared\_expert.\{gate,up,down}\_proj.weight
NeMo: .mlp.shared\_experts.\{gate,up,down}\_proj.weight

All other keys (attention, linear\_attn/GatedDeltaNet, norms, embeddings, vision
encoder) pass through unchanged. The HF VLM checkpoint stores the language
model head as `model.lm_head` while Automodel registers it on the outer model
as `lm_head`.

## Module Contents

### Classes

| Name                                                                                                                        | Description                                                             |
| --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [`Qwen3_5MoeStateDictAdapter`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-Qwen3_5MoeStateDictAdapter) | Converts between HF Qwen3.5-MoE checkpoints and the NeMo native format. |

### Functions

| Name                                                                                                                            | Description                                                                       |
| ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| [`_block_scale_placeholder`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_block_scale_placeholder)         | Create a regular 128x128 block-scale load target for a 2-D weight.                |
| [`_dequantize_block_fp8`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_dequantize_block_fp8)               | Dequantize one local 2-D 128x128 block-scaled FP8 expert weight.                  |
| [`_filter_excluded`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_filter_excluded)                         | Remove exported HF entries matched by `exclude_key_regex`.                        |
| [`_get_local_safetensors_keys`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_get_local_safetensors_keys)   | Read key metadata from a local HF safetensors checkpoint without loading tensors. |
| [`_infer_base_expert_hf_layout`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_infer_base_expert_hf_layout) | Infer the decoder expert layout from checkpoint key names.                        |
| [`_infer_mtp_expert_hf_layout`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_infer_mtp_expert_hf_layout)   | Infer the MTP expert layout from checkpoint key names.                            |
| [`_route_fp32_params`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_route_fp32_params)                     | Route bare GDN fp32 params into the holder used by the native module.             |
| [`_slice_ep_shard_dim1`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_slice_ep_shard_dim1)                 | Slice dim 1 of a local expert tensor for the `ep_shard` mesh dimension.           |
| [`_strip_fp32_params`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_strip_fp32_params)                     | Strip the fp32 holder segment from GDN state-dict keys.                           |

### Data

[`_BASE_GROUPED_EXPERT_KEY`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_BASE_GROUPED_EXPERT_KEY)

[`_BASE_SPLIT_FP8_EXPERT_KEY`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_BASE_SPLIT_FP8_EXPERT_KEY)

[`_BASE_SPLIT_FP8_EXPERT_PARAM`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_BASE_SPLIT_FP8_EXPERT_PARAM)

[`_FP8_BLOCK_SIZE`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_FP8_BLOCK_SIZE)

[`_MTP_GROUPED_EXPERT_KEY`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_MTP_GROUPED_EXPERT_KEY)

[`_MTP_SPLIT_EXPERT_KEY`](#nemo_automodel-components-models-qwen3_5_moe-state_dict_adapter-_MTP_SPLIT_EXPERT_KEY)

### API

```python
class nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter(
    config: typing.Any,
    moe_config: nemo_automodel.components.moe.layers.MoEConfig,
    backend: nemo_automodel.components.models.common.BackendConfig,
    dtype: torch.dtype = torch.float32,
    pretrained_model_name_or_path: str | None = None,
    mtp_expert_hf_layout: str | None = None,
    text_only: bool = False
)
```

**Bases:** [StateDictAdapter](/nemo-automodel/nemo_automodel/components/checkpoint/state_dict_adapter#nemo_automodel-components-checkpoint-state_dict_adapter-StateDictAdapter)

Converts between HF Qwen3.5-MoE checkpoints and the NeMo native format.

HF Qwen3.5-MoE stores expert weights as **aggregated 3-D tensors**:

model.language\_model.layers.\{L}.mlp.experts.gate\_up\_proj   # \[n\_experts, 2\*moe\_inter, hidden]
model.language\_model.layers.\{L}.mlp.experts.down\_proj      # \[n\_experts, hidden, moe\_inter]

NeMo uses a different naming convention **and transposed layout** (x @ weight):

model.language\_model.layers.\{L}.mlp.experts.gate\_and\_up\_projs  # \[n\_experts, hidden, 2\*moe\_inter]
model.language\_model.layers.\{L}.mlp.experts.down\_projs         # \[n\_experts, moe\_inter, hidden]

Both expert tensors require `.transpose(1, 2)` when converting between formats.

Additionally, the shared expert uses singular in HF and plural in NeMo:

HF:   .mlp.shared\_expert.\{gate,up,down}\_proj.weight
NeMo: .mlp.shared\_experts.\{gate,up,down}\_proj.weight

**`_expert_hf_layout`** `str | None = None`

---

**`_inferred_mtp_expert_hf_layout`** `str | None = None`

---

**`hf_to_internal_map`** `= {'.mlp.shared_expert.': '.mlp.shared_experts.'}`

---

**`internal_to_hf_map`**

---

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter._apply_key_mapping(
    state_dict: dict[str, typing.Any],
    mapping: dict[str, str]
) -> dict[str, typing.Any]
```

Apply key substring mappings to state dict keys.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter._get_expert_hf_layout(
    checkpoint_keys: typing.Iterable[str] | None = None
) -> str
```

Resolve and remember whether decoder experts use grouped BF16 or split block-FP8 HF keys.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter._get_mtp_expert_hf_layout(
    checkpoint_keys: typing.Iterable[str] | None = None
) -> str
```

Resolve and remember whether MTP experts use split or grouped HF keys.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter.convert_single_tensor_to_hf(
    fqn: str,
    tensor: typing.Any,
    kwargs = {}
) -> list[tuple[str, typing.Any]]
```

Rename a single native key to HF format and transpose expert tensors.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter.forced_hf_dtype_mapping(
    state_dict: dict[str, typing.Any]
) -> dict[str, str]
```

Return HF export dtype overrides for intrinsically-fp32 GDN tensors.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter.from_hf(
    hf_state_dict: dict[str, typing.Any],
    device_mesh: typing.Optional[torch.distributed.device_mesh.DeviceMesh] = None,
    kwargs = {}
) -> dict[str, typing.Any]
```

Rename HF keys to native keys and transpose expert tensors.

DTensors (DCP path): rename + transpose; split MTP experts are locally
reassembled without applying EP-shard slicing again.
Plain tensors (init path): slice to local EP shard, transpose, create DTensor.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter.Qwen3_5MoeStateDictAdapter.to_hf(
    state_dict: dict[str, typing.Any],
    exclude_key_regex: str | None = None,
    quantization: bool = False,
    kwargs = {}
) -> dict[str, typing.Any]
```

Rename native keys to HF keys and transpose expert tensors.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._block_scale_placeholder(
    weight: typing.Any
) -> torch.Tensor
```

Create a regular 128x128 block-scale load target for a 2-D weight.

**Parameters:**

**`weight`** `Any`

FP8 weight Tensor or DTensor of shape \[out, in].

---

**Returns:** `torch.Tensor`

Tensor of shape \[ceil(out / 128), ceil(in / 128)] with one scale for each 128x128 block.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._dequantize_block_fp8(
    weight: typing.Any,
    scale_inv: typing.Any,
    dtype: torch.dtype
) -> torch.Tensor
```

Dequantize one local 2-D 128x128 block-scaled FP8 expert weight.

**Parameters:**

**`weight`** `Any`

FP8 weight Tensor or DTensor of shape \[out, in].

---

**`scale_inv`** `Any`

Block-scale Tensor or DTensor of shape \[ceil(out / 128), ceil(in / 128)], with one scale for
each 128x128 block.

---

**`dtype`** `torch.dtype`

Output dtype.

---

**Returns:** `torch.Tensor`

Dequantized Tensor of shape \[out, in] in `dtype`.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._filter_excluded(
    result: list[tuple[str, typing.Any]],
    exclude_key_regex: str | None
) -> list[tuple[str, typing.Any]]
```

Remove exported HF entries matched by `exclude_key_regex`.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._get_local_safetensors_keys(
    model_path: str | None
) -> set[str]
```

Read key metadata from a local HF safetensors checkpoint without loading tensors.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._infer_base_expert_hf_layout(
    checkpoint_keys: typing.Iterable[str]
) -> str | None
```

Infer the decoder expert layout from checkpoint key names.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._infer_mtp_expert_hf_layout(
    checkpoint_keys: typing.Iterable[str]
) -> str | None
```

Infer the MTP expert layout from checkpoint key names.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._route_fp32_params(
    key: str
) -> str
```

Route bare GDN fp32 params into the holder used by the native module.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._slice_ep_shard_dim1(
    local_tensor: torch.Tensor,
    ep_shard_rank: int,
    ep_shard_size: int,
    tensor_name: str
) -> torch.Tensor
```

Slice dim 1 of a local expert tensor for the `ep_shard` mesh dimension.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._strip_fp32_params(
    key: str
) -> str
```

Strip the fp32 holder segment from GDN state-dict keys.

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._BASE_GROUPED_EXPERT_KEY = re.compile('(?:model\\.)?(?:language_model\\.)?layers\\.\\d+\\.mlp\\.experts\\.(...
```

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._BASE_SPLIT_FP8_EXPERT_KEY = re.compile('(?:model\\.)?(?:language_model\\.)?layers\\.\\d+\\.mlp\\.experts\\.\...
```

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._BASE_SPLIT_FP8_EXPERT_PARAM = re.compile('(?:model\\.)?(?:language_model\\.)?layers\\.(\\d+)\\.mlp\\.experts\\...
```

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._FP8_BLOCK_SIZE = 128
```

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._MTP_GROUPED_EXPERT_KEY = re.compile('mtp\\.layers\\.\\d+\\.mlp\\.experts\\.(?:gate_up_proj|down_proj)')
```

```python
nemo_automodel.components.models.qwen3_5_moe.state_dict_adapter._MTP_SPLIT_EXPERT_KEY = re.compile('mtp\\.layers\\.\\d+\\.mlp\\.experts\\.\\d+\\.(?:gate_proj|up_proj|do...
```