| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | """Tests for humming's is_layer_skipped handling of compressed-tensors |
| 4 | regex ("re:") ignore entries. |
| 5 | |
| 6 | Regression test: compressed-tensors checkpoints (e.g. Kimi-K2.6) list ignored |
| 7 | layers as regex patterns prefixed with "re:" (e.g. "re:vision_tower.*"). |
| 8 | humming previously substring-matched these literals, so ignored layers were |
| 9 | never skipped and got (incorrectly) quantized -- which then diverged between |
| 10 | the real weight-load path (falls back to unquantized) and the dummy-load path |
| 11 | (stays quantized), breaking any consumer that byte-compares the two. |
| 12 | """ |
| 13 | |
| 14 | import pytest |
| 15 | |
| 16 | from vllm.model_executor.layers.quantization.humming import HummingConfig |
| 17 | |
| 18 | # The real ignore list from Kimi-K2.6's compressed-tensors quantization_config. |
| 19 | K26_IGNORE = [ |
| 20 | "re:.*self_attn.*", |
| 21 | "re:.*shared_experts.*", |
| 22 | r"re:.*mlp\.(gate|up|gate_up|down)_proj.*", |
| 23 | "re:.*lm_head.*", |
| 24 | "re:vision_tower.*", |
| 25 | "re:mm_projector.*", |
| 26 | ] |
| 27 | |
| 28 | |
| 29 | @pytest.mark.parametrize( |
| 30 | "prefix,expected", |
| 31 | [ |
| 32 | # ignored layers (must be skipped -> stay unquantized) |
| 33 | ("vision_tower.encoder.blocks.0.mlp.fc0", True), |
| 34 | ("vision_tower.encoder.blocks.16.wo", True), |
| 35 | ("mm_projector.linear_1", True), |
| 36 | ("language_model.model.layers.0.self_attn.o_proj", True), |
| 37 | ("language_model.model.layers.0.mlp.gate_up_proj", True), |
| 38 | ("language_model.model.layers.0.mlp.down_proj", True), |
| 39 | ("language_model.model.layers.3.mlp.shared_experts.gate_proj", True), |
| 40 | ("model.lm_head", True), |
| 41 | # routed experts are NOT ignored -> must be quantized |
| 42 | ("language_model.model.layers.3.mlp.experts.383.up_proj", False), |
| 43 | ("language_model.model.layers.3.mlp.experts.0.down_proj", False), |
| 44 | ], |
| 45 | ) |
| 46 | def test_is_layer_skipped_regex_ignore(prefix, expected): |
| 47 | cfg = HummingConfig(full_config={"ignore": K26_IGNORE}) |
| 48 | assert cfg.is_layer_skipped({"ignore": K26_IGNORE}, prefix) is expected |
| 49 | |
| 50 | |
| 51 | def test_plain_substring_entries_still_work(): |
| 52 | # bitsandbytes-style modules_to_not_convert use plain substrings. |
| 53 | cfg = HummingConfig() |
| 54 | cfg_dict = {"modules_to_not_convert": ["lm_head", "vision"]} |
| 55 | assert cfg.is_layer_skipped(cfg_dict, "model.vision.encoder.fc") is True |
| 56 | assert cfg.is_layer_skipped(cfg_dict, "model.layers.0.mlp.up_proj") is False |