Upload 2 files
Browse files- quantized/combine.py +101 -11
- quantized/metadata.json +45 -0
quantized/combine.py
CHANGED
|
@@ -1,11 +1,101 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
|
| 3 |
+
import safetensors.torch
|
| 4 |
+
import os
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
def prompt_file(prompt, default):
|
| 8 |
+
path = input(f"{prompt} [{default}]: ").strip()
|
| 9 |
+
return path if path else default
|
| 10 |
+
|
| 11 |
+
# Prompt for input/output files
|
| 12 |
+
quant_file = prompt_file("Enter path to quantized blocks", "transformer_blocks.safetensors")
|
| 13 |
+
unquant_file = prompt_file("Enter path to unquantized layers", "unquantized_layers.safetensors")
|
| 14 |
+
output_file = prompt_file("Enter path to save combined model", "combined.safetensors")
|
| 15 |
+
metadata_file = prompt_file("Enter path to metadata.json (optional)", "metadata.json")
|
| 16 |
+
|
| 17 |
+
# Validate file existence
|
| 18 |
+
for f in [quant_file, unquant_file]:
|
| 19 |
+
if not os.path.isfile(f):
|
| 20 |
+
raise FileNotFoundError(f"File not found: {f}")
|
| 21 |
+
|
| 22 |
+
# Load state dicts
|
| 23 |
+
quantized_blocks = safetensors.torch.load_file(quant_file)
|
| 24 |
+
unquantized_layers = safetensors.torch.load_file(unquant_file)
|
| 25 |
+
|
| 26 |
+
# Warn about key overlaps
|
| 27 |
+
overlap = set(quantized_blocks) & set(unquantized_layers)
|
| 28 |
+
if overlap:
|
| 29 |
+
print(f"⚠️ Warning: Overlapping keys (unquantized will override): {overlap}")
|
| 30 |
+
|
| 31 |
+
# Merge state dicts
|
| 32 |
+
combined_state_dict = {**quantized_blocks, **unquantized_layers}
|
| 33 |
+
|
| 34 |
+
# Attempt to load metadata.json
|
| 35 |
+
metadata = {}
|
| 36 |
+
if os.path.isfile(metadata_file):
|
| 37 |
+
try:
|
| 38 |
+
with open(metadata_file, "r", encoding="utf-8") as f:
|
| 39 |
+
metadata = json.load(f)
|
| 40 |
+
# Convert nested objects to JSON strings as required by safetensors
|
| 41 |
+
for k, v in metadata.items():
|
| 42 |
+
if isinstance(v, dict):
|
| 43 |
+
metadata[k] = json.dumps(v)
|
| 44 |
+
except Exception as e:
|
| 45 |
+
print(f"⚠️ Failed to load metadata from {metadata_file}: {e}")
|
| 46 |
+
print("⏳ Falling back to hardcoded metadata...")
|
| 47 |
+
metadata = {} # Will populate below
|
| 48 |
+
|
| 49 |
+
# Fallback metadata (if file load failed or was missing)
|
| 50 |
+
if not metadata:
|
| 51 |
+
metadata = {
|
| 52 |
+
"model_class": "NunchakuFluxTransformer2dModel",
|
| 53 |
+
"comfy_config": json.dumps({
|
| 54 |
+
"model_class": "Flux",
|
| 55 |
+
"model_config": {
|
| 56 |
+
"axes_dim": [16, 56, 56],
|
| 57 |
+
"context_in_dim": 4096,
|
| 58 |
+
"depth": 19,
|
| 59 |
+
"depth_single_blocks": 38,
|
| 60 |
+
"disable_unet_model_creation": True,
|
| 61 |
+
"guidance_embed": True,
|
| 62 |
+
"hidden_size": 3072,
|
| 63 |
+
"image_model": "flux",
|
| 64 |
+
"in_channels": 16,
|
| 65 |
+
"mlp_ratio": 4.0,
|
| 66 |
+
"num_heads": 24,
|
| 67 |
+
"out_channels": 16,
|
| 68 |
+
"patch_size": 2,
|
| 69 |
+
"qkv_bias": True,
|
| 70 |
+
"theta": 10000,
|
| 71 |
+
"vec_in_dim": 768
|
| 72 |
+
}
|
| 73 |
+
}),
|
| 74 |
+
"quantization_config": json.dumps({
|
| 75 |
+
"method": "svdquant",
|
| 76 |
+
"weight": {"dtype": "int4", "scale_dtype": None, "group_size": 64},
|
| 77 |
+
"activation": {"dtype": "int4", "scale_dtype": None, "group_size": 64}
|
| 78 |
+
}),
|
| 79 |
+
"config": json.dumps({
|
| 80 |
+
"_class_name": "FluxTransformer2DModel",
|
| 81 |
+
"_diffusers_version": "0.34.0.dev0",
|
| 82 |
+
"_name_or_path": "../checkpoints/flux-dev/transformer",
|
| 83 |
+
"attention_head_dim": 128,
|
| 84 |
+
"axes_dims_rope": [16, 56, 56],
|
| 85 |
+
"guidance_embeds": True,
|
| 86 |
+
"in_channels": 64,
|
| 87 |
+
"joint_attention_dim": 4096,
|
| 88 |
+
"num_attention_heads": 24,
|
| 89 |
+
"num_layers": 19,
|
| 90 |
+
"num_single_layers": 38,
|
| 91 |
+
"out_channels": None,
|
| 92 |
+
"patch_size": 1,
|
| 93 |
+
"pooled_projection_dim": 768
|
| 94 |
+
})
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
# Save the combined safetensors file
|
| 98 |
+
safetensors.torch.save_file(combined_state_dict, output_file, metadata=metadata)
|
| 99 |
+
|
| 100 |
+
print(f"\n✅ Combined model saved to: {output_file}")
|
| 101 |
+
print(f"ℹ️ Metadata keys included: {', '.join(metadata.keys())}")
|
quantized/metadata.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_class": "NunchakuFluxTransformer2dModel",
|
| 3 |
+
"comfy_config": {
|
| 4 |
+
"model_class": "Flux",
|
| 5 |
+
"model_config": {
|
| 6 |
+
"axes_dim": [16, 56, 56],
|
| 7 |
+
"context_in_dim": 4096,
|
| 8 |
+
"depth": 19,
|
| 9 |
+
"depth_single_blocks": 38,
|
| 10 |
+
"disable_unet_model_creation": true,
|
| 11 |
+
"guidance_embed": true,
|
| 12 |
+
"hidden_size": 3072,
|
| 13 |
+
"image_model": "flux",
|
| 14 |
+
"in_channels": 16,
|
| 15 |
+
"mlp_ratio": 4.0,
|
| 16 |
+
"num_heads": 24,
|
| 17 |
+
"out_channels": 16,
|
| 18 |
+
"patch_size": 2,
|
| 19 |
+
"qkv_bias": true,
|
| 20 |
+
"theta": 10000,
|
| 21 |
+
"vec_in_dim": 768
|
| 22 |
+
}
|
| 23 |
+
},
|
| 24 |
+
"quantization_config": {
|
| 25 |
+
"method": "svdquant",
|
| 26 |
+
"weight": {"dtype": "int4", "scale_dtype": null, "group_size": 64},
|
| 27 |
+
"activation": {"dtype": "int4", "scale_dtype": null, "group_size": 64}
|
| 28 |
+
},
|
| 29 |
+
"config": {
|
| 30 |
+
"_class_name": "FluxTransformer2DModel",
|
| 31 |
+
"_diffusers_version": "0.34.0.dev0",
|
| 32 |
+
"_name_or_path": "../checkpoints/flux-dev/transformer",
|
| 33 |
+
"attention_head_dim": 128,
|
| 34 |
+
"axes_dims_rope": [16, 56, 56],
|
| 35 |
+
"guidance_embeds": true,
|
| 36 |
+
"in_channels": 64,
|
| 37 |
+
"joint_attention_dim": 4096,
|
| 38 |
+
"num_attention_heads": 24,
|
| 39 |
+
"num_layers": 19,
|
| 40 |
+
"num_single_layers": 38,
|
| 41 |
+
"out_channels": null,
|
| 42 |
+
"patch_size": 1,
|
| 43 |
+
"pooled_projection_dim": 768
|
| 44 |
+
}
|
| 45 |
+
}
|