Refuse scaled fp8 LTX single files with a pointer to GGUF
The Lightricks/LTX-2.3-fp8 checkpoints store float8 weights with per-tensor weight_scale and input_scale companions (verified from the file headers: 1496 F8_E4M3 tensors, 2924 scale tensors). A plain dtype cast would silently corrupt every quantized layer, so the 2.3 assembly now detects the companions and raises with a pointer to the GGUF quants, which offer comparable fidelity through the supported path. Dequantizing the scaled fp8 layout is a possible follow-up.
This commit is contained in:
parent
b58098b219
commit
9c2107e8d3
2 changed files with 42 additions and 0 deletions
|
|
@ -506,6 +506,17 @@ def load_ltx23_pipeline(checkpoint_path: Path | str, *, base_repo: str, torch_dt
|
|||
groups = _split_checkpoint(state)
|
||||
del state
|
||||
|
||||
# The Lightricks fp8 single files store SCALED float8 weights (per-tensor
|
||||
# .weight_scale/.input_scale companions). Casting those without applying the
|
||||
# scales silently corrupts every quantized layer, so refuse loudly. GGUF
|
||||
# Q8_0 offers comparable fidelity at similar size through the supported path.
|
||||
if any(k.endswith((".weight_scale", ".input_scale")) for k in groups["dit"]):
|
||||
raise ValueError(
|
||||
"This LTX checkpoint stores scaled fp8 weights, which this loader does "
|
||||
"not dequantize yet. Use the GGUF quants from unsloth/LTX-2.3-GGUF "
|
||||
"instead (Q8_0 for the highest fidelity) or the official bf16 checkpoint."
|
||||
)
|
||||
|
||||
transformer = load_ltx23_transformer(
|
||||
groups["dit"], base_repo = base_repo, torch_dtype = torch_dtype,
|
||||
is_gguf = is_gguf, hf_token = hf_token,
|
||||
|
|
|
|||
|
|
@ -327,6 +327,37 @@ def test_ltx23_split_and_variant(tmp_path):
|
|||
assert checkpoint_variant("x/ltx-2.3-22b-dev-Q8_0.gguf") == "dev"
|
||||
|
||||
|
||||
def test_ltx23_scaled_fp8_refused(monkeypatch, tmp_path):
|
||||
# The Lightricks fp8 files carry .weight_scale/.input_scale companions; a
|
||||
# plain dtype cast would silently corrupt them, so the loader must refuse
|
||||
# with a pointer to the supported GGUF path.
|
||||
from core.inference import video_ltx2
|
||||
|
||||
# Stub the module tree so this also runs under the CI sim, which blocks the
|
||||
# real diffusers import.
|
||||
diffusers = types.ModuleType("diffusers")
|
||||
diffusers.LTX2Pipeline = object
|
||||
loaders = types.ModuleType("diffusers.loaders")
|
||||
sfu = types.ModuleType("diffusers.loaders.single_file_utils")
|
||||
sfu.load_single_file_checkpoint = lambda path: {
|
||||
"model.diffusion_model.transformer_blocks.0.attn1.to_q.weight": object(),
|
||||
"model.diffusion_model.transformer_blocks.0.attn1.to_q.weight_scale": object(),
|
||||
}
|
||||
diffusers.loaders = loaders
|
||||
loaders.single_file_utils = sfu
|
||||
monkeypatch.setitem(sys.modules, "diffusers", diffusers)
|
||||
monkeypatch.setitem(sys.modules, "diffusers.loaders", loaders)
|
||||
monkeypatch.setitem(sys.modules, "diffusers.loaders.single_file_utils", sfu)
|
||||
monkeypatch.setitem(sys.modules, "transformers", types.ModuleType("transformers"))
|
||||
|
||||
path = tmp_path / "ltx-2.3-22b-distilled-fp8.safetensors"
|
||||
path.write_bytes(b"x")
|
||||
with pytest.raises(ValueError, match = "scaled fp8"):
|
||||
video_ltx2.load_ltx23_pipeline(
|
||||
path, base_repo = "Lightricks/LTX-2", torch_dtype = None, is_gguf = False
|
||||
)
|
||||
|
||||
|
||||
def test_generate_without_load_raises(fake_runtime):
|
||||
backend = VideoBackend()
|
||||
with pytest.raises(RuntimeError, match = VIDEO_NOT_LOADED_MSG):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue