models#
Per-model descriptors, one package per HF model type.
Directory names are the HF config.model_type they describe; a model whose code
ships with the checkpoint uses its remote-code model_type and records that as
ModelSpec.modeling_source, while a model defined in transformers records the release
its definitions come from as ModelSpec.min_transformers_version. Each package’s
specs.py registers one global ModelSpec (built from the section classes in this
package’s own specs.py) at import time. Importing this package registers them all.
Consumers resolve a spec via the registry lookups (get_spec / match_moe_block)
and read its sections.
The per-model file is named for what it holds, not for who reads it: a model’s spec is general model data, and export is only its first consumer.
A package may also hold modeling_ptq.py, the model-specific PTQ wrappers. It is not imported
here; the HF quantization plugin imports it (see README.md).
Classes
Subsystem section: per-model data of the expert-parallel (DP=EP) PTQ path. |
|
Subsystem section: per-model data of the unified HF export path. |
|
Topic section: the model's MoE-block layout. |
|
The one global per-model descriptor, holding each section as an attribute. |
|
Base class for the sections composing a |
Functions
Return the spec registered for |
|
Return all registered specs, in registration order. |
|
Return the root HF model type ( |
|
Return whether |
|
List a spec attribute's values across all registered specs, deduplicated in order. |
|
Return True if any of |
|
Return the MoE layout layout for |
|
Return the spec whose MoE section matches |
|
Register a model spec and return it. |
- class EPSpec#
Bases:
SpecSectionSubsystem section: per-model data of the expert-parallel (DP=EP) PTQ path.
Calibrating a large MoE data-parallel with its experts sharded needs three things from the model, and all three are facts about the architecture rather than about any run: which modules are the routed experts and how they shard, which transformers release first ships that information, and – for a VLM – which nested config carries it.
Most models need only the data below. A checkpoint whose modeling code it ships itself may need actual code run against it before it can be loaded expert-parallel (patching a remote-code class, decompressing packed experts); that is what
prepareis for, and it is deliberately the exception rather than the interface.- __init__(*, base_model_ep_plan=None, requires_transformers=None, plan_config_attr=None, prepare=None, prepared_ep_plan=None, unsupported=None)#
- Parameters:
base_model_ep_plan (dict[str, str] | None)
requires_transformers (str | None)
plan_config_attr (str | None)
prepare (Callable[..., Any] | None)
prepared_ep_plan (dict[str, str] | None)
unsupported (str | None)
- Return type:
None
- base_model_ep_plan: dict[str, str] | None = None#
The
base_model_ep_plantransformers needs to shard this model’s experts, applied to the config when it does not already carry one.Stock transformers ships a plan for some MoE models and not others; where it does, leave this
Noneand let the model’s own plan win. Entries map a parameter glob to a parallel style, e.g.{"layers.*.mlp.experts.gate_up_proj": "grouped_gemm"}.A router entry is not always wanted. DeepSeek-V3’s router is logits-only and its MoE block computes global top-k ids, so the experts already receive unmasked global ids – which is exactly what the all-to-all dispatch needs, and adding a gate entry would mask them.
- plan_config_attr: str | None = None#
The nested config attribute carrying the expert-parallel plan, for a VLM whose MoE is its text sub-model (
"text_config","llm_config").Nonemeans the root config.The plan has to sit on whichever config describes the module tree the globs are written against, so a plan on the wrong config silently matches nothing.
- prepare: Callable[..., Any] | None = None#
Escape hatch for a model that cannot be made expert-parallel by data alone.
Called as
prepare(hf_config, ckpt_path=..., trust_remote_code=...)and returns the config to load. Reserved for checkpoints carrying their own modeling code, where the work is patching classes or installing on-the-fly weight decompression. Runs after the declarative fields above have been applied.
- prepared_ep_plan: dict[str, str] | None = None#
The
base_model_ep_planprepareattaches, for a model whose plan onlypreparesupplies.Stated, not applied:
preparestill attaches it. A run that rules expert parallelism out skipsprepare, which patches the model’s code, yet must still tell an expert-parallel MoE it would hold whole on every rank from a dense model. It finds the routed experts through this plan, in the model as the checkpoint’s own code builds it:preparereplaces the experts in place, so the plan names their containers there too.
- requires_transformers: str | None = None#
Earliest transformers release that supports THIS model expert-parallel, when it is later than the framework floor.
Distinct from
ModelSpec.min_transformers_version, which is about the modeling code matching the spec. A model can be fully modelled and still not be shardable: qwen3_moe’s ownbase_model_ep_planlands in 5.7, while the shared EP framework is 5.6.
- unsupported: str | None = None#
Why this model cannot be quantized expert-parallel yet, when its config would route it there.
Stock transformers ships a
base_model_ep_planfor some MoEs the expert-parallel path cannot handle, and the plan alone makes a model expert-parallel capable. Naming the reason here refuses the run before any weight is loaded instead of failing deep in quantization.
- class ExportSpec#
Bases:
SpecSectionSubsystem section: per-model data of the unified HF export path.
Architecture facts (MoE block classes, expert naming) live in
MoESpec; this section holds data consumed by the export algorithms only.- __init__(*, grouped_expert_export=False, pqs_fuse_rules=(), weight_plus_one_norm_names=())#
- Parameters:
grouped_expert_export (bool)
pqs_fuse_rules (tuple[tuple[tuple[str, ...], str, str], ...])
weight_plus_one_norm_names (tuple[str, ...])
- Return type:
None
- grouped_expert_export: bool = False#
Whether
get_experts_listmay group this model’s experts for the AWQ / NVFP4-SVDQuant resmoothing pass.A statement about what modelopt has validated, not about the model:
qwen3_5_moeis architecturally identical toqwen3_moehere and is stillFalse, because the pre-registry code keyed off the root class name and"qwen3_5moeforcausallm"matched none of its qwen substrings. That is why it lives in the export section rather than onMoESpec, which holds only facts about the architecture.Whether the experts are actually iterable is separate again, and read off the module: a model listed here still exports fine when a newer transformers fuses its experts, because there is then simply nothing to group.
- pqs_fuse_rules: tuple[tuple[tuple[str, ...], str, str], ...] = ()#
AWQ
pre_quant_scalefusion rules, each a(module_class_substrings, fuse_into, fuse_from)triple: for a module whose class name contains one of the substrings, the pre_quant_scale onfuse_fromis folded intofuse_into(e.g. attentiono_proj->v_proj, MLPdown_proj->up_proj). A rule asserts mathematical equivalence for that model’s modules, so it is declared per model rather than applied generically.
- weight_plus_one_norm_names: tuple[str, ...] = ()#
Class names of norm layers whose stored weight is
w - 1(the effective scale isweight + 1), e.g. Gemma’s RMSNorm layouts and LayerNorm1P. Matched against a norm module’s MRO (case-insensitive exact names). Export must account for the +1 when folding scales into the norm weight (AWQ pre_quant_scale fusion). A structural fallback (zero_centered_gamma) stays in the engine.
- class MoESpec#
Bases:
SpecSectionTopic section: the model’s MoE-block layout.
Describes what a model’s MoE blocks are – which class, what the expert projections are called, how they are stored – so any modelopt subsystem (export, quantization, speculative decoding, …) can read it instead of keeping its own per-model MoE table.
One layout per model.
block_namesis a tuple, so a model whose MoE appears under several class names is covered as long as they share a layout (gpt_oss’sGptOssMLP/GptOssMoE; Qwen3-Omni’s Thinker and Talker blocks). No model in transformers needs two different layouts today. If one ever does, this section becomes a tuple onModelSpec; nothing here is shaped to prevent that.A layout is a fact about the architecture. Whether modelopt’s grouped export path may use it is policy and lives in
ExportSpec; whether the experts are iterable right now depends on the installed transformers and is read off the module.- __init__(*, block_names=(), expert_linear_names=None, fused_expert_names=False, gate_up_pair=None)#
- Parameters:
block_names (tuple[str, ...])
expert_linear_names (tuple[str, ...] | None)
fused_expert_names (bool)
gate_up_pair (tuple[str, str] | None)
- Return type:
None
- block_names: tuple[str, ...] = ()#
The matching key – MoE block class names, matched against the module’s MRO (case-insensitive exact names, not substrings; see
match_class_names).
- expert_linear_names: tuple[str, ...] | None = None#
Expert linear projection names, e.g.
("gate_proj", "down_proj", "up_proj"). For layouts modelopt rewrites into per-expert modules, these are the names on the rewritten module.
- expert_linear_names_for(module, fused=None)#
Resolve
module’s expert linear names, or None when this layout cannot.The module’s class is not consulted: a spec may provide naming without declaring
block_namesat all, and with one layout per model there is nothing to disambiguate.fusedis the layout the caller observed on the module. Passing it makes the answer conditional on describing that same layout, so a spec that only describes the per-expert form declines for a fused container rather than returning names that do not apply there.Noneaccepts either.- Parameters:
fused (bool | None)
- Return type:
tuple[str, …] | None
- fused_expert_names: bool = False#
True when
expert_linear_namesname a fused container’s own 3-D parameters (gate_up_proj/down_proj) rather than per-expert sub-modules.The same model type materializes both ways across transformers releases, so a consumer must know which layout a naming describes: applied to the other one it is wrong, not merely generic.
- gate_up_pair: tuple[str, str] | None = None#
The (gate, up) pair among
expert_linear_namesthat serving engines fuse into a singlegate_up_proj, e.g.("gate_proj", "up_proj")or("w1", "w3").Nonefor non-gated experts (NemotronH) and already-fused layouts (GptOss).
- property gate_up_pairs: tuple[tuple[str, str], ...]#
This layout’s (gate, up) pair, as a tuple so it can join a global vocabulary.
- matches(module)#
Whether
module’s class is one this layout describes.- Return type:
bool
- class ModelSpec#
Bases:
objectThe one global per-model descriptor, holding each section as an attribute.
Resolved by HF model type (see
get_specbelow); a model registers exactly one instance, filling only the sections it customizes and leaving the restNone. Consumers must handle an absent section;match_moe_blockandlist_all_possiblealready do for the lookups they cover.- __init__(*, model_type, min_transformers_version=None, modeling_source='transformers', moe_spec=None, export_spec=None, ep_spec=None)#
- Parameters:
model_type (str)
min_transformers_version (str | None)
modeling_source (Literal['transformers', 'remote_code'])
moe_spec (MoESpec | None)
export_spec (ExportSpec | None)
ep_spec (EPSpec | None)
- Return type:
None
- ep_spec: EPSpec | None = None#
Per-model data of the expert-parallel PTQ path, or
Nonewhen the model is dense or needs nothing beyond what stock transformers already ships.
- export_spec: ExportSpec | None = None#
Per-model data of the unified HF export path, or
Nonewhen export needs nothing model-specific.
- min_transformers_version: str | None = None#
Earliest
transformersrelease whose definitions match this spec, orNonewhen the question does not apply (modeling_source="remote_code").Clamped below at the repo’s minimum supported transformers (
tf_mininnoxfile.py): a model that predates the floor records the floor, since nothing older is ever installed or tested. A model added after the floor records its own release, which is what lets the test suite tell an expected absence on an older transformers apart from a spec that no longer matches reality.
- model_type: str#
The HF model type this spec describes (
config.model_type, e.g."qwen3_moe"). Unique across the registry.
- modeling_source: Literal['transformers', 'remote_code'] = 'transformers'#
shipped inside
transformers, or carried by the checkpoint and loaded withtrust_remote_code=True.A fact about the model, not about any one subsystem: it decides whether the classes named in this spec can be imported at all, so
model_typeis a remote-code spelling rather than a transformers one, and loading the model needs the flag.- Type:
Where the model’s modeling code lives
- class SpecSection#
Bases:
objectBase class for the sections composing a
ModelSpec.Marks a class as a section so
_spec_sectionscan findModelSpec’s section fields from its annotations. Without it the lookups would need a hand-maintained list of section names, which would silently fall out of date the first time a section was added and the list was not.- __init__()#
- Return type:
None
- get_spec(model_type)#
Return the spec registered for
model_type, orNone.- Parameters:
model_type (str)
- Return type:
ModelSpec | None
- hf_model_type(model)#
Return the root HF model type (
model.config.model_type), orNone.Accepts a model or a config object (duck-typed, no transformers import). This is the key for
get_spec/match_moe_block.- Return type:
str | None
- is_moe(module, model_type=None)#
Return whether
moduleis an MoE block.model_type(model.config.model_type) scopes the registry lookup to the model’s own spec;Nonesearches every spec.The model’s own spec is consulted first, so per-model data always outranks the generic name and structural fallbacks. The fallbacks matter: a model with no spec still has to be recognised, which is what keeps export working for MoE architectures nobody has registered.
- Parameters:
module (Module)
model_type (str | None)
- Return type:
bool
- list_all_possible(attr)#
List a spec attribute’s values across all registered specs, deduplicated in order.
E.g.
list_all_possible("gate_up_pairs"). Looks the name up onModelSpecand then on its sections, so callers name the field ("pqs_fuse_rules") without naming the section that holds it. Models whose declaring section isNonecontribute nothing.The result is a global vocabulary: consumers match it against any model’s modules, so adding a value to one spec affects all models the consumer walks — prefer
get_spec(model_type)/match_moe_blockwherever the owning model is identifiable.attrmust name a tuple-valued attribute. Scalars (model_type) would be iterated character by character, so they are rejected rather than silently producing nonsense.- Parameters:
attr (str)
- Return type:
tuple
- match_class_names(module, names)#
Return True if any of
namesequals a class name inmodule’s MRO.Case-insensitive exact-name comparison against every class in
type(module).__mro__: dynamically generated quantized classes match through their base class, and exact names avoid substring false positives.- Parameters:
names (tuple[str, ...])
- Return type:
bool
- match_moe_block(module, model_type=None)#
Return the MoE layout layout for
module, resolved by model type.model_type(the rootmodel.config.model_type) is a strict filter: only that model’s own spec is consulted, and an unregistered model type resolves toNoneeven if the module’s class names coincide with another model’s.model_type=Nonesearches all specs. A composite model whose MoE lives under a sub-model type registers the root type too (seegemma4/specs.py). Within the spec,block_namesmatched against the module’s MRO decides.- Parameters:
module (nn.Module)
model_type (str | None)
- Return type:
MoESpec | None
- match_moe_model(module, model_type=None)#
Return the spec whose MoE section matches
module, or None.Same scoping as
match_moe_block, which returns only the layout; use this when a consumer also needs the model’s other sections, such as the export policy that says whether its experts may be grouped.- Parameters:
module (nn.Module)
model_type (str | None)
- Return type:
ModelSpec | None