Download code/tools/patch_checkpoint_v3.py from FlyCockpit/GLM-5.2-NVFP4-AQLM-Abliterated-Vision: direct link, hf CLI and curl.
- Browser
- Download file 5.26 kB
-
https://huggingface.co/FlyCockpit/GLM-5.2-NVFP4-AQLM-Abliterated-Vision/resolve/main/code/tools/patch_checkpoint_v3.py
- Command line
-
hf download hf://FlyCockpit/GLM-5.2-NVFP4-AQLM-Abliterated-Vision/code/tools/patch_checkpoint_v3.py
-
curl -L -o patch_checkpoint_v3.py https://huggingface.co/FlyCockpit/GLM-5.2-NVFP4-AQLM-Abliterated-Vision/resolve/main/code/tools/patch_checkpoint_v3.py
5.26 kB
| #!/usr/bin/env python3 | |
| """Convert whole-NVFP4 layers of /data/glm52 to per-expert hybrid, in place. | |
| For each layer in the assignment that still has per-expert NVFP4 tensors in | |
| the checkpoint: build the v3 hybrid tensor set (hyb_kind, compacted NVFP4 | |
| hot arrays, sliced AQLM base groups from /data/glm52-aqlm-parts), write it | |
| as a patch shard, update index + config, then physically strip the stale | |
| per-expert tensors (vLLM's loader reads shard files, not the index). | |
| """ | |
| import json | |
| import os | |
| import re | |
| import sys | |
| import torch | |
| from safetensors import safe_open | |
| from safetensors.torch import save_file | |
| DST = "/data/glm52" | |
| PARTS = "/data/glm52-aqlm-parts" | |
| ASSIGN = "/data/glm52-expert-assignment.json" | |
| assignment = {int(k): v for k, v in json.load(open(ASSIGN)).items()} | |
| idx_path = os.path.join(DST, "model.safetensors.index.json") | |
| idx = json.load(open(idx_path)) | |
| wm = idx["weight_map"] | |
| cfg = json.load(open(os.path.join(DST, "config.json"))) | |
| books_cfg = cfg["quantization_config"]["aqlm_layer_books"] | |
| # layers that need conversion: in assignment but not yet in config books | |
| todo = sorted(li for li in assignment if str(li) not in books_cfg) | |
| print("layers to convert:", todo) | |
| if not todo: | |
| sys.exit(0) | |
| class Reader: | |
| def __init__(self): | |
| self._open = {} | |
| def get(self, name): | |
| shard = wm[name] | |
| if shard not in self._open: | |
| self._open[shard] = safe_open( | |
| os.path.join(DST, shard), framework="pt" | |
| ) | |
| return self._open[shard].get_tensor(name) | |
| reader = Reader() | |
| n_exp, inter, hidden = 256, 2048, 6144 | |
| for li in todo: | |
| hot = sorted(assignment[li]["hot"]) | |
| cold = sorted(assignment[li]["cold"]) | |
| hot_s, cold_s = set(hot), set(cold) | |
| base = [e for e in range(n_exp) if e not in hot_s and e not in cold_s] | |
| b_all = sorted(set(base) | cold_s) | |
| kind = torch.ones(n_exp, dtype=torch.int8) | |
| for e in hot: | |
| kind[e] = 0 | |
| for e in cold: | |
| kind[e] = 2 | |
| part = torch.load( | |
| os.path.join(PARTS, f"layer_{li}.pt"), map_location="cpu", | |
| weights_only=True, | |
| ) | |
| p = f"model.layers.{li}.mlp.experts" | |
| b_idx = torch.tensor(b_all, dtype=torch.long) | |
| base_idx = torch.tensor(base, dtype=torch.long) | |
| cold_idx = torch.tensor(cold, dtype=torch.long) | |
| tensors = { | |
| f"{p}.hyb_kind": kind, | |
| f"{p}.w13_codes": part["w13_codes"][b_idx].contiguous(), | |
| f"{p}.w13_codebooks": part["w13_codebooks"].clone(), | |
| f"{p}.w13_scales": part["w13_scales"][b_idx].contiguous(), | |
| f"{p}.w2m_codes": part["w2_codes"][base_idx].contiguous(), | |
| f"{p}.w2m_codebooks": part["w2_codebooks"].clone(), | |
| f"{p}.w2m_scales": part["w2_scales"][base_idx].contiguous(), | |
| f"{p}.w2c_codes": part["w2_codes"][cold_idx, :1].clone(), | |
| f"{p}.w2c_codebooks": part["w2_codebooks"][:1].clone(), | |
| f"{p}.w2c_scales": part["w2_scales"][cold_idx].contiguous(), | |
| } | |
| na = len(hot) | |
| w13_packed = torch.empty(na, 2 * inter, hidden // 2, dtype=torch.uint8) | |
| w13_bscale = torch.empty(na, 2 * inter, hidden // 16, dtype=torch.uint8) | |
| w13_scale2 = torch.empty(na, 2, dtype=torch.float32) | |
| w2_packed = torch.empty(na, hidden, inter // 2, dtype=torch.uint8) | |
| w2_bscale = torch.empty(na, hidden, inter // 16, dtype=torch.uint8) | |
| w2_scale2 = torch.empty(na, 1, dtype=torch.float32) | |
| for j, e in enumerate(hot): | |
| ep = f"{p}.{e}" | |
| w13_packed[j, :inter] = reader.get(f"{ep}.gate_proj.weight") | |
| w13_packed[j, inter:] = reader.get(f"{ep}.up_proj.weight") | |
| w2_packed[j] = reader.get(f"{ep}.down_proj.weight") | |
| w13_bscale[j, :inter] = reader.get( | |
| f"{ep}.gate_proj.weight_scale").view(torch.uint8) | |
| w13_bscale[j, inter:] = reader.get( | |
| f"{ep}.up_proj.weight_scale").view(torch.uint8) | |
| w2_bscale[j] = reader.get( | |
| f"{ep}.down_proj.weight_scale").view(torch.uint8) | |
| w13_scale2[j, 0] = reader.get(f"{ep}.gate_proj.weight_scale_2").float() | |
| w13_scale2[j, 1] = reader.get(f"{ep}.up_proj.weight_scale_2").float() | |
| w2_scale2[j, 0] = reader.get(f"{ep}.down_proj.weight_scale_2").float() | |
| tensors.update({ | |
| f"{p}.nvfp4_w13_packed": w13_packed, | |
| f"{p}.nvfp4_w13_bscale": w13_bscale, | |
| f"{p}.nvfp4_w13_scale2": w13_scale2, | |
| f"{p}.nvfp4_w2_packed": w2_packed, | |
| f"{p}.nvfp4_w2_bscale": w2_bscale, | |
| f"{p}.nvfp4_w2_scale2": w2_scale2, | |
| }) | |
| fname = f"model-hybrid-patch-layer{li}.safetensors" | |
| save_file(tensors, os.path.join(DST, fname)) | |
| stale = [n for n in wm | |
| if re.match(rf"model\.layers\.{li}\.mlp\.experts\.\d+\.", n)] | |
| for n in stale: | |
| del wm[n] | |
| for n in tensors: | |
| wm[n] = fname | |
| books_cfg[str(li)] = { | |
| "n_nvfp4": na, "n_base": len(base), "n_cold": len(cold), | |
| } | |
| nb = sum(t.numel() * t.element_size() for t in tensors.values()) | |
| print(f"layer {li}: hot={na} base={len(base)} cold={len(cold)} " | |
| f"patch={nb/1e9:.2f} GB, dropped {len(stale)} per-expert tensors", | |
| flush=True) | |
| reader._open.clear() | |
| json.dump(idx, open(idx_path, "w"), indent=0) | |
| json.dump(cfg, open(os.path.join(DST, "config.json"), "w"), indent=2) | |
| print("index/config updated; run strip_stale.py next") | |