Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -42,9 +42,9 @@ GPU_SIZE = os.environ.get("H3_GPU_SIZE", "xlarge")
|
|
| 42 |
# default, which reproduces the official weights exactly. Confirmed diffusers-native key naming (not ComfyUI,
|
| 43 |
# not pruned-AdaLN) via `xal2077/PinkCherry_MiniMax-H3-Demo`'s own working `load_state_dict(strict=True)` call
|
| 44 |
# against an earlier release of the same lineage.
|
| 45 |
-
CUSTOM_TRANSFORMER_REPO = os.environ.get("H3_CUSTOM_TRANSFORMER_REPO", "
|
| 46 |
CUSTOM_TRANSFORMER_FILE = os.environ.get(
|
| 47 |
-
"H3_CUSTOM_TRANSFORMER_FILE", "
|
| 48 |
)
|
| 49 |
|
| 50 |
LORA_REPO = os.environ.get("H3_LORA_REPO", "dagloop5/LoRA")
|
|
@@ -507,15 +507,18 @@ def load_models() -> str | None:
|
|
| 507 |
custom_transformer = MiniMaxH3Transformer3DModel.from_config(config)
|
| 508 |
base_shapes = {k: tuple(v.shape) for k, v in custom_transformer.state_dict().items()}
|
| 509 |
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
#
|
| 517 |
-
#
|
| 518 |
-
#
|
|
|
|
|
|
|
|
|
|
| 519 |
import json as _json
|
| 520 |
|
| 521 |
index_path = hf_hub_download(
|
|
@@ -530,34 +533,24 @@ def load_models() -> str | None:
|
|
| 530 |
with safe_open(shard_path, framework="pt") as shard_handle:
|
| 531 |
for key in shard_handle.keys():
|
| 532 |
official_state_dict[key] = shard_handle.get_tensor(key)
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
probe_key = "transformer_blocks.0.attn.to_q.weight"
|
| 552 |
-
shard_name = index["weight_map"][probe_key]
|
| 553 |
-
shard_path = _dl(MODEL_REPO, f"transformer/{shard_name}")
|
| 554 |
-
with safe_open(shard_path, framework="pt") as official_handle:
|
| 555 |
-
official_tensor = official_handle.get_tensor(probe_key)
|
| 556 |
-
converted_tensor = converted[probe_key]
|
| 557 |
-
print(f"[debug-compare] official {probe_key}: mean={official_tensor.float().mean():.6f} std={official_tensor.float().std():.6f} first5={official_tensor.flatten()[:5].tolist()}", flush=True)
|
| 558 |
-
print(f"[debug-compare] converted {probe_key}: mean={converted_tensor.float().mean():.6f} std={converted_tensor.float().std():.6f} first5={converted_tensor.flatten()[:5].tolist()}", flush=True)
|
| 559 |
-
print(f"[debug-compare] allclose: {torch.allclose(official_tensor, converted_tensor)}", flush=True)
|
| 560 |
-
custom_transformer.load_state_dict(converted, strict=True, assign=True)
|
| 561 |
|
| 562 |
# `rope.inv_freq` is a *non-persistent* buffer (`persistent=False` in `MiniMaxH3RotaryPosEmbed`) —
|
| 563 |
# excluded from `state_dict()` entirely, which is exactly why `strict=True` above never complained
|
|
|
|
| 42 |
# default, which reproduces the official weights exactly. Confirmed diffusers-native key naming (not ComfyUI,
|
| 43 |
# not pruned-AdaLN) via `xal2077/PinkCherry_MiniMax-H3-Demo`'s own working `load_state_dict(strict=True)` call
|
| 44 |
# against an earlier release of the same lineage.
|
| 45 |
+
CUSTOM_TRANSFORMER_REPO = os.environ.get("H3_CUSTOM_TRANSFORMER_REPO", "Comfy-Org/MiniMax-H3")
|
| 46 |
CUSTOM_TRANSFORMER_FILE = os.environ.get(
|
| 47 |
+
"H3_CUSTOM_TRANSFORMER_FILE", "diffusion_models/minimax_h3_fl2va_bf16.safetensors"
|
| 48 |
)
|
| 49 |
|
| 50 |
LORA_REPO = os.environ.get("H3_LORA_REPO", "dagloop5/LoRA")
|
|
|
|
| 507 |
custom_transformer = MiniMaxH3Transformer3DModel.from_config(config)
|
| 508 |
base_shapes = {k: tuple(v.shape) for k, v in custom_transformer.state_dict().items()}
|
| 509 |
|
| 510 |
+
custom_path = hf_hub_download(CUSTOM_TRANSFORMER_REPO, CUSTOM_TRANSFORMER_FILE)
|
| 511 |
+
with safe_open(custom_path, framework="pt") as handle:
|
| 512 |
+
raw = {k: handle.get_tensor(k) for k in handle.keys()}
|
| 513 |
+
converted = _convert_full_checkpoint(raw, base_shapes)
|
| 514 |
+
|
| 515 |
+
if os.environ.get("H3_DEBUG_COMPARE_ALL", "0") == "1":
|
| 516 |
+
# The meta+assign mechanism is proven correct (H3_DEBUG_OFFICIAL_VIA_META produced coherent,
|
| 517 |
+
# matching output using the official weights through this exact path), and two individual
|
| 518 |
+
# tensors (`norm1.weight`, `attn.to_q.weight`) are already proven bit-exact — so the remaining
|
| 519 |
+
# bug has to be in some *other* tensor `_convert_full_checkpoint` handles differently, not yet
|
| 520 |
+
# individually checked. This downloads the official transformer once (same cost as the mechanism
|
| 521 |
+
# test) and diffs every key against `converted`, rather than guessing which one to spot-check.
|
| 522 |
import json as _json
|
| 523 |
|
| 524 |
index_path = hf_hub_download(
|
|
|
|
| 533 |
with safe_open(shard_path, framework="pt") as shard_handle:
|
| 534 |
for key in shard_handle.keys():
|
| 535 |
official_state_dict[key] = shard_handle.get_tensor(key)
|
| 536 |
+
|
| 537 |
+
mismatches = []
|
| 538 |
+
for key, official_tensor in official_state_dict.items():
|
| 539 |
+
converted_tensor = converted.get(key)
|
| 540 |
+
if converted_tensor is None:
|
| 541 |
+
mismatches.append((key, "missing from converted"))
|
| 542 |
+
continue
|
| 543 |
+
if converted_tensor.shape != official_tensor.shape:
|
| 544 |
+
mismatches.append((key, f"shape {tuple(converted_tensor.shape)} != {tuple(official_tensor.shape)}"))
|
| 545 |
+
continue
|
| 546 |
+
if not torch.allclose(converted_tensor.float(), official_tensor.float(), atol=1e-3):
|
| 547 |
+
diff = (converted_tensor.float() - official_tensor.float()).abs().max().item()
|
| 548 |
+
mismatches.append((key, f"values differ, max abs diff {diff:.6f}"))
|
| 549 |
+
print(f"[debug-compare-all] checked {len(official_state_dict)} keys, {len(mismatches)} mismatches", flush=True)
|
| 550 |
+
for key, reason in mismatches[:30]:
|
| 551 |
+
print(f"[debug-compare-all] {key}: {reason}", flush=True)
|
| 552 |
+
|
| 553 |
+
custom_transformer.load_state_dict(converted, strict=True, assign=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 554 |
|
| 555 |
# `rope.inv_freq` is a *non-persistent* buffer (`persistent=False` in `MiniMaxH3RotaryPosEmbed`) —
|
| 556 |
# excluded from `state_dict()` entirely, which is exactly why `strict=True` above never complained
|