Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
64708a2
finegrained kernels
IlyasMoutawwakil Aug 13, 2026
7b21bdb
deepgemm and tp/ep fixes
IlyasMoutawwakil Aug 15, 2026
05bd0f3
finegrained: adopt the interleaved gate|up layout
IlyasMoutawwakil Aug 16, 2026
686238e
finegrained: keep DeepGEMM Mega MoE on the stacked gate|up layout
IlyasMoutawwakil Aug 18, 2026
641fcb2
fix
IlyasMoutawwakil Aug 18, 2026
e6b20c4
Merge remote-tracking branch 'origin/main' into finegrained-unified
IlyasMoutawwakil Aug 18, 2026
cb04cbe
finegrained: build the per-call kernel objects instead of caching them
IlyasMoutawwakil Aug 21, 2026
e1c7a92
finegrained: fuse both MoE biases into the GEMMs
IlyasMoutawwakil Aug 21, 2026
0a1b49b
Merge origin/main into finegrained-unified
IlyasMoutawwakil Sep 9, 2026
9041320
Merge remote-tracking branch 'origin/main' into finegrained-unified
IlyasMoutawwakil Sep 9, 2026
eac0ee8
finegrained: expert layouts as conversion ops; experts forwards on th…
IlyasMoutawwakil Sep 11, 2026
1d94e55
style
IlyasMoutawwakil Sep 11, 2026
fb16472
finegrained: on-the-fly quantization for every format; loader keeps c…
IlyasMoutawwakil Sep 11, 2026
07dae50
finegrained: pass input_recipe to the dispatchers, drop the Quantizat…
IlyasMoutawwakil Sep 11, 2026
0b6ca4c
Revert "finegrained: pass input_recipe to the dispatchers, drop the Q…
IlyasMoutawwakil Sep 13, 2026
513e231
finegrained: pass activation_format straight through; let deep-gemm s…
IlyasMoutawwakil Sep 14, 2026
240abc9
hub_kernels: finegrained-kernels ships as version 0
IlyasMoutawwakil Sep 14, 2026
30ab2c2
hub_kernels: load finegrained-kernels from the kernels-staging build …
IlyasMoutawwakil Sep 14, 2026
a562fb8
finegrained: consume modelopt's calibrated globals, and fuse a model'…
IlyasMoutawwakil Sep 15, 2026
89267bf
finegrained: address the integration review
IlyasMoutawwakil Sep 15, 2026
09ea21c
finegrained: freeze the mxfp4 and nvfp4 integrations, and serve what …
IlyasMoutawwakil Sep 15, 2026
d59f903
Merge branch 'main' into finegrained-unified
IlyasMoutawwakil Sep 15, 2026
e139d2a
fix style
IlyasMoutawwakil Sep 15, 2026
c665644
FineGrainedFP8Config is its own class again, not an alias of the new one
IlyasMoutawwakil Sep 15, 2026
29cca04
FineGrainedFP8Config: drop the frozen-notice docstring line
IlyasMoutawwakil Sep 15, 2026
f63ad97
Tolerate an experts module without the norm, and a machine without CUDA
IlyasMoutawwakil Sep 16, 2026
1265f0c
Pin that every modelopt converter target is a slot the module holds
IlyasMoutawwakil Sep 16, 2026
97dfa10
is_sm100: answer False without CUDA, and fake both halves in the tests
IlyasMoutawwakil Sep 16, 2026
788d02d
fix
IlyasMoutawwakil Sep 16, 2026
53a8970
finegrained: drop the DTensor unwrap, and pass the kernel operands by…
IlyasMoutawwakil Sep 16, 2026
e8e6b87
deepgemm: only Mega MoE cannot apply a post-expert norm
IlyasMoutawwakil Sep 16, 2026
43b9a74
Shard quantized expert companions under EP and TP
IlyasMoutawwakil Sep 17, 2026
fe0b718
fixes for the new model
IlyasMoutawwakil Sep 17, 2026
22b1001
fix multimodal and add some testing
IlyasMoutawwakil Sep 17, 2026
f9302cc
static
IlyasMoutawwakil Sep 18, 2026
daa2420
Load a calibrated checkpoint's input_scale, and fix what per-tensor w…
IlyasMoutawwakil Sep 18, 2026
b4dcb7b
fix
IlyasMoutawwakil Sep 18, 2026
f7081ec
Finish the finegrained integration: reload, TP sharding, dsv4 norms
IlyasMoutawwakil Sep 21, 2026
9ddb214
Fix a destructive Qwen3 TP-plan override; split out the conversions
IlyasMoutawwakil Sep 21, 2026
e83eadf
Collapse the conversion-op boilerplate; shorten the longest units
IlyasMoutawwakil Sep 21, 2026
60f904e
Key on capability not name; drop the last op boilerplate
IlyasMoutawwakil Sep 22, 2026
4cb5d9c
Quantize per module group; split the arms by producer, not by format
IlyasMoutawwakil Sep 22, 2026
a67e7ac
Carry the quantized-load fixes onto the per-scheme arms, and the same…
IlyasMoutawwakil Sep 22, 2026
9fc683d
Address the per-scheme review
IlyasMoutawwakil Sep 23, 2026
95b3e44
trim
IlyasMoutawwakil Sep 23, 2026
2392e6a
fixes
IlyasMoutawwakil Sep 23, 2026
f7a8e54
last
IlyasMoutawwakil Sep 23, 2026
4cbbe7f
Cover the groups feature, and export what it asks callers to build
IlyasMoutawwakil Sep 23, 2026
f687860
Point everything at the fine-grained integration; deprecate the froze…
IlyasMoutawwakil Sep 23, 2026
fab7f74
Bring two comment blocks under the noisy-comment limits
IlyasMoutawwakil Sep 23, 2026
21c0a07
Bring two comment blocks under the noisy-comment limits
IlyasMoutawwakil Sep 23, 2026
12f5aa8
Do not let the tied-head plan raise in post_init
IlyasMoutawwakil Sep 23, 2026
7abcedf
Do not let the tied-head plan raise in post_init
IlyasMoutawwakil Sep 23, 2026
db85a44
Address the second review round
IlyasMoutawwakil Sep 24, 2026
d5c361c
Merge finegrained-replace-frozen-fp8 into finegrained-per-scheme-demo
IlyasMoutawwakil Sep 24, 2026
9f7326c
Carry the review's comment and lint fixes to the sites it did not name
IlyasMoutawwakil Sep 24, 2026
f1b593d
Make tests/kernels a package so the moved fp8 test can import its fix…
IlyasMoutawwakil Sep 24, 2026
0067189
Declare GLM-4v-MoE's head plan instead of deriving it in the mixin
IlyasMoutawwakil Sep 24, 2026
bb24085
cleanup guards and post expert norm in deepgemm
IlyasMoutawwakil Sep 24, 2026
39eb1d1
not now
IlyasMoutawwakil Sep 24, 2026
bf0e7ec
minimal peft integration preparation
IlyasMoutawwakil Sep 24, 2026
5b2b7f0
addressing review comments
IlyasMoutawwakil Sep 25, 2026
f3c7cc8
Tiny checkpoints for every shipped layout, and the save/load fixes th…
IlyasMoutawwakil Sep 25, 2026
6a7c92e
Keep pre-quantized scale dtypes through the dtype plan
IlyasMoutawwakil Sep 25, 2026
2d1f0bc
Update src/transformers/distributed/sharding_utils.py
IlyasMoutawwakil Sep 30, 2026
f37d1d4
Update src/transformers/distributed/sharding_utils.py
IlyasMoutawwakil Sep 30, 2026
5ea2a3e
adapters
IlyasMoutawwakil Sep 30, 2026
c766206
Fine-grained layout ops: follow the experts module each tensor fills
IlyasMoutawwakil Oct 2, 2026
7d44b81
Revert "adapters"
IlyasMoutawwakil Oct 2, 2026
eb9c09f
trimming
IlyasMoutawwakil Oct 2, 2026
77f135c
Fine-grained NVFP4: exact per-expert gate_up activation globals
IlyasMoutawwakil Oct 5, 2026
71ee044
Merge origin/main into finegrained-per-scheme-demo
IlyasMoutawwakil Oct 15, 2026
4e8aa7e
Fine-grained tests: per-expert gate_up activation globals, and the op…
IlyasMoutawwakil Oct 15, 2026
9620ef5
Merge main into finegrained-per-scheme-demo
IlyasMoutawwakil Oct 15, 2026
585946e
test muse sparknvfp4 after merge
IlyasMoutawwakil Oct 15, 2026
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
8 changes: 4 additions & 4 deletions docs/source/en/experts_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ The kernel is loaded lazily on the first forward.

### FP8 and FP4 quantized experts

DeepSeek-style checkpoints are usually pre-quantized and carry their own quantization config, so you don't need to pass a [`FineGrainedFP8Config`]. The `"deepgemm"` backend automatically picks the FP8 (or FP4 on Blackwell) grouped-GEMM kernel. DeepGEMM requires dynamic per-row activation scales (`activation_scheme="dynamic"`) and rejects static (per-tensor) activation quantization.
DeepSeek-style checkpoints are usually pre-quantized and carry their own quantization config, so you don't need to pass a [`FineGrainedConfig`]. The `"deepgemm"` backend automatically picks the FP8 (or FP4 on Blackwell) grouped-GEMM kernel. DeepGEMM requires dynamic per-row activation scales (`activation_scheme="dynamic"`) and rejects static (per-tensor) activation quantization.

```py
from transformers import AutoModelForCausalLM
Expand All @@ -133,14 +133,14 @@ For FP4-packed expert weights (DeepSeek V4-style), the GPU must be SM100+ (Black
> [!NOTE]
> On Blackwell (SM100+), the `"deepgemm"` and `"deepgemm_megamoe"` experts kernels require power-of-two UE8M0 expert scales. A checkpoint quantized with plain `float32` scales (`scale_fmt="float"`) raises a `ValueError` on the first forward instead of silently corrupting the output. Load a checkpoint quantized with `scale_fmt="ue8m0"`, or switch to `grouped_mm` or `batched_mm`, which consume `float32` block scales directly. Hopper (SM90+) consumes `float32` scales on the DeepGEMM path without conversion.

The main reason to pass a [`FineGrainedFP8Config`] for a pre-quantized checkpoint is to dequantize it back to `bfloat16`, in which case the experts run in `bfloat16` rather than on the FP8/FP4 DeepGEMM path.
The main reason to pass a [`FineGrainedConfig`] for a pre-quantized checkpoint is to dequantize it back to `bfloat16`, in which case the experts run in `bfloat16` rather than on the FP8/FP4 DeepGEMM path.

```py
from transformers import AutoModelForCausalLM, FineGrainedFP8Config
from transformers import AutoModelForCausalLM, FineGrainedConfig

model = AutoModelForCausalLM.from_pretrained(
"deepseek-ai/DeepSeek-V3",
quantization_config=FineGrainedFP8Config(dequantize=True),
quantization_config=FineGrainedConfig(dequantize=True),
experts_implementation="deepgemm",
)
```
Expand Down
13 changes: 13 additions & 0 deletions docs/source/en/main_classes/quantization.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ Learn how to quantize models in the [Quantization](../quantization/overview) gui

[[autodoc]] SpQRConfig

## FineGrainedConfig
Comment thread
IlyasMoutawwakil marked this conversation as resolved.
Resolved

> [!WARNING]
> `FineGrainedConfig` supersedes `FineGrainedFP8Config`, `Mxfp4Config` and `NVFP4Config`, which are
> frozen and will be removed in a future release. The `fp8`, `mxfp8`, `mxfp4` and `nvfp4`
> `quant_method` keys already route here, so existing checkpoints need no change.

[[autodoc]] FineGrainedConfig

## FineGrainedGroup

[[autodoc]] FineGrainedGroup

## FineGrainedFP8Config

[[autodoc]] FineGrainedFP8Config
Expand Down
4 changes: 2 additions & 2 deletions docs/source/en/model_doc/deepseek_v32.md
Comment thread
IlyasMoutawwakil marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ In DeepSeek-V3.2 **every layer runs its own indexer** — there is no cross-laye
DeepSeek-V3.2-Exp is distributed as an FP8 checkpoint. The indexer projections are kept out of FP8 quantization, since the checkpoint stores them in bf16/fp32:

```python
from transformers import FineGrainedFP8Config, AutoModelForCausalLM, AutoTokenizer
from transformers import FineGrainedConfig, AutoModelForCausalLM, AutoTokenizer
import torch

model_name = "deepseek-ai/DeepSeek-V3.2-Exp"
quantization_config = FineGrainedFP8Config(
quantization_config = FineGrainedConfig(
modules_to_not_convert=["model.layers.*.mlp.gate.*", "*.self_attn.indexer.weights_proj.*"],
weight_block_size=(128, 128),
)
Expand Down
4 changes: 2 additions & 2 deletions docs/source/en/model_doc/minimax_m3_vl.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ from transformers import (
AutoModelForImageTextToText,
AutoTokenizer,
CompileConfig,
FineGrainedFP8Config,
FineGrainedConfig,
)
from transformers.distributed import DistributedConfig

Expand All @@ -164,7 +164,7 @@ model = AutoModelForImageTextToText.from_pretrained(
"MiniMaxAI/MiniMax-M3-preview",
dtype=torch.bfloat16,
# Dequantize the native MXFP8 weights to bf16 at load (the speed win); needs even TP/EP sharding.
quantization_config=FineGrainedFP8Config(dequantize=True),
quantization_config=FineGrainedConfig(dequantize=True),
distributed_config=DistributedConfig(
tp_size=int(os.environ["WORLD_SIZE"]),
ep_size=int(os.environ["WORLD_SIZE"]),
Expand Down
7 changes: 7 additions & 0 deletions docs/source/en/quantization/finegrained_fp8.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ rendered properly in your Markdown viewer.

# Fine-grained FP8

> [!WARNING]
> `FineGrainedFP8Config` is frozen and receives no new recipes. [`FineGrainedConfig`] supersedes it, serving
> block-FP8, MXFP8, MXFP4 and NVFP4 through one config for dense linears, embeddings and MoE
> experts alike. Existing checkpoints keep loading — the `fp8`, `mxfp8`, `mxfp4` and `nvfp4`
> `quant_method` keys now route to the fine-grained integration — so this page is here for
> reference while the frozen classes remain. They will be removed in a future release.

Fine-grained FP8 quantization quantizes the weights and activations to fp8.

- The weights are quantized to 8-bits for each 2D block (`weight_block_size=(128, 128)`).
Expand Down
7 changes: 7 additions & 0 deletions docs/source/en/quantization/mxfp4.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ rendered properly in your Markdown viewer.

# MXFP4

> [!WARNING]
> `Mxfp4Config` is frozen and receives no new recipes. [`FineGrainedConfig`] supersedes it, serving
> block-FP8, MXFP8, MXFP4 and NVFP4 through one config for dense linears, embeddings and MoE
> experts alike. Existing checkpoints keep loading — the `fp8`, `mxfp8`, `mxfp4` and `nvfp4`
> `quant_method` keys now route to the fine-grained integration — so this page is here for
> reference while the frozen classes remain. They will be removed in a future release.

Note: MXFP4 quantization currently only works for OpenAI GPT-OSS 120b and 20b.

MXFP4 is a 4-bit floating point format that dramatically reduces the memory requirements of large models. Large models (GPT-OSS-120B) can fit on a single 80GB GPU and smaller models (GPT-OSS-20B) only require 16GB of memory. It uses blockwise scaling to preserve its range and accuracy, which typically becomes degraded at lower precisions.
Expand Down
7 changes: 7 additions & 0 deletions docs/source/en/quantization/nvfp4.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ rendered properly in your Markdown viewer.

# NVFP4

> [!WARNING]
> `NVFP4Config` is frozen and receives no new recipes. [`FineGrainedConfig`] supersedes it, serving
> block-FP8, MXFP8, MXFP4 and NVFP4 through one config for dense linears, embeddings and MoE
> experts alike. Existing checkpoints keep loading — the `fp8`, `mxfp8`, `mxfp4` and `nvfp4`
> `quant_method` keys now route to the fine-grained integration — so this page is here for
> reference while the frozen classes remain. They will be removed in a future release.

NVFP4 quantization packs full-precision linear weights into NVIDIA's 4-bit floating-point format while a model is
loaded. [`NVFP4Config`] replaces eligible bias-free `torch.nn.Linear` modules, whose `in_features` and `out_features` are both divisible by 16, with an NVFP4 linear implementation from
the [NVFP4 Hub kernel](https://huggingface.co/kernels-community/nvfp4-gemm). The model's attention and MLP interfaces are
Expand Down
4 changes: 4 additions & 0 deletions src/transformers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@
"CompressedTensorsConfig",
"EetqConfig",
"FbgemmFp8Config",
"FineGrainedConfig",
"FineGrainedFP8Config",
"FineGrainedGroup",
"FourOverSixConfig",
"FPQuantConfig",
"GemmaQuantizationConfig",
Expand Down Expand Up @@ -737,7 +739,9 @@
from .utils.quantization_config import CompressedTensorsConfig as CompressedTensorsConfig
from .utils.quantization_config import EetqConfig as EetqConfig
from .utils.quantization_config import FbgemmFp8Config as FbgemmFp8Config
from .utils.quantization_config import FineGrainedConfig as FineGrainedConfig
from .utils.quantization_config import FineGrainedFP8Config as FineGrainedFP8Config
from .utils.quantization_config import FineGrainedGroup as FineGrainedGroup
from .utils.quantization_config import FourOverSixConfig as FourOverSixConfig
from .utils.quantization_config import FPQuantConfig as FPQuantConfig
from .utils.quantization_config import GemmaQuantizationConfig as GemmaQuantizationConfig
Expand Down
27 changes: 20 additions & 7 deletions src/transformers/conversion_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,16 +546,21 @@ def _build_checkpoint_conversion_mapping():
),
],
"deepseek_v4": [
# checkpoint-form renames the general `.attn.` one below would otherwise take first
WeightRenaming(source_patterns=r"\.attn\.wq_b\.", target_patterns=r".attn.q_b_proj."),
# General mid-key renames acting on several keys
WeightRenaming(source_patterns=r"\.attn\.", target_patterns=r".self_attn."),
WeightRenaming(source_patterns=r"\.ffn\.", target_patterns=r".mlp."),
WeightRenaming(source_patterns=r"\.indexer\.compressor\.", target_patterns=r"\.compressor\.indexer\."),
# Leaf patterns
WeightRenaming(source_patterns=r"^embed\.weight$", target_patterns="embed_tokens.weight"),
# The checkpoint has no `model.` prefix: named here, so a save takes it back off
WeightRenaming(source_patterns=r"^layers\.", target_patterns="model.layers."),
WeightRenaming(source_patterns=r"^norm\.weight$", target_patterns="model.norm.weight"),
WeightRenaming(source_patterns=r"^embed\.weight$", target_patterns="model.embed_tokens.weight"),
WeightRenaming(source_patterns=r"^head\.weight$", target_patterns="lm_head.weight"),
WeightRenaming(source_patterns=r"^hc_head_fn$", target_patterns="hc_head.hc_fn"),
WeightRenaming(source_patterns=r"^hc_head_base$", target_patterns="hc_head.hc_base"),
WeightRenaming(source_patterns=r"^hc_head_scale$", target_patterns="hc_head.hc_scale"),
WeightRenaming(source_patterns=r"^hc_head_fn$", target_patterns="model.hc_head.hc_fn"),
WeightRenaming(source_patterns=r"^hc_head_base$", target_patterns="model.hc_head.hc_base"),
WeightRenaming(source_patterns=r"^hc_head_scale$", target_patterns="model.hc_head.hc_scale"),
WeightRenaming(source_patterns=r"\.attn_norm\.", target_patterns=r".input_layernorm."),
WeightRenaming(source_patterns=r"\.ffn_norm\.", target_patterns=r".post_attention_layernorm."),
WeightRenaming(source_patterns=r"\.hc_attn_fn$", target_patterns=r".attn_hc.fn"),
Expand All @@ -570,10 +575,13 @@ def _build_checkpoint_conversion_mapping():
target_patterns=r"\.compressor\.indexer\.scorer\.weights_proj\.",
),
WeightRenaming(source_patterns=r"\.indexer\.wq_b\.", target_patterns=r"\.compressor\.indexer\.q_b_proj\."),
WeightRenaming(source_patterns=r"\.norm\.", target_patterns=r"\.kv_norm\."),
# the compressors' norms only: the attention's own is `kv_norm` already, and a save reversing a
# bare `.kv_norm.` would rename it too (`[.]`: the reverse unescapes a group's `\.`)
WeightRenaming(
source_patterns=r"\.compressor\.(|indexer[.])norm\.", target_patterns=r"\.compressor\.\1kv_norm\."
),
WeightRenaming(source_patterns=r"\.ape$", target_patterns=r"\.position_bias"),
WeightRenaming(source_patterns=r"\.wq_a\.", target_patterns=r".q_a_proj."),
WeightRenaming(source_patterns=r"\.self_attn\.wq_b\.", target_patterns=r"\.self_attn\.q_b_proj\."),
WeightRenaming(source_patterns=r"\.wkv\.", target_patterns=r".kv_proj."),
WeightRenaming(source_patterns=r"\.wgate\.", target_patterns=r".gate_proj."),
WeightRenaming(source_patterns=r"\.wo_a\.", target_patterns=r".o_a_proj."),
Expand Down Expand Up @@ -683,7 +691,12 @@ def _build_checkpoint_conversion_mapping():
source_patterns=r"^patch_merge_mlp\.linear_2\.",
target_patterns="model.multi_modal_projector.merge_linear_2.",
),
WeightRenaming(source_patterns=r"\.block_sparse_moe\.", target_patterns=r"\.mlp\."),
# the MoE block only, so a save does not reverse the dense and vision `.mlp.` too (`[.]`: the
# reverse unescapes a group's `\.`)
WeightRenaming(
source_patterns=r"\.block_sparse_moe\.(experts[.]|gate[.]|shared_experts[.]|e_score_correction_bias$)",
target_patterns=r"\.mlp\.\1",
),
WeightRenaming(
source_patterns=r"\.e_score_correction_bias", target_patterns=r"\.gate\.e_score_correction_bias"
),
Expand Down
Loading
Loading