dagloop5 commited on
Commit
af236ae
·
verified ·
1 Parent(s): f4431dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -35
app.py CHANGED
@@ -1,10 +1,8 @@
1
  """`Plaguekind/Minimax-H3` — the PlagueKind V1.5 ComfyUI workflow for MiniMax-H3, as a Space.
2
-
3
  The candidate repository holds no weights: it is a ComfyUI graph over `Comfy-Org/MiniMax-H3`, so what is
4
  reproduced here is the *graph*, on the `MiniMaxAI/MiniMax-H3` diffusers checkpoint. See `pk_workflow.py` for the
5
  node-by-node mapping; the short version is euler + `linear_quadratic` at 15 steps, FSR RCAS sharpening at 0.3, and
6
  FILM 2x frame interpolation to 48 fps.
7
-
8
  Deployment is the split one the unquantized MiniMax-H3 needs: 195.9 GiB of bfloat16 does not fit under a Space's
9
  150 GB storage quota, so the 62.14 GiB Qwen3-VL text encoder runs in a separate Space
10
  (`multimodalart/qwen3vl-conditioner`) that this one calls per request, and this Space holds the 61.73 GiB
@@ -82,7 +80,6 @@ DEFAULT_STEPS = 15
82
 
83
  def snap_frames(seconds: float) -> int:
84
  """The frame count MiniMax-H3's video VAE can decode: the next `17 * n + 5` at 24 fps.
85
-
86
  Identical to the workflow's `ComfyMathExpression`,
87
  `max(5, round(a*24)) + (5 - (max(5, round(a*24)) % 17)) % 17` — 5 s is 124 frames, i.e. 5.167 s.
88
  """
@@ -123,7 +120,6 @@ def status() -> str:
123
 
124
  def load_models() -> str | None:
125
  """Load the denoising half at startup, plus FILM.
126
-
127
  `MiniMaxH3GeneratorBlocks` declares `transformer`, `vae`, `audio_vae`, the two schedulers and `video_processor`,
128
  so `load_components` fetches exactly those subfolders — `text_encoder/` and `transformer_ref/` are never
129
  touched. Both autoencoders carry `_keep_in_fp32_modules` over every module and stay float32: a bfloat16 audio
@@ -138,31 +134,15 @@ def load_models() -> str | None:
138
  try:
139
  import torch
140
  from diffusers import ComponentsManager
 
141
  from h3_split_blocks import MiniMaxH3GeneratorBlocks
142
-
143
  lower_duration_floor()
144
-
145
  manager = ComponentsManager()
146
  blocks = MiniMaxH3GeneratorBlocks()
147
-
148
- print(
149
- f"[gen] loading {[c.name for c in blocks.expected_components]} from {MODEL_REPO} ...",
150
- flush=True,
151
- )
152
-
153
- pipe = blocks.init_pipeline(
154
- MODEL_REPO,
155
- components_manager=manager,
156
- collection="h3",
157
- )
158
-
159
  pipe.load_components(dtype=torch.bfloat16)
160
- # Load TenStrip fine-tuned checkpoint into the transformer
161
- from huggingface_hub import hf_hub_download
162
- from safetensors.torch import load_model
163
- finetune_path = hf_hub_download(repo_id="TenStrip/10Eros-Max", filename="10Eros_Max_h3_fl2va_bf16_test2_pruned.safetensors")
164
- load_model(pipe.transformer, finetune_path, strict=False, device="cpu")
165
- pipe.transformer.to(torch.bfloat16)
166
  pipe.transformer.set_attention_backend(ATTENTION)
167
 
168
  # Still startup, still free: an AoTI package carries no weights and opens its archive lazily inside the GPU
@@ -300,7 +280,6 @@ def _generate(
300
  seed,
301
  ):
302
  """The only thing on GPU time: the denoise loop, the two decoders and the workflow's post chain.
303
-
304
  The mp4 is muxed here rather than in the caller: a `@spaces.GPU` return crosses a process boundary by pickling,
305
  and a 2x-interpolated 124-frame clip is several hundred MB of frames against a few MB of h264.
306
  """
@@ -502,19 +481,16 @@ def _fit_keyframe(image_path, current_canvas):
502
 
503
  load_models()
504
 
505
- INTRO = """# PlagueKind · 10Eros-Max · MiniMax-H3
506
-
507
  <div align="center">
508
  <a href="https://huggingface.co/Plaguekind/Minimax-H3" target="_blank" rel="noopener"><strong>[ workflow ]</strong></a> &nbsp;
509
  <a href="https://huggingface.co/MiniMaxAI/MiniMax-H3" target="_blank" rel="noopener"><strong>[ model ]</strong></a> &nbsp;
510
  <a href="https://github.com/PlagueKind/Comfyui-PlagueKind-Nodes" target="_blank" rel="noopener"><strong>[ nodes ]</strong></a>
511
- <a href="https://huggingface.co/TenStrip/10Eros-Max" target="_blank" rel="noopener"><strong>[ 10Eros-Max ]</strong></a>
512
  </div>
513
-
514
  **MiniMax-H3** is a 33B parameter video generation model that produces video and a fully synchronized soundtrack
515
  (ambience, foley, speech) in one pass. **PlagueKind's V1.5 workflow** is a tuning of it: euler on a
516
  `linear_quadratic` sigma grid at 15 steps, FSR **RCAS** sharpening at 0.3, and **FILM** 2x frame interpolation to
517
- 48 fps. Text-to-video, first frame, last frame, or both. TenStrip's **10Eros-Max** is an experimental finetune of MiniMax-H3.
518
  """
519
 
520
  CSS = """
@@ -523,7 +499,7 @@ CSS = """
523
  .status p {font-size: 0.8rem; opacity: 0.65; text-align: center;}
524
  """
525
 
526
- with gr.Blocks(title="PlagueKind · 10Eros-Max · MiniMax-H3") as demo:
527
  gr.Markdown(INTRO)
528
  gr.Markdown(status(), elem_classes="status")
529
 
@@ -652,7 +628,6 @@ with gr.Blocks(title="PlagueKind · 10Eros-Max · MiniMax-H3") as demo:
652
  """
653
  `Plaguekind/Minimax-H3` ships no weights — it is a ComfyUI graph over `Comfy-Org/MiniMax-H3`. Its nodes map onto
654
  this Space as:
655
-
656
  | ComfyUI node | widget | here |
657
  |---|---|---|
658
  | `KSamplerSelect` | `euler` | MiniMax-H3's only sampler; the checkpoint is CFG-distilled, so one forward per step and no negative prompt |
@@ -664,13 +639,11 @@ this Space as:
664
  | `CreateVideo` | fps `24 * 2` | 48 fps output |
665
  | `RTXVideoSuperResolution` | 2x `ULTRA` | **not reproduced** |
666
  | `PathchSageAttentionKJ` | `sageattn_qk_int8_pv_fp8_cuda++` | cuDNN fused attention |
667
-
668
  Two deliberate deviations. `RTXVideoSuperResolution` is NVIDIA's NGX super-resolution, shipped as a driver-level
669
  Windows/RTX component with no Linux Python path, so the 2x upscale is missing — pick a larger **Target dimension**
670
  instead of upscaling a small one. And SageAttention's `qk_int8_pv_fp8_cuda++` kernel is not built for this pool's
671
  sm120 cards, so attention runs cuDNN's fused kernel, which is the fastest available here and is numerically the
672
  faithful one (SageAttention is a quantized approximation).
673
-
674
  One upgrade: the workflow loads `minimax_h3_fl2va_pruned_int8_convrot.safetensors` and a
675
  `qwen3vl_32b_..._int8_convrot` text encoder because that is what fits a consumer card. This Space runs both
676
  **unquantized bfloat16**, off `MiniMaxAI/MiniMax-H3`, with the 62 GiB text encoder in a
@@ -683,4 +656,4 @@ One upgrade: the workflow loads `minimax_h3_fl2va_pruned_int8_convrot.safetensor
683
 
684
  if __name__ == "__main__":
685
  # `theme` and `css` belong to `launch()` from Gradio 6.0 on; on `Blocks` they warn and are ignored.
686
- demo.launch(show_error=True, theme=gr.themes.Citrus(), css=CSS)
 
1
  """`Plaguekind/Minimax-H3` — the PlagueKind V1.5 ComfyUI workflow for MiniMax-H3, as a Space.
 
2
  The candidate repository holds no weights: it is a ComfyUI graph over `Comfy-Org/MiniMax-H3`, so what is
3
  reproduced here is the *graph*, on the `MiniMaxAI/MiniMax-H3` diffusers checkpoint. See `pk_workflow.py` for the
4
  node-by-node mapping; the short version is euler + `linear_quadratic` at 15 steps, FSR RCAS sharpening at 0.3, and
5
  FILM 2x frame interpolation to 48 fps.
 
6
  Deployment is the split one the unquantized MiniMax-H3 needs: 195.9 GiB of bfloat16 does not fit under a Space's
7
  150 GB storage quota, so the 62.14 GiB Qwen3-VL text encoder runs in a separate Space
8
  (`multimodalart/qwen3vl-conditioner`) that this one calls per request, and this Space holds the 61.73 GiB
 
80
 
81
  def snap_frames(seconds: float) -> int:
82
  """The frame count MiniMax-H3's video VAE can decode: the next `17 * n + 5` at 24 fps.
 
83
  Identical to the workflow's `ComfyMathExpression`,
84
  `max(5, round(a*24)) + (5 - (max(5, round(a*24)) % 17)) % 17` — 5 s is 124 frames, i.e. 5.167 s.
85
  """
 
120
 
121
  def load_models() -> str | None:
122
  """Load the denoising half at startup, plus FILM.
 
123
  `MiniMaxH3GeneratorBlocks` declares `transformer`, `vae`, `audio_vae`, the two schedulers and `video_processor`,
124
  so `load_components` fetches exactly those subfolders — `text_encoder/` and `transformer_ref/` are never
125
  touched. Both autoencoders carry `_keep_in_fp32_modules` over every module and stay float32: a bfloat16 audio
 
134
  try:
135
  import torch
136
  from diffusers import ComponentsManager
137
+
138
  from h3_split_blocks import MiniMaxH3GeneratorBlocks
139
+
140
  lower_duration_floor()
 
141
  manager = ComponentsManager()
142
  blocks = MiniMaxH3GeneratorBlocks()
143
+ print(f"[gen] loading {[c.name for c in blocks.expected_components]} from {MODEL_REPO} ...", flush=True)
144
+ pipe = blocks.init_pipeline(MODEL_REPO, components_manager=manager, collection="h3")
 
 
 
 
 
 
 
 
 
 
145
  pipe.load_components(dtype=torch.bfloat16)
 
 
 
 
 
 
146
  pipe.transformer.set_attention_backend(ATTENTION)
147
 
148
  # Still startup, still free: an AoTI package carries no weights and opens its archive lazily inside the GPU
 
280
  seed,
281
  ):
282
  """The only thing on GPU time: the denoise loop, the two decoders and the workflow's post chain.
 
283
  The mp4 is muxed here rather than in the caller: a `@spaces.GPU` return crosses a process boundary by pickling,
284
  and a 2x-interpolated 124-frame clip is several hundred MB of frames against a few MB of h264.
285
  """
 
481
 
482
  load_models()
483
 
484
+ INTRO = """# PlagueKind · MiniMax-H3
 
485
  <div align="center">
486
  <a href="https://huggingface.co/Plaguekind/Minimax-H3" target="_blank" rel="noopener"><strong>[ workflow ]</strong></a> &nbsp;
487
  <a href="https://huggingface.co/MiniMaxAI/MiniMax-H3" target="_blank" rel="noopener"><strong>[ model ]</strong></a> &nbsp;
488
  <a href="https://github.com/PlagueKind/Comfyui-PlagueKind-Nodes" target="_blank" rel="noopener"><strong>[ nodes ]</strong></a>
 
489
  </div>
 
490
  **MiniMax-H3** is a 33B parameter video generation model that produces video and a fully synchronized soundtrack
491
  (ambience, foley, speech) in one pass. **PlagueKind's V1.5 workflow** is a tuning of it: euler on a
492
  `linear_quadratic` sigma grid at 15 steps, FSR **RCAS** sharpening at 0.3, and **FILM** 2x frame interpolation to
493
+ 48 fps. Text-to-video, first frame, last frame, or both.
494
  """
495
 
496
  CSS = """
 
499
  .status p {font-size: 0.8rem; opacity: 0.65; text-align: center;}
500
  """
501
 
502
+ with gr.Blocks(title="PlagueKind · MiniMax-H3") as demo:
503
  gr.Markdown(INTRO)
504
  gr.Markdown(status(), elem_classes="status")
505
 
 
628
  """
629
  `Plaguekind/Minimax-H3` ships no weights — it is a ComfyUI graph over `Comfy-Org/MiniMax-H3`. Its nodes map onto
630
  this Space as:
 
631
  | ComfyUI node | widget | here |
632
  |---|---|---|
633
  | `KSamplerSelect` | `euler` | MiniMax-H3's only sampler; the checkpoint is CFG-distilled, so one forward per step and no negative prompt |
 
639
  | `CreateVideo` | fps `24 * 2` | 48 fps output |
640
  | `RTXVideoSuperResolution` | 2x `ULTRA` | **not reproduced** |
641
  | `PathchSageAttentionKJ` | `sageattn_qk_int8_pv_fp8_cuda++` | cuDNN fused attention |
 
642
  Two deliberate deviations. `RTXVideoSuperResolution` is NVIDIA's NGX super-resolution, shipped as a driver-level
643
  Windows/RTX component with no Linux Python path, so the 2x upscale is missing — pick a larger **Target dimension**
644
  instead of upscaling a small one. And SageAttention's `qk_int8_pv_fp8_cuda++` kernel is not built for this pool's
645
  sm120 cards, so attention runs cuDNN's fused kernel, which is the fastest available here and is numerically the
646
  faithful one (SageAttention is a quantized approximation).
 
647
  One upgrade: the workflow loads `minimax_h3_fl2va_pruned_int8_convrot.safetensors` and a
648
  `qwen3vl_32b_..._int8_convrot` text encoder because that is what fits a consumer card. This Space runs both
649
  **unquantized bfloat16**, off `MiniMaxAI/MiniMax-H3`, with the 62 GiB text encoder in a
 
656
 
657
  if __name__ == "__main__":
658
  # `theme` and `css` belong to `launch()` from Gradio 6.0 on; on `Blocks` they warn and are ignored.
659
+ demo.launch(show_error=True, theme=gr.themes.Citrus(), css=CSS)