Skip to content

Fix WeightConverter substring match on leaf-style source patterns - #45794

Closed
qgallouedec wants to merge 1 commit into
mainfrom
fix-weightconverter-leaf-pattern-anchor
Closed

qgallouedec wants to merge 1 commit into
mainfrom
fix-weightconverter-leaf-pattern-anchor

Conversation

@qgallouedec

Copy link
Copy Markdown
Member

WeightConverter source patterns are compiled with re.search, so a pattern ending in an identifier (e.g. experts.gate_up_proj) substring-matches sibling keys like experts.gate_up_proj_scale_inv. On save_pretrained, the reverse converter then routes the FP8 scale companion through [Chunk, SplitModulelist]. With block-quantized scales of shape (n_experts, 1, 1), torch.chunk(tensor, 2, dim=1) returns 1 piece instead of 2, and SplitModulelist.get_target_patterns raises:

ValueError: Undefined Operation encountered!

Scope. Only save_pretrained is affected! from_pretrained and inference round-trip cleanly. I.e. loading and using DeepSeek-v4 works.
The bug breaks any user flow that writes the model back to disk: re-exporting a loaded FP8 checkpoint, pushing a fork to the Hub, or checkpointing during fine-tuning.

It is not DeepSeek-V4-specific: any model whose conversion mapping has a multi-source WeightConverter with a leaf-style target name and a sibling key sharing that prefix (e.g. an FP8 *_scale_inv companion) hits the same substring-match. DeepSeek-V4 is the first in-tree model to combine those ingredients.

Fix

In WeightTransform.__init__, auto-anchor leaf-style source patterns at a key boundary when compiling the alternation regex:

if pattern and (pattern[-1].isalnum() or pattern[-1] == "_"):
    pattern = f"{pattern}(?=$|\\.)"

Patterns that already end in $ or in a separator (\. for prefix renames) are unaffected. Now experts.gate_up_proj matches ...experts.gate_up_proj but no longer matches ...experts.gate_up_proj_scale_inv.

Repro

import torch, tempfile
from torch import nn
from transformers import DeepseekV4Config, DeepseekV4ForCausalLM
from transformers.models.deepseek_v4.modeling_deepseek_v4 import DeepseekV4Experts

cfg = DeepseekV4Config(
    vocab_size=128, hidden_size=8, num_attention_heads=4, num_key_value_heads=1, num_hidden_layers=2, intermediate_size=32,
    quantization_config={"activation_scheme": "dynamic", "fmt": "e4m3", "quant_method": "fp8", "scale_fmt": "ue8m0", "weight_block_size": [128, 128]},
)
m = DeepseekV4ForCausalLM(cfg).to(dtype=torch.bfloat16)


def cdiv(a, b):
    return (a + b - 1) // b


# Attach all FP8 scale companions, matching what DeepSeek-v4 has.
for name, mod in m.named_modules():
    if isinstance(mod, nn.Linear) and not name.endswith("lm_head"):
        of, inf = mod.out_features, mod.in_features
        mod.register_parameter("weight_scale_inv", nn.Parameter(torch.ones(cdiv(of, 128), cdiv(inf, 128)), requires_grad=False))
    elif isinstance(mod, DeepseekV4Experts):
        n, gu_o, gu_i = mod.gate_up_proj.shape
        _, d_o, d_i = mod.down_proj.shape
        mod.register_parameter("gate_up_proj_scale_inv", nn.Parameter(torch.ones(n, cdiv(gu_o, 128), cdiv(gu_i, 128)), requires_grad=False))
        mod.register_parameter("down_proj_scale_inv", nn.Parameter(torch.ones(n, cdiv(d_o, 128), cdiv(d_i, 128)), requires_grad=False))

with tempfile.TemporaryDirectory() as d:
    m.save_pretrained(d)  # before fix: raises Undefined Operation; workaround: save_kwargs={"save_original_format": False}
    DeepseekV4ForCausalLM.from_pretrained(d)  # before fix (with workaround): MISSING list

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Comment on lines +658 to +663
# Auto-anchor leaf-style patterns (those ending with an identifier char) at a key
# boundary, so e.g. ``experts.gate_up_proj`` does not also match
# ``experts.gate_up_proj_scale_inv``. Skip patterns that already end in an explicit
# anchor (``$``) or that intentionally end on a separator (``\.``) for prefix renames.
if pattern and (pattern[-1].isalnum() or pattern[-1] == "_"):
pattern = f"{pattern}(?=$|\\.)"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo we should allow it in case models need to replace anything that starts with "prefix", and the issue is in the regex of MoE in conversion mapping. We need to add an explicit /. in regex instead

in any case cc @Cyrilvallez to decide on it

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah and probably error out? this is a good example where there's inteded vs not intended and we should probably not I think assume user wants one of the two

@Cyrilvallez Cyrilvallez left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with @zucchini-nlp! We cannot force such matching strategy without breaking matching logic in general. The specific deepseekv4 pattern should be changed instead! Let's just add a final dot to the pattern to avoid wrong matches

@qgallouedec

Copy link
Copy Markdown
Member Author

closing in favour of #45930

ArthurZucker added a commit that referenced this pull request Jun 1, 2026
* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (#45930)"

This reverts commit ecc7e32.

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes #45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was #45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
IlyasMoutawwakil pushed a commit that referenced this pull request Jun 1, 2026
…oftmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes #45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was #45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.
pull Bot pushed a commit to itsbrex/transformers that referenced this pull request Jun 2, 2026
* init

* style

* full support

* support EP better using offsets !

* comments

* get rid of neutralize_ep_sentinels

* remove deepgemm stuff

* fix

* prefix

* move

* fix

* remove comment

* fix unintilized outputs leaking

* revert unnecessary changes

* more unnecessary changes

* revert downcast

* keep it simple

* guard deepgemm cuda version

* fix style

* update

* add deepgemm testing

* moe sentinel support

* fix

* compilable sonicmoe

* mega moe kernel support attempt

* use package for now

* skip ep router and experts pre/post processing

* simpler

* fix

Co-authored-by: Copilot <copilot@github.com>

* fix

* fix

* dtensor support

* more dtensor

* simpler

* remove comment

* revert

* bc order

* revert extra indent

* revert unnecessary change

* update

* less defensive

* allow all kernels

* alow all kernels

* hub only

* fix

* fix

* test

* test

* sync

* check nvcc

* probe

* fix

* test psum

* test

* test

* probe

* fix

* test

* nan issue

* repro

* repro

* fix

* simplifications

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* empty

* simplify

* test deepseek

* dsv4 only

* download dsv4

* fix test

* push

* test

* fix

* fix ep plan

* fix attempt

* debug

* attempt

* debug

* fixes in modeling

* more modeling changes

* more modeling changes

* initial megamoe works but wrong output, deepgemm fully functional

* mega moe works !

* simplification

* comments

* fix merge

* fix rank divergence

* use _keep_in_fp32_modules

* simplify quantizer

* introduce indexerscorer

* remove testing file

* style

* weight rename for scorer

* style

* address review comments

* style

* align with laguna

* stale comments and styling

* use grouped finegrained fp8 for grouped linear

Co-authored-by: sywangyi yi.a.wang@intel.com

* comments and docs

* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (huggingface#45930)"

This reverts commit ecc7e32.

* fix quantizer and use upstream deepgemm

* remove force al kernels

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes huggingface#45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was huggingface#45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* always floats scal inv with triton

* minimal changes i quantizer

* force stable abi build for now

* support transposed

* fix yarn

* unnecessary change

* add flash base test and fix the incorrect and crash issue during enab… (huggingface#46076)

* fix incorrect output in tests/models/deepseek_v4/test_modeling_deepseek_v4.py::DeepseekV4IntegrationTest::test_v4_flash_fp8_generation and add test for flash-base

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* update

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* merge

* better errors across deepgemm

* more better errors for deepgemm

* ep tests

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* custom ep/tp plan for megamoe

* process megamoe after weight loading

* fix megamoe process

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

* simplify after merge

* review comments

* revert unncessary

* avoid name contraction

* fixes

* dynamic tp/ep plan swap

* fix deepgemm single error and device assertion docs

* properly support bias in grouped linear

* simplify

* fix dist error handling and min cuda compatbility

* fix least cuda compat

* get alignment from deepgemm and cache it

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Arthur Zucker <arthur.zucker@gmail.com>
Co-authored-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
khushali9 pushed a commit to khushali9/transformers that referenced this pull request Jun 8, 2026
* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (huggingface#45930)"

This reverts commit ecc7e32.

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes huggingface#45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was huggingface#45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
khushali9 pushed a commit to khushali9/transformers that referenced this pull request Jun 8, 2026
* init

* style

* full support

* support EP better using offsets !

* comments

* get rid of neutralize_ep_sentinels

* remove deepgemm stuff

* fix

* prefix

* move

* fix

* remove comment

* fix unintilized outputs leaking

* revert unnecessary changes

* more unnecessary changes

* revert downcast

* keep it simple

* guard deepgemm cuda version

* fix style

* update

* add deepgemm testing

* moe sentinel support

* fix

* compilable sonicmoe

* mega moe kernel support attempt

* use package for now

* skip ep router and experts pre/post processing

* simpler

* fix

Co-authored-by: Copilot <copilot@github.com>

* fix

* fix

* dtensor support

* more dtensor

* simpler

* remove comment

* revert

* bc order

* revert extra indent

* revert unnecessary change

* update

* less defensive

* allow all kernels

* alow all kernels

* hub only

* fix

* fix

* test

* test

* sync

* check nvcc

* probe

* fix

* test psum

* test

* test

* probe

* fix

* test

* nan issue

* repro

* repro

* fix

* simplifications

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* empty

* simplify

* test deepseek

* dsv4 only

* download dsv4

* fix test

* push

* test

* fix

* fix ep plan

* fix attempt

* debug

* attempt

* debug

* fixes in modeling

* more modeling changes

* more modeling changes

* initial megamoe works but wrong output, deepgemm fully functional

* mega moe works !

* simplification

* comments

* fix merge

* fix rank divergence

* use _keep_in_fp32_modules

* simplify quantizer

* introduce indexerscorer

* remove testing file

* style

* weight rename for scorer

* style

* address review comments

* style

* align with laguna

* stale comments and styling

* use grouped finegrained fp8 for grouped linear

Co-authored-by: sywangyi yi.a.wang@intel.com

* comments and docs

* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (huggingface#45930)"

This reverts commit ecc7e32.

* fix quantizer and use upstream deepgemm

* remove force al kernels

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes huggingface#45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was huggingface#45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* always floats scal inv with triton

* minimal changes i quantizer

* force stable abi build for now

* support transposed

* fix yarn

* unnecessary change

* add flash base test and fix the incorrect and crash issue during enab… (huggingface#46076)

* fix incorrect output in tests/models/deepseek_v4/test_modeling_deepseek_v4.py::DeepseekV4IntegrationTest::test_v4_flash_fp8_generation and add test for flash-base

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* update

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* merge

* better errors across deepgemm

* more better errors for deepgemm

* ep tests

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* custom ep/tp plan for megamoe

* process megamoe after weight loading

* fix megamoe process

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

* simplify after merge

* review comments

* revert unncessary

* avoid name contraction

* fixes

* dynamic tp/ep plan swap

* fix deepgemm single error and device assertion docs

* properly support bias in grouped linear

* simplify

* fix dist error handling and min cuda compatbility

* fix least cuda compat

* get alignment from deepgemm and cache it

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Arthur Zucker <arthur.zucker@gmail.com>
Co-authored-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qgallouedec
qgallouedec deleted the fix-weightconverter-leaf-pattern-anchor branch June 11, 2026 13:22
stevhliu pushed a commit to stevhliu/transformers that referenced this pull request Jul 30, 2026
* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (huggingface#45930)"

This reverts commit ecc7e32.

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes huggingface#45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was huggingface#45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
stevhliu pushed a commit to stevhliu/transformers that referenced this pull request Jul 30, 2026
* init

* style

* full support

* support EP better using offsets !

* comments

* get rid of neutralize_ep_sentinels

* remove deepgemm stuff

* fix

* prefix

* move

* fix

* remove comment

* fix unintilized outputs leaking

* revert unnecessary changes

* more unnecessary changes

* revert downcast

* keep it simple

* guard deepgemm cuda version

* fix style

* update

* add deepgemm testing

* moe sentinel support

* fix

* compilable sonicmoe

* mega moe kernel support attempt

* use package for now

* skip ep router and experts pre/post processing

* simpler

* fix

Co-authored-by: Copilot <copilot@github.com>

* fix

* fix

* dtensor support

* more dtensor

* simpler

* remove comment

* revert

* bc order

* revert extra indent

* revert unnecessary change

* update

* less defensive

* allow all kernels

* alow all kernels

* hub only

* fix

* fix

* test

* test

* sync

* check nvcc

* probe

* fix

* test psum

* test

* test

* probe

* fix

* test

* nan issue

* repro

* repro

* fix

* simplifications

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* empty

* simplify

* test deepseek

* dsv4 only

* download dsv4

* fix test

* push

* test

* fix

* fix ep plan

* fix attempt

* debug

* attempt

* debug

* fixes in modeling

* more modeling changes

* more modeling changes

* initial megamoe works but wrong output, deepgemm fully functional

* mega moe works !

* simplification

* comments

* fix merge

* fix rank divergence

* use _keep_in_fp32_modules

* simplify quantizer

* introduce indexerscorer

* remove testing file

* style

* weight rename for scorer

* style

* address review comments

* style

* align with laguna

* stale comments and styling

* use grouped finegrained fp8 for grouped linear

Co-authored-by: sywangyi yi.a.wang@intel.com

* comments and docs

* Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale companions (huggingface#45930)"

This reverts commit ecc7e32.

* fix quantizer and use upstream deepgemm

* remove force al kernels

* [deepseek_v4] fix FP8 save-side substring match + fp32 gate through softmax

* core_model_loading: WeightConverter.reverse_transform now appends a
  (?=\.|$) token-boundary lookahead to each reversed source so they can't
  substring-match longer sibling tokens. Re-fixes huggingface#45794 (the FP8Experts
  scale companion `mlp.experts.gate_up_proj_scale_inv` was being routed
  into the weight-only [Chunk, SplitModulelist] ops on save) without
  needing `$` on every model-specific converter — that was huggingface#45930's
  approach and broke load via `process_source_pattern`.
* Add `ConversionOps.supports_round_trip` opt-in flag; the on-the-fly
  `quantization_operation` check in reverse_transform now uses it
  instead of a blanket bail-out. Flagged the ops with audited reverse
  pairs (Chunk/Concatenate, MergeModulelist/SplitModulelist, Transpose,
  Conv3d↔Linear, Ernie pair, _IdentityOp, Fp8Quantize/Fp8Dequantize).
* deepseek_v4 compressors (HCA / Indexer / CSA): drop the trailing
  `.to(chunk_gate.dtype)` so the gate stays fp32 from the
  `+ position_bias` through the softmax — matches the reference
  Compressor.forward which upcasts x to fp32 at entry.
* deepseek_v4 config: only set `attention_factor=1.0` when the compress
  group resolves to `rope_type="yarn"`. Suppresses the noisy
  "Unrecognized keys in rope_parameters for rope_type=default" warning
  on the second post_init pass (where yarn params have already been
  consumed).
* Refresh slow integration test expectations to match the fp32-gate
  output.

Verified on the published DeepSeek-V4-Flash checkpoint:
RUN_SLOW=1 pytest tests/models/deepseek_v4 -k Integration  -> 2 passed.

* always floats scal inv with triton

* minimal changes i quantizer

* force stable abi build for now

* support transposed

* fix yarn

* unnecessary change

* add flash base test and fix the incorrect and crash issue during enab… (huggingface#46076)

* fix incorrect output in tests/models/deepseek_v4/test_modeling_deepseek_v4.py::DeepseekV4IntegrationTest::test_v4_flash_fp8_generation and add test for flash-base

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* update

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>

* merge

* better errors across deepgemm

* more better errors for deepgemm

* ep tests

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* scope supports_round_trip to quantization ops only

Drop the flag from the regular shape ops (Chunk, Concatenate, MergeModulelist,
SplitModulelist, Transpose, Conv3d↔Linear, _IdentityOp, the Ernie pair) — those
reverse themselves via their own `reverse_op` property, no flag needed. The
flag only gates `WeightConverter.reverse_transform`'s check on the converter's
`quantization_operation`, so today it's just Fp8Quantize / Fp8Dequantize. Other
quant backends (bnb, torchao, eetq, mxfp4, quanto, ...) stay opt-out until
their round-trip is audited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>

* Update src/transformers/core_model_loading.py

* style: ruff format

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* custom ep/tp plan for megamoe

* process megamoe after weight loading

* fix megamoe process

* up

* the actual fix???

* up

* nit comment for futur

* style: drop unused exception variable in Fp8Dequantize._dequantize_one

* up

* style: apply make fix-repo docstring formatting

* simplify after merge

* review comments

* revert unncessary

* avoid name contraction

* fixes

* dynamic tp/ep plan swap

* fix deepgemm single error and device assertion docs

* properly support bias in grouped linear

* simplify

* fix dist error handling and min cuda compatbility

* fix least cuda compat

* get alignment from deepgemm and cache it

---------

Signed-off-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Arthur Zucker <arthur.zucker@gmail.com>
Co-authored-by: Wang, Yi <yi.a.wang@intel.com>
Co-authored-by: Arthur <48595927+ArthurZucker@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants