-
Notifications
You must be signed in to change notification settings - Fork 129
Cherry-pick: Updated fix regression in Mistral-Large-3-675B (#1304) for v0.19.0 #1374
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
ebc1f73
b91f982
9fe229b
d117ae3
8a26348
4654581
cdcb48d
61ae8c6
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 | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,8 @@ | |||||||||||||||||||||||||||||||
| from unittest.mock import MagicMock | ||||||||||||||||||||||||||||||||
| from vllm.model_executor.layers.quantization.compressed_tensors.compressed_tensors import CompressedTensorsConfig | ||||||||||||||||||||||||||||||||
| from vllm_gaudi.ops.hpu_compressed_tensors import (HPUCompressedTensorsLinearMethod, HPUCompressedTensorsW8A8Fp8, | ||||||||||||||||||||||||||||||||
| HPUCompressedTensorsWNA16, HPUCompressedTensorsWNA16MoEMethod) | ||||||||||||||||||||||||||||||||
| HPUCompressedTensorsWNA16, HPUCompressedTensorsWNA16MoEMethod, | ||||||||||||||||||||||||||||||||
| HPUCompressedTensorsW8A8Fp8MoEMethod) | ||||||||||||||||||||||||||||||||
| from vllm_gaudi.utils import HPUCompileConfig | ||||||||||||||||||||||||||||||||
| from vllm.forward_context import override_forward_context | ||||||||||||||||||||||||||||||||
| from safetensors import safe_open | ||||||||||||||||||||||||||||||||
|
|
@@ -392,3 +393,173 @@ def test_compressed_tensors_wna16_moe_method(default_vllm_config: None, dist_ini | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Check correctness | ||||||||||||||||||||||||||||||||
| torch.testing.assert_close(ref_output, out, atol=1e-4, rtol=1e-4) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def test_compressed_tensors_linear_method_w8a8fp8_block(default_vllm_config: None, dist_init): | ||||||||||||||||||||||||||||||||
| """weight per-block, activation dynamic per-group | ||||||||||||||||||||||||||||||||
| Config based on mistralai/Mistral-Large-3-675B-Instruct-2512 params.json | ||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||
| block_structure = [128, 128] | ||||||||||||||||||||||||||||||||
| config = { | ||||||||||||||||||||||||||||||||
| 'config_groups': { | ||||||||||||||||||||||||||||||||
| 'FP8_BLOCK': { | ||||||||||||||||||||||||||||||||
| 'format': 'float-quantized', | ||||||||||||||||||||||||||||||||
| 'input_activations': { | ||||||||||||||||||||||||||||||||
| 'actorder': None, | ||||||||||||||||||||||||||||||||
| 'block_structure': None, | ||||||||||||||||||||||||||||||||
| 'dynamic': True, | ||||||||||||||||||||||||||||||||
| 'group_size': 128, | ||||||||||||||||||||||||||||||||
| 'num_bits': 8, | ||||||||||||||||||||||||||||||||
| 'observer': None, | ||||||||||||||||||||||||||||||||
| 'observer_kwargs': {}, | ||||||||||||||||||||||||||||||||
| 'strategy': 'group', | ||||||||||||||||||||||||||||||||
| 'symmetric': True, | ||||||||||||||||||||||||||||||||
| 'type': 'float' | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| 'output_activations': None, | ||||||||||||||||||||||||||||||||
| 'targets': ['Linear'], | ||||||||||||||||||||||||||||||||
| 'weights': { | ||||||||||||||||||||||||||||||||
| 'actorder': None, | ||||||||||||||||||||||||||||||||
| 'block_structure': block_structure, | ||||||||||||||||||||||||||||||||
| 'dynamic': False, | ||||||||||||||||||||||||||||||||
| 'group_size': None, | ||||||||||||||||||||||||||||||||
| 'num_bits': 8, | ||||||||||||||||||||||||||||||||
| 'observer': 'static_minmax', | ||||||||||||||||||||||||||||||||
| 'observer_kwargs': {}, | ||||||||||||||||||||||||||||||||
| 'strategy': 'block', | ||||||||||||||||||||||||||||||||
| 'symmetric': True, | ||||||||||||||||||||||||||||||||
| 'type': 'float' | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| 'format': 'float-quantized', | ||||||||||||||||||||||||||||||||
| 'global_compression_ratio': None, | ||||||||||||||||||||||||||||||||
| 'ignore': [], | ||||||||||||||||||||||||||||||||
| 'kv_cache_scheme': None, | ||||||||||||||||||||||||||||||||
| 'quant_method': 'compressed-tensors', | ||||||||||||||||||||||||||||||||
| 'quantization_status': 'compressed' | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| oot_quant_config = CompressedTensorsConfig.from_config(config) | ||||||||||||||||||||||||||||||||
| input_size = 256 | ||||||||||||||||||||||||||||||||
| output_size = 256 | ||||||||||||||||||||||||||||||||
| block_n, block_k = block_structure | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| oot_op = create_row_parallel_linear(input_size=input_size, output_size=output_size, | ||||||||||||||||||||||||||||||||
| quant_config=oot_quant_config).to("hpu") | ||||||||||||||||||||||||||||||||
| assert isinstance(oot_op.quant_method, HPUCompressedTensorsLinearMethod) | ||||||||||||||||||||||||||||||||
| assert isinstance(oot_op.scheme, HPUCompressedTensorsW8A8Fp8) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Create synthetic FP8 block-quantized weights | ||||||||||||||||||||||||||||||||
| weight_fp32 = torch.randn(output_size, input_size, dtype=torch.bfloat16, device="hpu") | ||||||||||||||||||||||||||||||||
| weight_fp8 = weight_fp32.to(torch.float8_e4m3fn) | ||||||||||||||||||||||||||||||||
| scale_rows = (output_size + block_n - 1) // block_n | ||||||||||||||||||||||||||||||||
| scale_cols = (input_size + block_k - 1) // block_k | ||||||||||||||||||||||||||||||||
| weight_scale = torch.ones(scale_rows, scale_cols, dtype=torch.float32, device="hpu") | ||||||||||||||||||||||||||||||||
| oot_op.weight.data.copy_(weight_fp8) | ||||||||||||||||||||||||||||||||
| oot_op.weight_scale.data.copy_(weight_scale) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| oot_op.quant_method.process_weights_after_loading(oot_op) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Verify blockwise post-processing created the expected attributes | ||||||||||||||||||||||||||||||||
| assert hasattr(oot_op, "weight_scale_inv"), "weight_scale_inv should be created for block strategy" | ||||||||||||||||||||||||||||||||
| assert not hasattr(oot_op, "weight_scale"), "weight_scale should be removed after aliasing" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Execute layer with synthetic input | ||||||||||||||||||||||||||||||||
| x = torch.randn(1, 4, input_size, dtype=torch.bfloat16, device="hpu") | ||||||||||||||||||||||||||||||||
| out = oot_op.scheme.apply_weights(oot_op, x) | ||||||||||||||||||||||||||||||||
| assert out.shape == (1, 4, output_size) | ||||||||||||||||||||||||||||||||
| assert out.dtype == torch.bfloat16 | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+467
to
+473
|
||||||||||||||||||||||||||||||||
| # Execute layer with synthetic input | |
| x = torch.randn(1, 4, input_size, dtype=torch.bfloat16, device="hpu") | |
| out = oot_op.scheme.apply_weights(oot_op, x) | |
| assert out.shape == (1, 4, output_size) | |
| assert out.dtype == torch.bfloat16 | |
| # Execute layer with deterministic input and validate numerical correctness | |
| # against a BF16 reference computed from the dequantized FP8 weight. | |
| x = torch.ones(1, 4, input_size, dtype=torch.bfloat16, device="hpu") | |
| out = oot_op.scheme.apply_weights(oot_op, x) | |
| assert out.shape == (1, 4, output_size) | |
| assert out.dtype == torch.bfloat16 | |
| ref_weight = weight_fp8.to(torch.bfloat16) | |
| ref_out = torch.matmul(x, ref_weight.transpose(0, 1)) | |
| assert torch.allclose(out, ref_out, atol=1e-2, rtol=1e-2) |
Copilot
AI
Apr 17, 2026
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.
This new block-quantized MoE test currently verifies only output shape and dtype. To better cover the regression being fixed, consider adding a correctness assertion (or at least a stronger sanity check like finite outputs) against a reference implementation for the same weights/scales.
| assert out.dtype == torch.bfloat16 | |
| assert out.dtype == torch.bfloat16 | |
| assert torch.isfinite( | |
| out).all(), "block-quantized MoE output should not contain NaN or Inf values" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |||||||||||||||||||||
| from vllm.model_executor.custom_op import CustomOp | ||||||||||||||||||||||
| from vllm.model_executor.layers.linear import WEIGHT_LOADER_V2_SUPPORTED | ||||||||||||||||||||||
| from vllm.model_executor.layers.fused_moe.layer import (FusedMoE, FusedMoEConfig) | ||||||||||||||||||||||
| from vllm.model_executor.layers.fused_moe.config import FusedMoEQuantConfig | ||||||||||||||||||||||
| from compressed_tensors.quantization import (QuantizationArgs, QuantizationStrategy) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| from vllm.model_executor.layers.quantization.utils.w8a8_utils import convert_to_channelwise, all_close_1d | ||||||||||||||||||||||
|
|
@@ -54,6 +55,24 @@ | |||||||||||||||||||||
| SUPPORTED_STRATEGIES = [QuantizationStrategy.CHANNEL, QuantizationStrategy.TENSOR, QuantizationStrategy.BLOCK] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _hpu_weight_scale_alias(layer: torch.nn.Module, scale_name: str, hpu_scale_name: str) -> None: | ||||||||||||||||||||||
| """Rename weight scale name to convention expected by HPU ops | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| For example, for block quantization, HPU ops expect `weight_scale` to be named `weight_scale_inv`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| This preserves compatibility across checkpoints/codepaths that use either | ||||||||||||||||||||||
| naming convention. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| if hasattr(layer, hpu_scale_name) or not hasattr(layer, scale_name): | ||||||||||||||||||||||
| return | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Rename weight_scale to convention expected by HPU ops | ||||||||||||||||||||||
| scale = getattr(layer, scale_name) | ||||||||||||||||||||||
| scale = scale.data if isinstance(scale, torch.nn.Parameter) else scale | ||||||||||||||||||||||
| layer.register_parameter(hpu_scale_name, torch.nn.Parameter(scale, requires_grad=False)) | ||||||||||||||||||||||
|
Comment on lines
+71
to
+72
|
||||||||||||||||||||||
| scale = scale.data if isinstance(scale, torch.nn.Parameter) else scale | |
| layer.register_parameter(hpu_scale_name, torch.nn.Parameter(scale, requires_grad=False)) | |
| if isinstance(scale, torch.nn.Parameter): | |
| layer.register_parameter(hpu_scale_name, scale) | |
| else: | |
| aliased_scale = scale.detach() if isinstance(scale, torch.Tensor) else scale | |
| layer.register_parameter( | |
| hpu_scale_name, | |
| torch.nn.Parameter(aliased_scale, requires_grad=False), | |
| ) |
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.
In this test,
weight_fp32is created withdtype=torch.bfloat16(and then cast to FP8). Renaming the variable (or adjusting the dtype) would avoid confusion about what precision the tensor actually represents.