From 14d098c34c2e5247eca8ea605ca7f629e750e1a2 Mon Sep 17 00:00:00 2001 From: Kyle Sayers Date: Fri, 5 Dec 2025 06:29:09 +0000 Subject: [PATCH 1/3] deprecate Signed-off-by: Kyle Sayers --- src/llmcompressor/utils/helpers.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/llmcompressor/utils/helpers.py b/src/llmcompressor/utils/helpers.py index 0be09bd06..886fccd22 100644 --- a/src/llmcompressor/utils/helpers.py +++ b/src/llmcompressor/utils/helpers.py @@ -24,6 +24,7 @@ import numpy import torch from compressed_tensors.quantization import disable_quantization, enable_quantization +from compressed_tensors.utils import deprecated from loguru import logger from transformers import PreTrainedModel @@ -85,6 +86,7 @@ ############################## +@deprecated() def flatten_iterable(li: Iterable): """ :param li: a possibly nested iterable of items to be flattened @@ -102,6 +104,7 @@ def _flatten_gen(_li): return list(_flatten_gen(li)) +@deprecated() def convert_to_bool(val: Any): """ :param val: the value to be converted to a bool, @@ -116,6 +119,7 @@ def convert_to_bool(val: Any): ) +@deprecated() def validate_str_iterable( val: Union[str, Iterable[str]], error_desc: str = "" ) -> Union[str, Iterable[str]]: @@ -141,6 +145,7 @@ def validate_str_iterable( raise ValueError("unsupported type ({}) given in {}".format(val, error_desc)) +@deprecated() def bucket_iterable( val: Iterable[Any], num_buckets: int = 3, @@ -188,6 +193,7 @@ def bucket_iterable( INTERPOLATION_FUNCS = ["linear", "cubic", "inverse_cubic"] +@deprecated(future_name="torch.lerp") def interpolate( x_cur: float, x0: float, x1: float, y0: Any, y1: Any, inter_func: str = "linear" ) -> Any: @@ -240,6 +246,7 @@ def interpolate( return y_per * (y1 - y0) + y0 +@deprecated(future_name="torch.lerp") def interpolate_list_linear( measurements: List[Tuple[float, float]], x_val: Union[float, List[float]] ) -> List[Tuple[float, float]]: @@ -276,6 +283,7 @@ def interpolate_list_linear( return interpolated +@deprecated(future_name="torch.lerp") def interpolated_integral(measurements: List[Tuple[float, float]]): """ Calculate the interpolated integal for a group of measurements of the form @@ -305,6 +313,7 @@ def interpolated_integral(measurements: List[Tuple[float, float]]): return integral +@deprecated() def clean_path(path: str) -> str: """ :param path: the directory or file path to clean @@ -313,6 +322,7 @@ def clean_path(path: str) -> str: return os.path.abspath(os.path.expanduser(path)) +@deprecated() def create_dirs(path: str): """ :param path: the directory path to try and create @@ -329,6 +339,7 @@ def create_dirs(path: str): raise +@deprecated() def create_parent_dirs(path: str): """ :param path: the file path to try to create the parent directories for @@ -337,6 +348,7 @@ def create_parent_dirs(path: str): create_dirs(parent) +@deprecated() def create_unique_dir(path: str, check_number: int = 0) -> str: """ :param path: the file path to create a unique version of @@ -352,6 +364,7 @@ def create_unique_dir(path: str, check_number: int = 0) -> str: return create_unique_dir(path, check_number + 1) +@deprecated() def path_file_count(path: str, pattern: str = "*") -> int: """ Return the number of files that match the given pattern under the given path @@ -365,6 +378,7 @@ def path_file_count(path: str, pattern: str = "*") -> int: return len(fnmatch.filter(os.listdir(path), pattern)) +@deprecated() def path_file_size(path: str) -> int: """ Return the total size, in bytes, for a path on the file system @@ -402,6 +416,7 @@ def path_file_size(path: str) -> int: return total_size +@deprecated() def is_url(val: str): """ :param val: value to check if it is a url or not @@ -426,6 +441,7 @@ def is_url(val: str): NDARRAY_KEY = "ndarray" +@deprecated() def load_numpy(file_path: str) -> Union[numpy.ndarray, Dict[str, numpy.ndarray]]: """ Load a numpy file into either an ndarray or an OrderedDict representing what @@ -446,6 +462,7 @@ def load_numpy(file_path: str) -> Union[numpy.ndarray, Dict[str, numpy.ndarray]] return array +@deprecated() def save_numpy( array: Union[numpy.ndarray, Dict[str, numpy.ndarray], Iterable[numpy.ndarray]], export_dir: str, @@ -485,6 +502,7 @@ def save_numpy( return export_path +@deprecated() def _fix_loaded_numpy(array) -> Union[numpy.ndarray, Dict[str, numpy.ndarray]]: if not isinstance(array, numpy.ndarray): tmp_arrray = array @@ -495,6 +513,7 @@ def _fix_loaded_numpy(array) -> Union[numpy.ndarray, Dict[str, numpy.ndarray]]: return array +@deprecated() def load_numpy_from_tar( path: str, ) -> List[Union[numpy.ndarray, Dict[str, numpy.ndarray]]]: @@ -519,6 +538,7 @@ def load_numpy_from_tar( return data +@deprecated() def load_numpy_list( data: Union[str, Iterable[Union[str, numpy.ndarray, Dict[str, numpy.ndarray]]]], ) -> List[Union[numpy.ndarray, Dict[str, numpy.ndarray]]]: @@ -550,6 +570,7 @@ def load_numpy_list( return loaded +@deprecated() def load_labeled_data( data: Union[str, Iterable[Union[str, numpy.ndarray, Dict[str, numpy.ndarray]]]], labels: Union[ @@ -628,6 +649,7 @@ def __len__(self): return len(self._items[list(self._items.keys())[0]]) + @deprecated() def append(self, item: Union[numpy.ndarray, Dict[str, numpy.ndarray]]): """ Append a new item into the current batch. @@ -681,6 +703,7 @@ def append(self, item: Union[numpy.ndarray, Dict[str, numpy.ndarray]]): self._items[key].append(val) + @deprecated() def stack(self) -> Dict[str, numpy.ndarray]: """ Stack the current items into a batch along a new, zeroed dimension @@ -695,6 +718,7 @@ def stack(self) -> Dict[str, numpy.ndarray]: return batch_dict +@deprecated() def tensor_export( tensor: Union[numpy.ndarray, Dict[str, numpy.ndarray], Iterable[numpy.ndarray]], export_dir: str, @@ -731,6 +755,7 @@ def tensor_export( return export_path +@deprecated() def tensors_export( tensors: Union[numpy.ndarray, Dict[str, numpy.ndarray], Iterable[numpy.ndarray]], export_dir: str, @@ -762,6 +787,7 @@ def tensors_export( return exported_paths +@deprecated() def _tensors_export_recursive( tensors: Union[numpy.ndarray, Iterable[numpy.ndarray]], export_dir: str, @@ -796,6 +822,7 @@ def _tensors_export_recursive( ) +@deprecated() def _tensors_export_batch( tensors: Union[numpy.ndarray, Dict[str, numpy.ndarray], Iterable[numpy.ndarray]], export_dir: str, @@ -842,6 +869,7 @@ def _tensors_export_batch( ) +@deprecated() def json_to_jsonl(json_file_path: str, overwrite: bool = True): """ Converts a json list file to jsonl file format (used for sharding efficienty) @@ -873,6 +901,7 @@ def json_to_jsonl(json_file_path: str, overwrite: bool = True): jsonl_file.write("\n") # newline +@deprecated() def deprecation_warning(message: str): warnings.simplefilter("always", DeprecationWarning) warnings.warn( @@ -1056,6 +1085,7 @@ def calibration_forward_context(model: torch.nn.Module): yield +@deprecated() @contextlib.contextmanager def patch_attr(base: object, attr: str, value: Any): """ From 0859218e99f6615c449668837a0d442b2c883337 Mon Sep 17 00:00:00 2001 From: Kyle Sayers Date: Fri, 5 Dec 2025 06:34:05 +0000 Subject: [PATCH 2/3] use ct patchattr Signed-off-by: Kyle Sayers --- .../pipelines/independent/pipeline.py | 2 +- .../pipelines/sequential/ast_helpers.py | 2 +- .../sequential/ast_utils/name_analyzer.py | 2 +- .../pipelines/sequential/helpers.py | 3 ++- src/llmcompressor/utils/dev.py | 4 +--- tests/llmcompressor/utils/test_helpers.py | 19 ------------------- 6 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/llmcompressor/pipelines/independent/pipeline.py b/src/llmcompressor/pipelines/independent/pipeline.py index c204e012e..daf7a42bd 100644 --- a/src/llmcompressor/pipelines/independent/pipeline.py +++ b/src/llmcompressor/pipelines/independent/pipeline.py @@ -1,12 +1,12 @@ from typing import TYPE_CHECKING import torch +from compressed_tensors.utils import patch_attr from loguru import logger from torch.utils.data.dataloader import DataLoader from llmcompressor.core import active_session from llmcompressor.pipelines.registry import CalibrationPipeline -from llmcompressor.utils.helpers import patch_attr if TYPE_CHECKING: from llmcompressor.args.dataset_arguments import DatasetArguments diff --git a/src/llmcompressor/pipelines/sequential/ast_helpers.py b/src/llmcompressor/pipelines/sequential/ast_helpers.py index c038529a1..65e8d9c61 100644 --- a/src/llmcompressor/pipelines/sequential/ast_helpers.py +++ b/src/llmcompressor/pipelines/sequential/ast_helpers.py @@ -8,9 +8,9 @@ from typing import List import torch +from compressed_tensors.utils import patch_attr from llmcompressor.pipelines.sequential.ast_utils.auto_wrapper import AutoWrapper -from llmcompressor.utils import patch_attr __all__ = ["autowrap_forwards", "append_autowrap_source_on_fail"] diff --git a/src/llmcompressor/pipelines/sequential/ast_utils/name_analyzer.py b/src/llmcompressor/pipelines/sequential/ast_utils/name_analyzer.py index a9636a96a..134a8bee7 100644 --- a/src/llmcompressor/pipelines/sequential/ast_utils/name_analyzer.py +++ b/src/llmcompressor/pipelines/sequential/ast_utils/name_analyzer.py @@ -2,7 +2,7 @@ import builtins from typing import Set, Tuple -from llmcompressor.utils import patch_attr +from compressed_tensors.utils import patch_attr class NameAnalyzer(ast.NodeVisitor): diff --git a/src/llmcompressor/pipelines/sequential/helpers.py b/src/llmcompressor/pipelines/sequential/helpers.py index e13144689..4a776a7d5 100644 --- a/src/llmcompressor/pipelines/sequential/helpers.py +++ b/src/llmcompressor/pipelines/sequential/helpers.py @@ -10,6 +10,7 @@ from compressed_tensors.utils import ( has_offloaded_params, offloaded_dispatch, + patch_attr, remove_dispatch, ) from compressed_tensors.utils.match import match_targets @@ -24,7 +25,7 @@ from llmcompressor.modifiers import Modifier from llmcompressor.modifiers.utils.hooks import HooksMixin from llmcompressor.pipelines.sequential.transformers_helpers import HFTracer -from llmcompressor.utils.helpers import calibration_forward_context, patch_attr +from llmcompressor.utils.helpers import calibration_forward_context from llmcompressor.utils.pytorch.module import get_no_split_params from .ast_helpers import append_autowrap_source_on_fail, autowrap_forwards diff --git a/src/llmcompressor/utils/dev.py b/src/llmcompressor/utils/dev.py index f0feb6c04..a227ffa06 100644 --- a/src/llmcompressor/utils/dev.py +++ b/src/llmcompressor/utils/dev.py @@ -7,15 +7,13 @@ import torch from accelerate import dispatch_model, infer_auto_device_map from accelerate.utils import get_balanced_memory -from compressed_tensors.utils import remove_dispatch +from compressed_tensors.utils import patch_attr, remove_dispatch from huggingface_hub import snapshot_download from safetensors.torch import save_file from transformers import AutoModelForCausalLM, PreTrainedModel from transformers.modeling_utils import TORCH_INIT_FUNCTIONS from transformers.utils import SAFE_WEIGHTS_INDEX_NAME, WEIGHTS_INDEX_NAME -from llmcompressor.utils.helpers import patch_attr - __all__ = [ "skip_weights_download", "patch_transformers_logger_level", diff --git a/tests/llmcompressor/utils/test_helpers.py b/tests/llmcompressor/utils/test_helpers.py index cb474c1f5..8ae028267 100644 --- a/tests/llmcompressor/utils/test_helpers.py +++ b/tests/llmcompressor/utils/test_helpers.py @@ -18,7 +18,6 @@ flatten_iterable, getattr_chain, interpolate, - patch_attr, validate_str_iterable, ) from llmcompressor.utils.dev import skip_weights_download @@ -165,24 +164,6 @@ class DummyModel(PreTrainedModel): assert model.training -@pytest.mark.unit -def test_patch_attr(): - # patch, original value - obj = SimpleNamespace() - obj.attribute = "original" - with patch_attr(obj, "attribute", "patched"): - assert obj.attribute == "patched" - obj.attribute = "modified" - assert obj.attribute == "original" - - # patch, no original attribute - obj = SimpleNamespace() - with patch_attr(obj, "attribute", "patched"): - assert obj.attribute == "patched" - obj.attribute = "modified" - assert not hasattr(obj, "attribute") - - @requires_gpu @pytest.mark.unit @pytest.mark.parametrize( From 5dda5005bc8b3bd73f4601d798dde3c453b621cc Mon Sep 17 00:00:00 2001 From: Kyle Sayers Date: Fri, 5 Dec 2025 06:36:29 +0000 Subject: [PATCH 3/3] getattr_chain Signed-off-by: Kyle Sayers --- .../modifiers/quantization/calibration.py | 7 ++-- src/llmcompressor/utils/helpers.py | 1 + tests/llmcompressor/utils/test_helpers.py | 35 ------------------- 3 files changed, 6 insertions(+), 37 deletions(-) diff --git a/src/llmcompressor/modifiers/quantization/calibration.py b/src/llmcompressor/modifiers/quantization/calibration.py index da974b25b..9109b8fa3 100644 --- a/src/llmcompressor/modifiers/quantization/calibration.py +++ b/src/llmcompressor/modifiers/quantization/calibration.py @@ -8,12 +8,15 @@ QuantizationStrategy, ) from compressed_tensors.quantization.lifecycle.forward import forward_quantize -from compressed_tensors.utils import align_module_device, update_offload_parameter +from compressed_tensors.utils import ( + align_module_device, + getattr_chain, + update_offload_parameter, +) from loguru import logger from torch.nn import Module from llmcompressor.observers import Observer -from llmcompressor.utils.helpers import getattr_chain __all__ = [ "initialize_observer", diff --git a/src/llmcompressor/utils/helpers.py b/src/llmcompressor/utils/helpers.py index 886fccd22..5f6a58820 100644 --- a/src/llmcompressor/utils/helpers.py +++ b/src/llmcompressor/utils/helpers.py @@ -972,6 +972,7 @@ def import_from_path(path: str) -> str: raise AttributeError(f"Cannot find {class_name} in {_path}") +@deprecated() def getattr_chain(obj: Any, chain_str: str, *args, **kwargs) -> Any: """ Chain multiple getattr calls, separated by `.` diff --git a/tests/llmcompressor/utils/test_helpers.py b/tests/llmcompressor/utils/test_helpers.py index 8ae028267..996b3f43b 100644 --- a/tests/llmcompressor/utils/test_helpers.py +++ b/tests/llmcompressor/utils/test_helpers.py @@ -1,5 +1,3 @@ -from types import SimpleNamespace - import pytest import torch from transformers import ( @@ -16,7 +14,6 @@ convert_to_bool, disable_cache, flatten_iterable, - getattr_chain, interpolate, validate_str_iterable, ) @@ -106,38 +103,6 @@ def test_interpolate(x_cur, x0, x1, y0, y1, inter_func, out): assert abs(out - interpolated) < 0.01 -@pytest.mark.unit -def test_getattr_chain(): - base = SimpleNamespace() - base.a = None - base.b = SimpleNamespace() - base.b.c = "value" - base.b.d = None - - # test base cases - assert getattr_chain(base, "", None) is None - with pytest.raises(AttributeError): - getattr_chain(base, "") - - # test single layer - assert getattr_chain(base, "a") is None - assert getattr_chain(base, "a", "default") is None - assert getattr_chain(base, "b") == base.b - - assert getattr_chain(base, "dne", None) is None - with pytest.raises(AttributeError): - getattr_chain(base, "dne") - - # test multi layer - assert getattr_chain(base, "b.c") == "value" - assert getattr_chain(base, "b.d") is None - assert getattr_chain(base, "b.d", "default") is None - - assert getattr_chain(base, "b.d.dne", "default") == "default" - with pytest.raises(AttributeError): - getattr_chain(base, "b.d.dne") - - @pytest.mark.unit def test_DisableQuantization(): model = torch.nn.Linear(1, 1)