File size: 2,256 Bytes
6429c4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Generate StarNodes converter profiles for MiniMax-H3 from the bf16 safetensors header.

Two variants:
  minimax_h3_nvfp4_mixed.json  - AdaLN kept at FP8, attn/mlp at NVFP4  (recommended)
  minimax_h3_nvfp4_full.json   - everything incl. AdaLN at NVFP4       (aggressive)

Kept at BF16 in both: all biases, all norms, rope freqs, patch/time/condition
embedders and the final output heads (~0.04B params total, 0.1% of the model).
"""
import json, struct, sys, os, datetime

SRC = "/workspace/ComfyUI/models/diffusion_models/minimax_h3_ref2va_bf16.safetensors"
OUT_DIR = "/workspace/ComfyUI/custom_nodes/comfyui-starnodes-modelconverter/profiles"

with open(SRC, "rb") as f:
    n = struct.unpack("<Q", f.read(8))[0]
    hdr = json.loads(f.read(n))
keys = sorted(k for k in hdr if k != "__metadata__")


def classify(key, adaln_fmt):
    # non-weight tensors and everything tiny stays bf16
    if not key.endswith(".weight"):
        return "BF16"
    if "norm" in key or key.endswith("inv_freq"):
        return "BF16"
    if any(t in key for t in ("patch_proj", "time_embedder", "condition_proj", "final_layer")):
        return "BF16"
    if "adaln" in key:
        return adaln_fmt
    if ".attn." in key or ".mlp." in key:
        return "NVFP4"
    return "BF16"


def build(adaln_fmt, name):
    layers, counts = {}, {}
    for k in keys:
        fmt = classify(k, adaln_fmt)
        layers[k] = fmt
        counts[fmt] = counts.get(fmt, 0) + 1
        if fmt != "BF16":
            base = k[: -len(".weight")]
            layers[f"{base}.weight_scale"] = "FP32_SCALE"
            layers[f"{base}.comfy_quant"] = "METADATA"
    prof = {
        "__metadata__": {
            "original_model_name": name,
            "original_model_path": SRC,
            "timestamp": datetime.datetime.now().isoformat(),
            "total_layers": len(layers),
            "created_by": "hand-authored for MiniMax-H3 (33.12B: adaln 39.4%, mlp 36.3%, attn 24.2%)",
        },
        "layers": layers,
    }
    path = os.path.join(OUT_DIR, f"{name}.json")
    with open(path, "w") as f:
        json.dump(prof, f, indent=1)
    print(f"{name}: {counts}  -> {path}")


build("FP8_E4M3FN + SCALE", "minimax_h3_nvfp4_mixed")
build("NVFP4", "minimax_h3_nvfp4_full")