Repository navigation
[OMNIML-6076] [1/3] Describe expert parallelism in the model specs #3134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,10 +15,18 @@ | |
|
|
||
| """Llama4 specs (HF model type ``llama4``).""" | ||
|
|
||
| from ..specs import ModelSpec, MoESpec, register | ||
| from ..specs import EPSpec, ModelSpec, MoESpec, register | ||
|
|
||
| __all__: list[str] = [] | ||
|
|
||
| # transformers ships a base_model_ep_plan for Llama-4, which alone would route it into the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION]
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keeping them public, deliberately. |
||
| # expert-parallel path. | ||
| EP_UNSUPPORTED = ( | ||
| "Llama-4's MoE block routes tokens itself and runs every expert densely, rather than " | ||
| "dispatching its top-k through the experts interface, and its experts are stored transposed, " | ||
| "(num_experts, in, out), which the expert-parallel export cannot write." | ||
| ) | ||
|
|
||
| # Llama4TextExperts is fused: one module holding 3-D gate_up_proj and down_proj | ||
| # parameters, run through torch.bmm. There is no (gate, up) pair left to fuse, and the | ||
| # grouped-export path (get_experts_list) does not apply. The block also carries a | ||
|
|
@@ -27,6 +35,7 @@ | |
| ModelSpec( | ||
| model_type="llama4", | ||
| min_transformers_version="5.5", | ||
| ep_spec=EPSpec(unsupported=EP_UNSUPPORTED), | ||
| moe_spec=MoESpec( | ||
| block_names=("Llama4TextMoe",), | ||
| expert_linear_names=("gate_up_proj", "down_proj"), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """llama4_text specs (HF model type ``llama4_text``).""" | ||
|
|
||
| from . import specs |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Llama-4 text-only specs (HF model type ``llama4_text``). | ||
|
|
||
| The same architecture as ``llama4`` reached through ``Llama4ForCausalLM``, with its own | ||
| ``base_model_ep_plan`` on the root config, so it is refused expert parallelism the same way. | ||
|
|
||
| Only that refusal is registered under this type, deliberately: no MoE or export section, so its | ||
| MoE and export lookups find none, as they did before this type had a spec. Giving it ``llama4``'s | ||
| MoE section would change how text-only Llama-4 checkpoints match MoE blocks in quantization and | ||
| export, which belongs with tests of those paths, not with its expert-parallel refusal. | ||
| """ | ||
|
|
||
| from ..llama4.specs import EP_UNSUPPORTED | ||
| from ..specs import EPSpec, ModelSpec, register | ||
|
|
||
| __all__: list[str] = [] | ||
|
|
||
| register( | ||
| ModelSpec( | ||
| model_type="llama4_text", | ||
| min_transformers_version="5.5", | ||
| ep_spec=EPSpec(unsupported=EP_UNSUPPORTED), | ||
|
Comment on lines
+33
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] This registration diverges from the repo's own precedent for exactly this situation, and leaves the registry asserting something false about the architecture.
# gemma4_text/specs.py
"""... The MoE block lives in the text model either way, so the layout is imported from
``gemma4`` rather than restated -- the two must not drift apart."""
moe_spec=_GEMMA4_MOE_SPEC,Here Why it matters: nothing breaks today (I traced Suggested fix: either hoist # llama4/specs.py
_LLAMA4_MOE_SPEC = MoESpec(
block_names=("Llama4TextMoe",),
expert_linear_names=("gate_up_proj", "down_proj"),
fused_expert_names=True,
)
# llama4_text/specs.py
from ..llama4.specs import _LLAMA4_MOE_SPEC, _EP_UNSUPPORTED
...
moe_spec=_LLAMA4_MOE_SPEC,
ep_spec=EPSpec(unsupported=_EP_UNSUPPORTED),— or, if the omission is deliberate, state it in the module docstring the way
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deliberate. Giving it
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docstring note is in 3b43cc6. It says the type registers only the expert-parallel refusal, so its MoE and export lookups find none as before, and that giving it |
||
| ) | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """minimax_m3_vl specs (HF model type ``minimax_m3_vl``).""" | ||
|
|
||
| from . import specs |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """MiniMax-M3 specs (HF model type ``minimax_m3_vl``). | ||
|
|
||
| transformers ships everything M3 needs to run expert-parallel: its MoE block calls the experts with | ||
| the router's top-k, its experts dispatch through the experts interface, and its text config carries a | ||
| ``base_model_ep_plan``. The generic all-to-all transport takes over unchanged. | ||
| """ | ||
|
|
||
| from ..specs import EPSpec, ModelSpec, register | ||
|
|
||
| __all__: list[str] = [] | ||
|
|
||
| register( | ||
| ModelSpec( | ||
| model_type="minimax_m3_vl", | ||
| min_transformers_version="5.13", | ||
| ep_spec=EPSpec(requires_transformers="5.13"), | ||
| ) | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
|
|
||
| """NemotronH-Omni specs (HF model type ``nemotron_h_omni``).""" | ||
|
|
||
| from . import specs |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
|
|
||
| """NemotronH-Omni specs (HF model type ``nemotron_h_omni``). | ||
|
|
||
| The Omni VLM's language sub-model is a native NemotronH, so its MoE facts are NemotronH's. | ||
| What differs is where the expert-parallel plan has to be attached: on the nested language-model | ||
| config, not the VLM root. transformers aggregates each sub-model's plan up to the root WITH its | ||
| module prefix, so a plan there surfaces as ``language_model.<base>.layers.*`` and matches the real | ||
| parameter paths -- while a plan on the top config reaches no expert at all. | ||
|
|
||
| Only that plan is registered under the root type, so lookups of the MoE and export sections by | ||
| ``nemotron_h_omni`` find neither. No export depends on them: on transformers 5 the language | ||
| model's experts are one fused container, which the export writes through its own handler, and | ||
| every step those lookups gate leaves a fused container as it is. | ||
| """ | ||
|
|
||
| from ..nemotron_h.specs import BASE_MODEL_EP_PLAN | ||
| from ..specs import EPSpec, ModelSpec, register | ||
|
|
||
| __all__: list[str] = [] | ||
|
|
||
| register( | ||
| ModelSpec( | ||
| model_type="nemotron_h_omni", | ||
| # transformers ships the Omni VLM itself from 5.18. The checkpoint's own code | ||
| # (``trust_remote_code=True``) names the language-model config ``llm_config``, and | ||
| # transformers' port ``text_config``: the plan goes on whichever the config has, tried in | ||
| # the order the load reads them. | ||
| min_transformers_version="5.18", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] Nothing enforces the field at runtime today, so there is no bug. But the deferred follow-up named in the PR description — extending Relatedly:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment above The plan applies to either spelling. |
||
| ep_spec=EPSpec( | ||
| # Its own copy: the registry is process-wide, and a spec holding NemotronH's dict would | ||
| # carry any change to one plan into the other. | ||
| base_model_ep_plan=dict(BASE_MODEL_EP_PLAN), | ||
| plan_config_attr=("text_config", "llm_config"), | ||
| ), | ||
| ) | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[SUGGESTION] The comment pairs two claims that are in tension and leaves the resolution unstated: "from 5.13 the config's own plan wins and this one goes unused", and (two sentences later) "adding a gate entry would mask them". Stock transformers' EP plans for the DeepSeek family do style the router (
ep_router/megamoe_router, whoseRouterParallel._prepare_output_fnremaps to local ids and masks non-local — see theTorchA2ARouteroverride inmodelopt/torch/utils/moe.py). So on 5.13+, where the config's own plan is the one that applies, deepseek_v3 gets exactly the gate styling this spec deliberately omits, and the a2a dispatch's precondition ("the router must emit GLOBAL ids unmasked") is the load's problem rather than the spec's.No change needed to the data — but a reader who takes "goes unused" at face value will conclude the masking hazard cannot arise for deepseek_v3 on recent transformers, which is the opposite of the truth. Worth one clause saying where that is handled (the load rewriting router/expert styles to
torch_a2a_*), or dropping "goes unused" in favour of "stock's plan applies instead, and the load re-styles its router entry".There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2748, next in the series, rewrites this comment when it moves the plan into
BASE_MODEL_EP_PLANfor the Kimi adapters. Its text already says what you ask: "From 5.13 its own plan wins (an existing plan always does, see apply_distributed_support): the same experts, plus an ep_router entry for the gate, which the load swaps for torch_a2a_router (global ids, unmasked)."The load does that swap in
load_and_prepare_ep("ep_router": "torch_a2a_router"). Rewording the comment here as well would only conflict with that rewrite, so this text stays as is.