dagloop5 commited on
Commit
8778b92
·
verified ·
1 Parent(s): 690fc2b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -39
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", "SexGod1979/PinkCherry_MiniMax-H3")
46
  CUSTOM_TRANSFORMER_FILE = os.environ.get(
47
- "H3_CUSTOM_TRANSFORMER_FILE", "v1-final-fl2va/PinkCherry_v1_bf16_fla2va_H3.safetensors"
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
- if os.environ.get("H3_DEBUG_OFFICIAL_VIA_META", "0") == "1":
511
- # Isolates the meta-device + `assign=True` loading mechanism from `_convert_full_checkpoint`'s
512
- # own conversion logic: loads the official, diffusers-native shards — no renaming, no splitting,
513
- # nothing converted at all — through the exact same path the custom-checkpoint loader uses. If
514
- # this *also* produces the same corrupted output, the bug is in the mechanism itself (meta
515
- # construction, `assign=True`, the fp32 upcast, or something in between), independent of
516
- # anything the conversion does, since no conversion happens here at all. If this loads clean,
517
- # the bug is narrowed back to `_convert_full_checkpoint` specifically, despite everything
518
- # checked against it so far.
 
 
 
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
- custom_transformer.load_state_dict(official_state_dict, strict=True, assign=True)
534
- print(
535
- "[gen] loaded the OFFICIAL weights via the meta+assign path, bypassing "
536
- "_convert_full_checkpoint entirely — diagnostic only",
537
- flush=True,
538
- )
539
- else:
540
- custom_path = hf_hub_download(CUSTOM_TRANSFORMER_REPO, CUSTOM_TRANSFORMER_FILE)
541
- with safe_open(custom_path, framework="pt") as handle:
542
- raw = {k: handle.get_tensor(k) for k in handle.keys()}
543
- converted = _convert_full_checkpoint(raw, base_shapes)
544
- if os.environ.get("H3_DEBUG_COMPARE", "0") == "1":
545
- from huggingface_hub import hf_hub_download as _dl
546
- import json as _json
547
-
548
- index_path = _dl(MODEL_REPO, "transformer/diffusion_pytorch_model.safetensors.index.json")
549
- with open(index_path) as handle:
550
- index = _json.load(handle)
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