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.
This commit is contained in:
Daniel Han 2026-07-01 08:57:32 +00:00
commit fe5eee6a36
2 changed files with 34 additions and 8 deletions

View file

@ -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".

View file

@ -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():