Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions tensorrt_llm/_torch/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,30 @@ def resolve_moe_backend(moe_backend: str,
quant_config: Optional[QuantConfig] = None) -> str:
"""Resolve AUTO moe_backend to a specific backend based on model architecture.

**Not the implementation-selection entry point.** That is
``moe_resolution.resolve_moe_impl``, and the two run in different
phases on different questions. This one turns the literal ``AUTO`` into
a concrete backend name while the checkpoint is being read; the other
turns a concrete backend name into an impl class while a layer is being
built, by asking each candidate's ``can_implement``.

The phases cannot be merged, and the reason is a genuine cycle rather
than an accident of layering: several quant formats pick their
``quant_algo`` from the backend name (see ``get_mxfp4_quant_algo`` and
``load_hf_quant_config``), so a backend name is needed to finish
building ``quant_config`` -- while ``resolve_moe_impl`` needs a
finished ``quant_config`` to state the problem at all. Hence the
deliberate two-step in ``from_pretrained``: an architecture-only hint
first, then a quant-aware resolution once ``quant_config`` exists.

What this must therefore never grow is capability knowledge. Every
rule here is a *preference* ("on Blackwell we would rather run
TRTLLM-Gen"), and preferences that turn out to be unservable are caught
downstream, where ``resolve_moe_impl`` records the substitution in a
``MoEResolutionReport``. A "can it run" test added here would be a
second copy of a gate that already exists in a ``can_implement``, and
the two copies would drift.

Args:
moe_backend: The configured moe_backend (may be "AUTO")
architecture: The model architecture name (e.g., "GptOssForCausalLM")
Expand Down
22 changes: 17 additions & 5 deletions tensorrt_llm/_torch/models/modeling_deepseekv4.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
TritonFusedMoE,
TRTLLMGenFusedMoE,
create_moe,
get_moe_cls,
resolve_moe_cls,
)
from ..modules.fused_moe.fused_moe_deepgemm import DeepGemmFusedMoE
from ..modules.fused_moe.fused_moe_wide_ep import WideEPMoE
Expand Down Expand Up @@ -1504,10 +1504,22 @@ def __init__(
moe_swiglu_limit = None
if swiglu_limit is not None:
# `create_moe` only accepts swiglu_limit for these MoE classes;
# resolve via get_moe_cls so backend-string fallbacks (e.g.
# TRTLLM/CUTEDSL/DENSEGEMM dropping back to CutlassFusedMoE on
# unsupported quant) are handled correctly.
moe_cls = get_moe_cls(model_config, override_quant_config=experts_quant_config)
# ask the resolver rather than the backend string so that a
# degradation (e.g. TRTLLM/CUTEDSL/DENSEGEMM dropping back to
# CutlassFusedMoE on unsupported quant) is accounted for here too.
moe_cls = resolve_moe_cls(
model_config,
override_quant_config=experts_quant_config,
dtype=dtype,
# Same routing object as create_moe below.
routing=self.gate.routing_method,
# create_moe below passes no bias and no swiglu alpha/beta, so
# it resolves with the plain SwiGLU package. Say so here too:
# leaving this unknown lets gates abstain that create_moe
# rejects, and the two calls would pick different backends.
swiglu_gptoss_style=False,
layer_idx=layer_idx,
)
Comment thread
xxi-nv marked this conversation as resolved.
supports_swiglu_limit = moe_cls in (
CutlassFusedMoE,
TritonFusedMoE,
Expand Down
17 changes: 15 additions & 2 deletions tensorrt_llm/_torch/models/modeling_laguna.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@
from ..modules.attention import _helix_cp_allgather_input, _helix_cp_output_projection
from ..modules.decoder_layer import DecoderLayer
from ..modules.embedding import Embedding
from ..modules.fused_moe import MiniMaxM2MoeRoutingMethod, create_moe, get_moe_cls
from ..modules.fused_moe import (
MiniMaxM2MoeRoutingMethod,
RoutingMethodType,
create_moe,
resolve_moe_cls,
)
from ..modules.fused_moe.interface import MoE, MoEWeightLoadingMode
from ..modules.fused_moe.interface import MoE as MoEInterface
from ..modules.gated_mlp import GatedMLP
Expand Down Expand Up @@ -127,7 +132,15 @@ def __init__(self, model_config, layer_idx, aux_stream_dict):
num_experts=self.num_experts,
top_k=self.top_k,
dtype=config.torch_dtype,
moe_backend_cls=get_moe_cls(model_config),
moe_backend_cls=resolve_moe_cls(
model_config,
routing=RoutingMethodType.MiniMax2,
# Match the create_moe call below, which passes no bias and no
# swiglu alpha/beta. Left unknown, gates that create_moe
# rejects abstain here and the gate would name a backend the
# layer does not run.
swiglu_gptoss_style=False,
),
)

self.experts = create_moe(
Expand Down
13 changes: 11 additions & 2 deletions tensorrt_llm/_torch/models/modeling_qwen3_moe.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
RenormalizeMoeRoutingMethod,
RenormalizeNaiveMoeRoutingMethod,
RoutingMethodType, TRTLLMGenFusedMoE,
create_moe, get_moe_cls)
create_moe, resolve_moe_cls)
from ..modules.fused_moe.interface import MoE, MoEWeightLoadingMode
from ..modules.linear import TensorParallelMode
from ..modules.rms_norm import RMSNorm
Expand Down Expand Up @@ -111,7 +111,16 @@ def __init__(
dtype=config.torch_dtype,
apply_routing=False,
routing_method_type=RoutingMethodType.Renormalize,
moe_backend_cls=get_moe_cls(model_config, layer_idx=layer_idx),
moe_backend_cls=resolve_moe_cls(
model_config,
routing=RoutingMethodType.Renormalize,
# Match the create_moe call below, which passes no bias and no
# swiglu alpha/beta. Left unknown, gates that create_moe
# rejects abstain here and the gate would name a backend the
# layer does not run.
swiglu_gptoss_style=False,
layer_idx=layer_idx,
),
)

self.weight_loading_mode = MoEWeightLoadingMode.FUSED_GATE_UP_PROJ if config.model_type == "qwen3_vl_moe_text" else MoEWeightLoadingMode.VANILLA
Expand Down
Loading
Loading