From fe5eee6a363591831253a4a079f56ff4b96f1913 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 1 Jul 2026 08:57:32 +0000 Subject: [PATCH] Lower llm-compressor floor to 0.6.0 so supported old torch still resolves The >=0.8.0 floor conflicts with the torch this install pins in its constraints file. Unsloth supports torch>=2.4, but llm-compressor 0.7.0+ require torch>=2.7 (0.10+ need >=2.9, 0.12+ need >=2.10). On a supported torch 2.4-2.6 box pip then has no candidate in [0.8.0, 1.0) and FP8/FP4 export fails before quantization. Lower the floor to 0.6.0 (its metadata only needs torch>=1.7), which never conflicts with any supported torch. pip still prefers the newest compatible release, so modern torch continues to get the latest 0.x (0.12.0). The <1.0 ceiling that blocks an inflated-version supply-chain jump is unchanged. Add a regression test asserting the floor stays <= 0.6.0. --- .../saving/test_llm_compressor_install_pin.py | 20 +++++++++++++++++ unsloth/save.py | 22 ++++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/tests/saving/test_llm_compressor_install_pin.py b/tests/saving/test_llm_compressor_install_pin.py index fc3f30fee0..89fdf52f84 100644 --- a/tests/saving/test_llm_compressor_install_pin.py +++ b/tests/saving/test_llm_compressor_install_pin.py @@ -54,6 +54,26 @@ def test_spec_is_a_bounded_pin() -> None: assert ">=" in spec and "<" in spec, f"spec must have lower and upper bounds, got {spec!r}" +def test_floor_stays_compatible_with_supported_torch() -> None: + """The floor must not require a torch newer than the oldest torch Unsloth supports (>=2.4). + + llm-compressor 0.7.0+ require torch>=2.7 (0.10+ >=2.9, 0.12+ >=2.10); only <=0.6.x allows + torch<2.7. Since install_llm_compressor() pins the current torch in the constraints file, a + floor above 0.6.0 leaves pip with no candidate on a supported torch 2.4-2.6 box and breaks + FP8/FP4 export. Keep the floor at or below 0.6.0. + """ + from packaging.requirements import Requirement + from packaging.version import Version + + req = Requirement(_spec_value()) + lowers = [Version(s.version) for s in req.specifier if s.operator in (">=", "==", "~=")] + assert lowers, "spec must declare a lower bound" + assert max(lowers) <= Version("0.6.0"), ( + f"floor {max(lowers)} requires a torch newer than Unsloth's minimum (2.4); " + "llm-compressor >0.6.0 needs torch>=2.7. Keep the floor <= 0.6.0." + ) + + def test_install_command_uses_pinned_spec_not_bare_name() -> None: fn = _get_function("install_llm_compressor") # No argv list may pass the bare, unpinned package literal "llmcompressor". diff --git a/unsloth/save.py b/unsloth/save.py index 4355d77f6d..b9a7cb1dfc 100644 --- a/unsloth/save.py +++ b/unsloth/save.py @@ -1367,14 +1367,20 @@ def install_python_non_blocking(packages = []): # bound, `pip install llmcompressor` resolves to whatever the configured index offers, so a # compromised, dependency-confused, or inflated-version ("999.0.0") release could be pulled and # executed under the Unsloth process at install/import time; the "<1.0" ceiling blocks that jump. -# The floor keeps the oneshot / QuantizationModifier API this uses. Crucially the range still lets -# pip pick up new 0.x releases, which is where support for brand-new architectures lands (the gate -# below can require a newer llm-compressor for newer schemes/models) -- an exact pin would break -# exporting new models. Bump the ceiling deliberately when llm-compressor reaches 1.0 so a new -# major is vetted before it is auto-installed. An already-installed newer llm-compressor is used -# as-is (the import below short-circuits), so this only constrains the auto-install, never what -# the user installed themselves. -_LLM_COMPRESSOR_SPEC = "llmcompressor>=0.8.0,<1.0" +# The range still lets pip pick up new 0.x releases, which is where support for brand-new +# architectures lands (the gate below can require a newer llm-compressor for newer schemes/models) +# -- an exact pin would break exporting new models. Bump the ceiling deliberately when +# llm-compressor reaches 1.0 so a new major is vetted before it is auto-installed. +# +# The floor is 0.6.0 (its metadata only needs torch>=1.7) so it never conflicts with the torch this +# install pins in the constraints file below: Unsloth supports torch>=2.4, but llm-compressor +# 0.7.0+ require torch>=2.7 (0.10+ need >=2.9, 0.12+ need >=2.10). A higher floor would leave pip +# with no candidate on a supported torch 2.4-2.6 box and break FP8/FP4 export before quantization. +# pip still prefers the newest compatible release, so modern torch gets the latest 0.x anyway. +# +# An already-installed newer llm-compressor is used as-is (the import below short-circuits), so this +# only constrains the auto-install, never what the user installed themselves. +_LLM_COMPRESSOR_SPEC = "llmcompressor>=0.6.0,<1.0" def install_llm_compressor():