Remove arbitrary low-bit tensor count cap and honor discard before preservation

This commit is contained in:
silveroxides
2026-10-31 23:16:02 +01:00
parent 6bbc566a52
commit 9ebe34565c
3 changed files with 25 additions and 33 deletions
+4 -4
View File
@@ -312,15 +312,15 @@ class MergerLogic:
discarded_keys += 1
pbar.update(1)
continue
if preserve_low_bit:
write_preserved_tensor(writer, key, primary_handler, force_raw=True)
pbar.update(1)
continue
# Check discard patterns first - skip entirely
if _matches_any_pattern(key, discard_patterns, glob_mode=glob_mode):
discarded_keys += 1
pbar.update(1)
continue
if preserve_low_bit:
write_preserved_tensor(writer, key, primary_handler, force_raw=True)
pbar.update(1)
continue
for name, mapping in alpha_normalization.items():
alpha_info = mapping.get(key)
-13
View File
@@ -7,9 +7,6 @@ import struct
import torch
MAX_ISOLATED_LOW_BIT_TENSORS = 2
def _low_bit_dtypes():
names = (
"int8",
@@ -135,11 +132,6 @@ class DiffusionQuantization:
key for key in self.data_keys
if key not in self.quantized_keys and _is_low_bit(handler, key)
}
if len(self.isolated_low_bit_keys) > MAX_ISOLATED_LOW_BIT_TENSORS:
raise ValueError(
f"[{label}] {model_path} contains {len(self.isolated_low_bit_keys)} low-bit tensors; "
"casted or quantized inputs are unsupported"
)
if self.isolated_low_bit_keys:
logging.warning(
"[%s] %s contains %d isolated low-bit tensor(s); preserving/excluding unchanged: %s",
@@ -413,11 +405,6 @@ def inspect_low_bit_input(handler, label: str, operation: str) -> set[str]:
)
low_bit_keys = {key for key in keys if _is_low_bit(handler, key)}
if len(low_bit_keys) > MAX_ISOLATED_LOW_BIT_TENSORS:
raise ValueError(
f"[{operation}] {label} contains {len(low_bit_keys)} low-bit tensors; "
"casted or quantized inputs are unsupported"
)
if low_bit_keys:
logging.warning(
"[%s] %s contains %d isolated low-bit tensor(s); "
+21 -16
View File
@@ -85,17 +85,16 @@ def test_int8_uint8_are_detected_and_warn_once(tmp_path, modules, caplog, dtype)
assert "low" in records[0].message
def test_exact_two_tensor_threshold(tmp_path, modules):
for count in range(4):
def test_multiple_low_bit_config_tensors_allowed(tmp_path, modules):
for count in (0, 1, 2, 52):
path = tmp_path / f"threshold_{count}.safetensors"
tensors = {f"low_{i}": torch.ones(2, dtype=torch.uint8) for i in range(count)}
tensors = {
f"diffusion_model.blocks.{i}.attn.comfy_attention.config": torch.ones(2, dtype=torch.uint8)
for i in range(count)
}
tensors["normal"] = torch.ones(1)
save_file(tensors, str(path))
if count <= 2:
assert len(_inspect_file(path, modules)) == count
else:
with pytest.raises(ValueError, match="3 low-bit tensors.*casted or quantized"):
_inspect_file(path, modules)
assert len(_inspect_file(path, modules)) == count
@pytest.mark.parametrize(
@@ -315,18 +314,24 @@ def test_multi_variants_preserve_earliest_complete_affected_layer(
assert "diffusion_model.normal.diff" in result
def test_hard_error_happens_before_resize_output_creation(monkeypatch, tmp_path, modules):
def test_resize_preserves_multiple_low_bit_config_tensors(monkeypatch, tmp_path, modules):
resize = modules["resize"]
_patch_output(monkeypatch, resize, tmp_path)
source = tmp_path / "three_low.safetensors"
save_file({f"low_{i}": torch.ones(1, dtype=torch.uint8) for i in range(3)}, str(source))
output = tmp_path / "must_not_exist.safetensors"
tensors = {
f"diffusion_model.blocks.{i}.attn.comfy_attention.config": torch.ones(1, dtype=torch.uint8)
for i in range(3)
}
tensors["diffusion_model.normal.lora_down.weight"] = torch.ones((2, 2))
tensors["diffusion_model.normal.lora_up.weight"] = torch.ones((2, 2))
save_file(tensors, str(source))
with pytest.raises(ValueError, match="3 low-bit tensors"):
resize.resize_lora_file(
str(source), 1, None, None, "cpu", torch.float16, output.stem, verbose=False
)
assert not output.exists()
output = resize.resize_lora_file(
str(source), 1, None, None, "cpu", torch.float16, "three_low_out", verbose=False
)
result = load_file(output)
for i in range(3):
assert result[f"diffusion_model.blocks.{i}.attn.comfy_attention.config"].dtype == torch.uint8
def test_recognized_quantization_creates_no_resize_output(monkeypatch, tmp_path, modules):