From d2758f8c5720627d85310a69d08dd6ea8c648c53 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:15:33 +0000 Subject: [PATCH 1/7] Initial plan From f8b62fc4be87e4a1f5c434568d984fc75019d48c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:24:35 +0000 Subject: [PATCH 2/7] Fix ignore_layers for FP8 models by checking INNER_SUPPORTED_LAYER_TYPES Co-authored-by: yiliu30 <106061964+yiliu30@users.noreply.github.com> --- auto_round/compressors/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_round/compressors/utils.py b/auto_round/compressors/utils.py index db95d9547..1dbaf4038 100644 --- a/auto_round/compressors/utils.py +++ b/auto_round/compressors/utils.py @@ -864,14 +864,14 @@ def get_fp_layer_names(model: torch.nn.Module, ignore_layers: str): list: A list of layer names that match the specified FP layers or are subcomponents of those layers. """ - from auto_round.utils import SUPPORTED_LAYER_TYPES + from auto_round.utils import INNER_SUPPORTED_LAYER_TYPES, SUPPORTED_LAYER_TYPES if not ignore_layers: return [] ignore_layers = ignore_layers.replace(" ", "").split(",") all_layer_names = [] for n, m in model.named_modules(): - if type(m) in SUPPORTED_LAYER_TYPES: + if type(m) in SUPPORTED_LAYER_TYPES or m.__class__.__name__ in INNER_SUPPORTED_LAYER_TYPES: all_layer_names.append(n) not_to_quantized_layers = [] From 9f0eaf89a2a0a363491818b96023a711c4e6fbb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:25:41 +0000 Subject: [PATCH 3/7] Add test for ignore_layers with FP8 models Co-authored-by: yiliu30 <106061964+yiliu30@users.noreply.github.com> --- test/test_cuda/advanced/test_fp8_input.py | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/test_cuda/advanced/test_fp8_input.py b/test/test_cuda/advanced/test_fp8_input.py index ec3dc6bf3..0063afa13 100644 --- a/test/test_cuda/advanced/test_fp8_input.py +++ b/test/test_cuda/advanced/test_fp8_input.py @@ -141,3 +141,31 @@ def test_diff_datatype(self): ar = AutoRound(model_name, iters=iters, scheme=scheme) ar.quantize_and_save(output_dir=self.save_dir) shutil.rmtree(self.save_dir, ignore_errors=True) + + def test_ignore_layers_fp8(self): + """Test that ignore_layers works correctly with FP8 models.""" + from auto_round.compressors.utils import get_fp_layer_names + + model, tokenizer = self.tiny_fp8_model() + + # Test that get_fp_layer_names can find FP8Linear layers + # Using "mlp" as the ignore pattern which should match mlp layers in the model + layer_names = get_fp_layer_names(model, "mlp") + print(f"Found {len(layer_names)} layers matching 'mlp' pattern") + + # Verify that some layers were found + assert len(layer_names) > 0, "Should find layers matching 'mlp' pattern in FP8 model" + + # Now test with AutoRound using ignore_layers + ar = AutoRound( + model=model, + tokenizer=tokenizer, + iters=0, + ignore_layers="mlp" + ) + ar.quantize_and_save(output_dir=self.save_dir) + + # Verify the model was saved successfully + assert os.path.exists(self.save_dir), "Model should be saved" + + shutil.rmtree(self.save_dir, ignore_errors=True) From 97abed098a927c445e40c136d03e4f84462d22bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:26:57 +0000 Subject: [PATCH 4/7] Add comprehensive unit tests for get_fp_layer_names function Co-authored-by: yiliu30 <106061964+yiliu30@users.noreply.github.com> --- test/test_cpu/utils/test_compressor_utils.py | 107 +++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 test/test_cpu/utils/test_compressor_utils.py diff --git a/test/test_cpu/utils/test_compressor_utils.py b/test/test_cpu/utils/test_compressor_utils.py new file mode 100644 index 000000000..fefab28b8 --- /dev/null +++ b/test/test_cpu/utils/test_compressor_utils.py @@ -0,0 +1,107 @@ +""" +Unit tests for auto_round.compressors.utils module. +""" +import torch +import pytest + +from auto_round.compressors.utils import get_fp_layer_names +from auto_round.utils import INNER_SUPPORTED_LAYER_TYPES + + +class TestGetFpLayerNames: + """Test suite for get_fp_layer_names function.""" + + def test_regular_linear_layers(self): + """Test with regular Linear layers.""" + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layer1 = torch.nn.Linear(10, 10) + self.layer2 = torch.nn.Linear(10, 10) + self.mlp = torch.nn.Sequential( + torch.nn.Linear(10, 10), + torch.nn.Linear(10, 10) + ) + + model = MockModel() + + # Test finding specific layer + result = get_fp_layer_names(model, 'layer1') + assert 'layer1' in result, "Should find layer1" + + # Test finding layers with pattern + result = get_fp_layer_names(model, 'mlp') + assert len(result) == 2, "Should find 2 layers in mlp" + assert 'mlp.0' in result and 'mlp.1' in result + + def test_fp8linear_layers(self): + """Test with FP8Linear layers (mocked by changing class name).""" + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layer1 = torch.nn.Linear(10, 10) + # Mock FP8Linear by changing class name + self.layer2 = torch.nn.Linear(10, 10) + self.layer2.__class__.__name__ = 'FP8Linear' + + self.mlp = torch.nn.Sequential() + linear1 = torch.nn.Linear(10, 10) + self.mlp.add_module('0', linear1) + linear2 = torch.nn.Linear(10, 10) + linear2.__class__.__name__ = 'FP8Linear' + self.mlp.add_module('1', linear2) + + model = MockModel() + + # Test finding FP8Linear layer + result = get_fp_layer_names(model, 'layer2') + assert 'layer2' in result, "Should find FP8Linear layer (layer2)" + + # Test finding mixed Linear and FP8Linear in mlp + result = get_fp_layer_names(model, 'mlp') + assert len(result) == 2, "Should find 2 layers in mlp (both Linear and FP8Linear)" + assert 'mlp.0' in result, "Should find regular Linear in mlp" + assert 'mlp.1' in result, "Should find FP8Linear in mlp" + + def test_empty_ignore_layers(self): + """Test with empty ignore_layers string.""" + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layer1 = torch.nn.Linear(10, 10) + + model = MockModel() + result = get_fp_layer_names(model, '') + assert len(result) == 0, "Empty ignore_layers should return empty list" + + def test_multiple_ignore_patterns(self): + """Test with multiple ignore patterns.""" + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layer1 = torch.nn.Linear(10, 10) + self.layer2 = torch.nn.Linear(10, 10) + self.layer3 = torch.nn.Linear(10, 10) + + model = MockModel() + result = get_fp_layer_names(model, 'layer1,layer3') + assert 'layer1' in result, "Should find layer1" + assert 'layer3' in result, "Should find layer3" + assert 'layer2' not in result, "Should not find layer2" + + def test_pattern_with_digits(self): + """Test pattern matching with digits (special case in the code).""" + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layers = torch.nn.ModuleList([ + torch.nn.Linear(10, 10), + torch.nn.Linear(10, 10), + torch.nn.Linear(10, 10) + ]) + + model = MockModel() + # Pattern ending with digit should get a dot appended for matching + result = get_fp_layer_names(model, 'layers.0') + # Should match 'layers.0' + assert 'layers.0' in result, "Should match layers.0" From 4f77d6d293d2243cc54b6405054f584ced0e8bed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 04:29:10 +0000 Subject: [PATCH 5/7] Address code review feedback: improve test mocking and remove debug print Co-authored-by: yiliu30 <106061964+yiliu30@users.noreply.github.com> --- test/test_cpu/utils/test_compressor_utils.py | 16 ++++++++++------ test/test_cuda/advanced/test_fp8_input.py | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/test/test_cpu/utils/test_compressor_utils.py b/test/test_cpu/utils/test_compressor_utils.py index fefab28b8..95fbf2bf6 100644 --- a/test/test_cpu/utils/test_compressor_utils.py +++ b/test/test_cpu/utils/test_compressor_utils.py @@ -35,20 +35,24 @@ def __init__(self): assert 'mlp.0' in result and 'mlp.1' in result def test_fp8linear_layers(self): - """Test with FP8Linear layers (mocked by changing class name).""" + """Test with FP8Linear layers (mocked by creating a proper class).""" + # Create a proper mock FP8Linear class + class FP8Linear(torch.nn.Linear): + """Mock FP8Linear class for testing.""" + def __init__(self, in_features, out_features): + super().__init__(in_features, out_features) + class MockModel(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(10, 10) - # Mock FP8Linear by changing class name - self.layer2 = torch.nn.Linear(10, 10) - self.layer2.__class__.__name__ = 'FP8Linear' + # Use proper FP8Linear mock + self.layer2 = FP8Linear(10, 10) self.mlp = torch.nn.Sequential() linear1 = torch.nn.Linear(10, 10) self.mlp.add_module('0', linear1) - linear2 = torch.nn.Linear(10, 10) - linear2.__class__.__name__ = 'FP8Linear' + linear2 = FP8Linear(10, 10) self.mlp.add_module('1', linear2) model = MockModel() diff --git a/test/test_cuda/advanced/test_fp8_input.py b/test/test_cuda/advanced/test_fp8_input.py index 0063afa13..a5fc8a4bd 100644 --- a/test/test_cuda/advanced/test_fp8_input.py +++ b/test/test_cuda/advanced/test_fp8_input.py @@ -151,7 +151,6 @@ def test_ignore_layers_fp8(self): # Test that get_fp_layer_names can find FP8Linear layers # Using "mlp" as the ignore pattern which should match mlp layers in the model layer_names = get_fp_layer_names(model, "mlp") - print(f"Found {len(layer_names)} layers matching 'mlp' pattern") # Verify that some layers were found assert len(layer_names) > 0, "Should find layers matching 'mlp' pattern in FP8 model" From 17fbf3ae4ef3887ce8413a417d253788564dc440 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 15 Jan 2026 05:03:06 +0000 Subject: [PATCH 6/7] Address review feedback: remove unused import and add None test Co-authored-by: yiliu30 <106061964+yiliu30@users.noreply.github.com> --- test/test_cpu/utils/test_compressor_utils.py | 101 +++++++++++-------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/test/test_cpu/utils/test_compressor_utils.py b/test/test_cpu/utils/test_compressor_utils.py index 95fbf2bf6..1aa77f67c 100644 --- a/test/test_cpu/utils/test_compressor_utils.py +++ b/test/test_cpu/utils/test_compressor_utils.py @@ -1,11 +1,11 @@ """ Unit tests for auto_round.compressors.utils module. """ -import torch + import pytest +import torch from auto_round.compressors.utils import get_fp_layer_names -from auto_round.utils import INNER_SUPPORTED_LAYER_TYPES class TestGetFpLayerNames: @@ -13,99 +13,112 @@ class TestGetFpLayerNames: def test_regular_linear_layers(self): """Test with regular Linear layers.""" + class MockModel(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(10, 10) self.layer2 = torch.nn.Linear(10, 10) - self.mlp = torch.nn.Sequential( - torch.nn.Linear(10, 10), - torch.nn.Linear(10, 10) - ) - + self.mlp = torch.nn.Sequential(torch.nn.Linear(10, 10), torch.nn.Linear(10, 10)) + model = MockModel() - + # Test finding specific layer - result = get_fp_layer_names(model, 'layer1') - assert 'layer1' in result, "Should find layer1" - + result = get_fp_layer_names(model, "layer1") + assert "layer1" in result, "Should find layer1" + # Test finding layers with pattern - result = get_fp_layer_names(model, 'mlp') + result = get_fp_layer_names(model, "mlp") assert len(result) == 2, "Should find 2 layers in mlp" - assert 'mlp.0' in result and 'mlp.1' in result - + assert "mlp.0" in result and "mlp.1" in result + def test_fp8linear_layers(self): """Test with FP8Linear layers (mocked by creating a proper class).""" + # Create a proper mock FP8Linear class class FP8Linear(torch.nn.Linear): """Mock FP8Linear class for testing.""" + def __init__(self, in_features, out_features): super().__init__(in_features, out_features) - + class MockModel(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(10, 10) # Use proper FP8Linear mock self.layer2 = FP8Linear(10, 10) - + self.mlp = torch.nn.Sequential() linear1 = torch.nn.Linear(10, 10) - self.mlp.add_module('0', linear1) + self.mlp.add_module("0", linear1) linear2 = FP8Linear(10, 10) - self.mlp.add_module('1', linear2) - + self.mlp.add_module("1", linear2) + model = MockModel() - + # Test finding FP8Linear layer - result = get_fp_layer_names(model, 'layer2') - assert 'layer2' in result, "Should find FP8Linear layer (layer2)" - + result = get_fp_layer_names(model, "layer2") + assert "layer2" in result, "Should find FP8Linear layer (layer2)" + # Test finding mixed Linear and FP8Linear in mlp - result = get_fp_layer_names(model, 'mlp') + result = get_fp_layer_names(model, "mlp") assert len(result) == 2, "Should find 2 layers in mlp (both Linear and FP8Linear)" - assert 'mlp.0' in result, "Should find regular Linear in mlp" - assert 'mlp.1' in result, "Should find FP8Linear in mlp" - + assert "mlp.0" in result, "Should find regular Linear in mlp" + assert "mlp.1" in result, "Should find FP8Linear in mlp" + def test_empty_ignore_layers(self): """Test with empty ignore_layers string.""" + class MockModel(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(10, 10) - + model = MockModel() - result = get_fp_layer_names(model, '') + result = get_fp_layer_names(model, "") assert len(result) == 0, "Empty ignore_layers should return empty list" - + + def test_none_ignore_layers(self): + """Test with None as ignore_layers input.""" + + class MockModel(torch.nn.Module): + def __init__(self): + super().__init__() + self.layer1 = torch.nn.Linear(10, 10) + + model = MockModel() + result = get_fp_layer_names(model, None) + assert len(result) == 0, "None ignore_layers should return empty list" + def test_multiple_ignore_patterns(self): """Test with multiple ignore patterns.""" + class MockModel(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(10, 10) self.layer2 = torch.nn.Linear(10, 10) self.layer3 = torch.nn.Linear(10, 10) - + model = MockModel() - result = get_fp_layer_names(model, 'layer1,layer3') - assert 'layer1' in result, "Should find layer1" - assert 'layer3' in result, "Should find layer3" - assert 'layer2' not in result, "Should not find layer2" - + result = get_fp_layer_names(model, "layer1,layer3") + assert "layer1" in result, "Should find layer1" + assert "layer3" in result, "Should find layer3" + assert "layer2" not in result, "Should not find layer2" + def test_pattern_with_digits(self): """Test pattern matching with digits (special case in the code).""" + class MockModel(torch.nn.Module): def __init__(self): super().__init__() - self.layers = torch.nn.ModuleList([ - torch.nn.Linear(10, 10), - torch.nn.Linear(10, 10), - torch.nn.Linear(10, 10) - ]) - + self.layers = torch.nn.ModuleList( + [torch.nn.Linear(10, 10), torch.nn.Linear(10, 10), torch.nn.Linear(10, 10)] + ) + model = MockModel() # Pattern ending with digit should get a dot appended for matching - result = get_fp_layer_names(model, 'layers.0') + result = get_fp_layer_names(model, "layers.0") # Should match 'layers.0' - assert 'layers.0' in result, "Should match layers.0" + assert "layers.0" in result, "Should match layers.0" From 3bee2e5c64f036ed89ca4202423bfcd0cc39433f Mon Sep 17 00:00:00 2001 From: yiliu30 Date: Fri, 16 Jan 2026 00:26:59 -0500 Subject: [PATCH 7/7] fix pre-commit Signed-off-by: yiliu30 --- test/test_cuda/advanced/test_fp8_input.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/test/test_cuda/advanced/test_fp8_input.py b/test/test_cuda/advanced/test_fp8_input.py index a5fc8a4bd..a980d40ec 100644 --- a/test/test_cuda/advanced/test_fp8_input.py +++ b/test/test_cuda/advanced/test_fp8_input.py @@ -145,26 +145,21 @@ def test_diff_datatype(self): def test_ignore_layers_fp8(self): """Test that ignore_layers works correctly with FP8 models.""" from auto_round.compressors.utils import get_fp_layer_names - + model, tokenizer = self.tiny_fp8_model() - + # Test that get_fp_layer_names can find FP8Linear layers # Using "mlp" as the ignore pattern which should match mlp layers in the model layer_names = get_fp_layer_names(model, "mlp") - + # Verify that some layers were found assert len(layer_names) > 0, "Should find layers matching 'mlp' pattern in FP8 model" - + # Now test with AutoRound using ignore_layers - ar = AutoRound( - model=model, - tokenizer=tokenizer, - iters=0, - ignore_layers="mlp" - ) + ar = AutoRound(model=model, tokenizer=tokenizer, iters=0, ignore_layers="mlp") ar.quantize_and_save(output_dir=self.save_dir) - + # Verify the model was saved successfully assert os.path.exists(self.save_dir), "Model should be saved" - + shutil.rmtree(self.save_dir, ignore_errors=True)