DmitryDB commited on
Commit
1baab62
·
verified ·
1 Parent(s): 65637f4

Move dynamic-time separate-QKV checkpoints to dedicated repository

Browse files
FL2VA/SHA256SUMS CHANGED
@@ -1,2 +1 @@
1
  ad0cf8b50ba92068b5a4477527d5da73412a22db99cded35b07195504e78cf6a minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
2
- 495b9d565b17194196646ef39b0c04ac7dde4a8df695b103b3fcbe04b5da00a6 minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors
 
1
  ad0cf8b50ba92068b5a4477527d5da73412a22db99cded35b07195504e78cf6a minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
 
FL2VA/minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:495b9d565b17194196646ef39b0c04ac7dde4a8df695b103b3fcbe04b5da00a6
3
- size 22547374816
 
 
 
 
README.md CHANGED
@@ -17,329 +17,151 @@ tags:
17
  - ref2va
18
  ---
19
 
20
- # MiniMax-H3 INT8 Lean ConvRot
21
-
22
- This repository contains a quality-oriented mixed-precision ComfyUI derivative
23
- of [`MiniMaxAI/MiniMax-H3`](https://huggingface.co/MiniMaxAI/MiniMax-H3).
24
- The released checkpoints cover both the **FL2VA** and **Ref2VA** diffusion
25
- transformers. Each is designed as a first 24 GiB GPU candidate while preserving
26
- more of the original model than the corresponding official pruned INT8
27
- checkpoint. Two layouts are provided: a stock-compatible dense time-table
28
- edition and a patched edition with the original FP32 time MLP and physically
29
- separate Q, K, and V modules.
30
-
31
- These are not official MiniMax or ComfyOrg checkpoints. The `table-*` files use
32
- the standard MiniMax-H3 `adaln_t_table` format and load in an unmodified
33
- ComfyUI. The `dynamic-*-separate-qkv-*` files require the small core patch
34
- included in [`patches/`](patches/).
35
 
36
- ## Included files
37
-
38
- | Path | Purpose |
39
- |---|---|
40
- | [`FL2VA/minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors`](FL2VA/minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors) | Stock-compatible FL2VA diffusion transformer, 20.940 GiB |
41
- | [`Ref2VA/minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors`](Ref2VA/minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors) | Stock-compatible Ref2VA diffusion transformer, 20.940 GiB |
42
- | [`FL2VA/minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors`](FL2VA/minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors) | Patched FL2VA: original FP32 time MLP and separate Q/K/V, 20.999 GiB |
43
- | [`Ref2VA/minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors`](Ref2VA/minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors) | Patched Ref2VA: original FP32 time MLP and separate Q/K/V, 20.999 GiB |
44
- | [`vae/minimax_h3_video_vae_fp16.safetensors`](vae/minimax_h3_video_vae_fp16.safetensors) | Stock ComfyUI MiniMax-H3 visual VAE, FP16, 4.850 GiB |
45
- | [`vae/minimax_h3_audio_vae_fp32.safetensors`](vae/minimax_h3_audio_vae_fp32.safetensors) | Stock ComfyUI MiniMax-H3 stereo audio VAE, FP32, 0.564 GiB |
46
- | [`patches/comfyui-minimax-h3-dynamic-time-separate-qkv.patch`](patches/comfyui-minimax-h3-dynamic-time-separate-qkv.patch) | Required ComfyUI core patch for the two dynamic/separate files |
47
- | [`reports/layer_policy.json`](reports/layer_policy.json) / [`layer_policy_ref2va.json`](reports/layer_policy_ref2va.json) | Exact per-layer precision policies |
48
- | [`reports/validation.json`](reports/validation.json) / [`validation_ref2va.json`](reports/validation_ref2va.json) | Structural, numerical, and CPU-load results |
49
- | [`reports/validation_dynamic_separate_fl2va.json`](reports/validation_dynamic_separate_fl2va.json) / [`validation_dynamic_separate_ref2va.json`](reports/validation_dynamic_separate_ref2va.json) | Bitwise split and dynamic-time validation for the patched files |
50
- | [`reports/loadtest_dynamic_separate_fl2va.json`](reports/loadtest_dynamic_separate_fl2va.json) / [`loadtest_dynamic_separate_ref2va.json`](reports/loadtest_dynamic_separate_ref2va.json) | Full patched-Comfy CPU loader results |
51
- | [`reports/mm_quant_profile_fl2va.json`](reports/mm_quant_profile_fl2va.json) | Row-sampled reconstruction profile for all 200 main matrices |
52
- | [`reports/mm_quant_profile_ref2va.json`](reports/mm_quant_profile_ref2va.json) | Matching Ref2VA reconstruction profile |
53
-
54
- This repository intentionally does **not** include the MiniMax-H3 text encoder.
55
- It is being prepared as a separate repository. ComfyUI does not require the
56
- Diffusers scheduler, tokenizer, processor, or remote-code Python bundles as
57
- separate downloads: a standard workflow needs one selected diffusion model,
58
- the two included VAEs, and a compatible MiniMax-H3 text encoder.
59
-
60
- ## Shared quantization policy
61
-
62
- The original FL2VA and Ref2VA Diffusers shards each contain 50 transformer
63
- blocks with separate Q, K, and V tensors. Both release layouts use the same
64
- quality21 precision policy:
65
-
66
- - swaps the two `fc1` halves from `[value, gate]` to `[gate, value]`;
67
- - stores 170 selected main attention/MLP matrices as INT8 ConvRot with group
68
- size 256 and per-row FP32 scales;
69
- - keeps 30 high-error main matrices as exact BF16 copies;
70
- - keeps the two-block token refiner, norms, Q/K norms, and condition projection
71
- at their source precision;
72
- - keeps patch projections and video/audio output heads in source FP32;
73
- - replaces only the redundant input width of the 51 large AdaLN projections,
74
- while keeping every block and final AdaLN projection separate in FP32.
75
-
76
- The stock-compatible files additionally pack attention rows as global
77
- `cat(Q,K,V)` and evaluate the original FP32 time embedder offline into a dense
78
- FP32 table with 4,097 rows and 16 coordinates. Each stock-compatible checkpoint
79
- contains 872 tensor entries: 170 INT8 weights, 170 quantization configuration
80
- blobs, 250 BF16 entries, and 282 FP32 entries.
81
-
82
- ## Patched dynamic-time, separate-QKV edition
83
-
84
- The two `dynamic-k16-separate-qkv` files retain the original four FP32 time-MLP
85
- tensors:
86
 
87
- ```text
88
- 256 -> 5,376 -> 2,688
89
- full_t = SiLU(original_time_embedder(t))
90
- coords = (full_t - mean) @ basis[2,688 x 16]
91
- AdaLN_i(t) = separate_linear_i(coords)
92
- ```
93
 
94
- The 16-dimensional dynamic basis compresses only the shared input subspace of
95
- the 51 very wide AdaLN projections. It does not replace the time MLP with an
96
- interpolation table, and it does not merge the 51 per-block/final AdaLN layers.
 
 
97
 
98
- Q, K, and V are also separate modules all the way through loading and forward:
99
-
100
- - 50 main blocks contain independent INT8 ConvRot `q_proj`, `k_proj`, and
101
- `v_proj` weights, scales, and descriptors;
102
- - both token-refiner blocks contain independent BF16 Q, K, and V projections;
103
- - the checkpoint contains no `qkv_proj` key;
104
- - the patch performs three projection calls rather than concatenating the
105
- tensors at load time.
106
-
107
- This changes storage structure, not the quantization values. All 156 resulting
108
- Q/K/V projection tensors are bit-identical to the corresponding contiguous
109
- thirds of the validated fused release. Per-row scales were already independent,
110
- so splitting QKV alone is not claimed as a quality improvement. It may be
111
- slower than fused QKV because the current ConvRot path can rotate the same input
112
- three times and launches three projections. GPU speed and peak VRAM have not
113
- yet been measured.
114
-
115
- Each patched checkpoint contains 1,181 tensor entries and 270 INT8 ConvRot
116
- modules. The total quantized QKV payload is unchanged; the approximately
117
- 0.059 GiB size increase comes primarily from restoring the original FP32 time
118
- MLP.
119
 
120
- ## Precision policy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
- Every DiT block has four main matrices: QKV, attention output, MLP `fc1`, and
123
- MLP `fc2`, for 200 matrices total per checkpoint. The `quality21` profile stores
124
- 170 in INT8 and 30 in BF16.
125
 
126
- The BF16 island is:
 
 
 
 
127
 
128
- - attention output projections in blocks 0–15, 17, 19, 20, 27, 38, 43–47,
129
- and 49 (27 matrices);
130
- - MLP `fc2` in blocks 39, 45, and 49 (3 matrices).
 
 
131
 
132
- These were selected from deterministic reconstruction audits using 64 output
133
- rows and every input column of each matrix. Ref2VA independently selected the
134
- same 30-layer set as FL2VA, with a per-layer error correlation of `0.999676`.
135
- Attention output projections were the most error-prone family and are
136
- considerably cheaper to retain in BF16 than QKV or `fc1`. The exact
137
- machine-readable lists are in [`reports/layer_policy.json`](reports/layer_policy.json)
138
- and [`reports/layer_policy_ref2va.json`](reports/layer_policy_ref2va.json).
139
 
140
- ## Stock-compatible time conditioning
141
 
142
- The time embedder maps the current diffusion timestep/noise level to a
143
- 2,688-dimensional signal. Every transformer block turns this signal into its
144
- own AdaLN shifts, scales, and gates, telling the network which denoising stage
145
- is being evaluated.
146
 
147
- At inference this frozen mapping traces a smooth one-dimensional curve because
148
- its input is a single scalar timestep. This release evaluates the original FP32
149
- time MLP offline, projects the curve onto a shared 16-dimensional basis, and
150
- stores those coordinates at 4,097 evenly spaced points:
151
 
152
  ```text
153
- u(t) = SiLU(original_time_embedder(t))
154
- table[j] = project(u(j / 4096))
155
- AdaLN_i(t) = linear_i(interpolate(table, t))
156
  ```
157
 
158
- Each of the 50 block AdaLN projections and the final AdaLN projection remains a
159
- different FP32 linear layer. Only their shared input curve is compressed.
160
 
161
- On 19 validation timesteps, the relative AdaLN output error against the raw HF
162
- weights was `3.04e-7` to `3.82e-7` for FL2VA and `3.42e-7` to `4.46e-7` for
163
- Ref2VA across blocks 0, 24, 49, and the final layer. For context, the official
164
- pruned rank-8 FP16 tables measured about `0.016%–0.021%` on the same
165
- projections. This comparison covers only the time/AdaLN path, not end-to-end
166
- generation quality.
167
 
168
- ## Comparison with official ComfyOrg files
 
 
 
 
 
 
 
 
169
 
170
- | Checkpoint | Size | Main matrices | Time/AdaLN representation |
171
- |---|---:|---:|---|
172
- | Official regular INT8 ConvRot | about 31.70 GiB | 200 INT8 | full AdaLN weights |
173
- | Official pruned INT8 ConvRot | 19.530 GiB | 200 INT8 | FP16 rank-8 table |
174
- | Each stock `table-k16 quality21` release | 20.940 GiB | 170 INT8 + 30 BF16 | FP32 rank-16 table, 4,097 rows |
175
- | Each patched `dynamic-k16 separate-QKV quality21` release | 20.999 GiB | Same 170 semantic main matrices; 270 physical INT8 modules | Original FP32 time MLP + FP32 dynamic rank-16 basis |
176
-
177
- Each stock file is about 1.410 GiB (7.22%) larger than its official pruned INT8
178
- counterpart. The patched edition adds about 0.059 GiB over the stock quality21
179
- file by restoring the original FP32 time MLP. The remaining added space is
180
- intentionally spent on a higher-precision time representation and a BF16 island
181
- for the most sensitive main matrices.
182
-
183
- The full 200-matrix sampled reconstruction proxies produced:
184
-
185
- | Variant | Official-style absmax INT8 | This profile |
186
- |---|---:|---:|
187
- | FL2VA | 0.9345% | 0.7639% |
188
- | Ref2VA | 0.9345% | 0.7639% |
189
-
190
- For these profiles, selected BF16 matrices count as zero storage reconstruction
191
- error. On the remaining 170 INT8 matrices, searched scales reduced the mean
192
- proxy from about 0.9109% to 0.8987%. The approximately 18.25% overall reduction
193
- is a sampled weight reconstruction result, **not** a perceptual or generation
194
- benchmark.
195
-
196
- ## ComfyUI installation
197
-
198
- 1. Use a current ComfyUI checkout with MiniMax-H3 and native INT8 ConvRot
199
- support. The stock table files were CPU-load-tested on a clean, unmodified
200
- ComfyUI commit `14b05228cef127ce529bc0c08660770d4af3e9a8`.
201
- 2. If using a `dynamic-k16-separate-qkv` file, apply the included patch from the
202
- root of that ComfyUI checkout. This is not required for the `table-k16` files:
203
-
204
- ```powershell
205
- git apply --check C:\path\to\comfyui-minimax-h3-dynamic-time-separate-qkv.patch
206
- git apply C:\path\to\comfyui-minimax-h3-dynamic-time-separate-qkv.patch
207
- ```
208
-
209
- The patch was verified with `git apply --check` against commit `14b05228`.
210
- It updates MiniMax-H3 model detection/runtime and makes partial-offload
211
- bookkeeping tolerate packed INT8 layers without a regular `.weight` field.
212
- 3. Place the FL2VA and/or Ref2VA safetensors file in
213
- `ComfyUI/models/diffusion_models/`. FL2VA is for text/image first-last-frame
214
- workflows; Ref2VA is for reference image/video/audio workflows.
215
- 4. Place both files from `vae/` in `ComfyUI/models/vae/`.
216
- 5. Load one diffusion checkpoint and both VAEs with the standard loaders in the
217
- matching MiniMax-H3 FL2VA or Ref2VA workflow. Supply a compatible text
218
- encoder separately.
219
 
220
  ```text
221
- ComfyUI/models/
222
- |-- diffusion_models/
223
- | `-- <one FL2VA or Ref2VA table/dynamic-separate checkpoint>
224
- |-- vae/
225
- | |-- minimax_h3_video_vae_fp16.safetensors
226
- | `-- minimax_h3_audio_vae_fp32.safetensors
227
- `-- text_encoders/
228
- `-- <MiniMax-H3 text encoder from its separate repository>
229
  ```
230
 
231
- No custom node is required. Only the two explicitly named dynamic/separate
232
- checkpoints require the included core patch.
233
-
234
- ## Validation status
235
-
236
- Completed:
237
-
238
- - safetensors structure, shapes, dtypes, and all 170 ConvRot descriptors;
239
- - SHA-256: FL2VA
240
- `ad0cf8b50ba92068b5a4477527d5da73412a22db99cded35b07195504e78cf6a`;
241
- Ref2VA
242
- `f4b2a8b4a53446f5d696a39deb693b09ac7ce37013793a8b19340644e38b154f`;
243
- - BF16 main island: 30/30 matrices bitwise equal to raw HF;
244
- - FL2VA: 871/871 tensors outside the time representation preserved bit-for-bit
245
- during the final stock-table conversion;
246
- - Ref2VA: 258/258 direct source-copy tensors (4,146,503,680 bytes) bitwise equal
247
- to raw HF;
248
- - FP32 table interpolation checked at every one of the 4,096 interval
249
- midpoints; FL2VA grid rows reproduced exactly, and the independent Ref2VA
250
- FP64-SVD rebuild differed by at most `4.55e-13`;
251
- - full CPU load through a clean, unmodified ComfyUI as
252
- `ModelPatcher -> MiniMaxH3Model`, table mode `(4097, 16)`, for both diffusion
253
- checkpoints;
254
- - patched editions: 1,181 keys, 270 INT8 ConvRot descriptors at group size 256,
255
- zero fused-QKV keys, and all 156 Q/K/V projection tensors bitwise equal to
256
- the corresponding thirds of the stock quality21 checkpoints;
257
- - patched editions: all 719 common non-QKV tensors bitwise equal to their stock
258
- quality21 counterparts and all four FP32 time-MLP tensors bitwise equal to
259
- the selected raw HF variant;
260
- - patched FL2VA dynamic coordinates reproduce the released 4,097-row table
261
- bit-for-bit; the independently reconstructed Ref2VA dynamic path differs by
262
- `2.89e-7` relative (`1.31e-6` maximum absolute coordinate error);
263
- - patched AdaLN output relative errors on 19 timesteps are `2.85e-7` to
264
- `3.32e-7` for FL2VA and `2.96e-7` to `3.31e-7` for Ref2VA across blocks
265
- 0, 24, 49, and the final layer;
266
- - both patched files fully load on CPU through the patched ComfyUI as
267
- `MiniMaxH3Model`, with dynamic basis enabled, table mode disabled, and
268
- independent Q/K/V modules in both the main stack and token refiner;
269
- - patched SHA-256: FL2VA
270
- `495b9d565b17194196646ef39b0c04ac7dde4a8df695b103b3fcbe04b5da00a6`;
271
- Ref2VA
272
- `82d16de12bee9d006c83c80b8843f2bb7e05cd25320724113ca7d128c6be6a04`;
273
- - both companion VAE files fully loaded on CPU through the same clean ComfyUI:
274
- `MiniMaxH3VideoVAE` in FP16 with native internal tiling, and
275
- `MiniMaxH3AudioVAE` in FP32 with 32 kHz stereo output;
276
- - companion VAE SHA-256 checksums match the official Comfy-Org repackaged files:
277
- `7c1f131492e7eddacaac9069a61b81bdd39de5cc96561e677c5eab1cdce5e522`
278
- (video) and
279
- `8e505d95dd1561d47abd43d4238fd40d9bb1ae9e147ed0a4cba778d76ae4db48`
280
- (audio).
281
-
282
- Not completed at release time:
283
-
284
- - CUDA/GPU loading of these exact checkpoints;
285
- - peak VRAM measurement for a target resolution and frame count;
286
- - end-to-end FL2VA or Ref2VA generation;
287
- - same-seed visual/audio A/B against BF16 and official pruned variants.
288
-
289
- Therefore, 20.940 GiB (stock table) or 20.999 GiB (patched dynamic/separate) is
290
- the on-disk tensor payload, not a promise that every workflow will remain under
291
- 24 GiB. Activations, runtime buffers, resolution, frame count, batch size, and
292
- offloading policy determine peak VRAM.
293
-
294
- ## Conversion provenance
295
-
296
- The converter reads the original top-level `transformer/` or `transformer_ref/`
297
- Diffusers shards from MiniMaxAI directly; it does not create a 61+ GiB merged
298
- BF16 intermediate. The nested task-specific transformer folders were not used
299
- because their already-packed QKV is head-major. The stock-compatible edition
300
- uses global `cat(Q,K,V)` packing expected by unmodified ComfyUI; the patched
301
- edition retains the top-level source's separate Q, K, and V ordering.
302
-
303
- The official FL2VA and Ref2VA pruned files,
304
- [`minimax_h3_fl2va_pruned_int8_convrot.safetensors`](https://huggingface.co/Comfy-Org/MiniMax-H3/blob/main/diffusion_models/minimax_h3_fl2va_pruned_int8_convrot.safetensors)
305
- and
306
- [`minimax_h3_ref2va_pruned_int8_convrot.safetensors`](https://huggingface.co/Comfy-Org/MiniMax-H3/blob/main/diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors),
307
- were used only as layout references and as the sources of the corresponding
308
- FP32 `rope.inv_freq` tensors absent from the raw Diffusers state dicts.
309
-
310
- The two files under `vae/` are unmodified, bit-identical copies of the standard
311
- [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3/tree/main/vae)
312
- repackages. The original remote-code VAE bundles are more complicated: the
313
- visual VAE constructs a causal 3D-CNN encoder and 36-layer ViT decoder from
314
- Python and configuration files, while the audio VAE constructs a DAC-lineage
315
- encoder and BigVGAN decoder. ComfyUI implements both architectures natively.
316
- The single-file visual repack casts all 560 source weight tensors from FP32 to
317
- FP16 and embeds the latent statistics; the audio repack preserves 743 tensors,
318
- folds 172 weight-normalized pairs into ordinary FP32 weights, and embeds its
319
- latent statistics. No remote Python code or external VAE config is required.
320
-
321
- ## Limitations and intended use
322
-
323
- This release is intended for research and local ComfyUI inference. It is a
324
- new, structurally validated operating point, not a completed quality benchmark.
325
- Both variants were profiled separately. Their independently selected
326
- quality21 BF16 islands are identical, but this does not establish perceptual
327
- quality without end-to-end A/B generation. The separate-QKV runtime also trades
328
- the fused projection for three independent ConvRot calls, so it should be
329
- treated as an experimental quality/architecture variant until GPU speed and
330
- VRAM are measured.
331
 
332
  ## License
333
 
334
- This derivative is distributed under the
335
- [MiniMax H3 Community License Agreement](LICENSE). The license limits use and
336
- distribution to its defined Applicable Territory, excludes the European Union,
337
- United Kingdom, Republic of Korea, and United States, and includes additional
338
- use and redistribution conditions. Read the full license and [`NOTICE`](NOTICE)
339
- before downloading, using, or redistributing these files.
340
 
341
  ## Links
342
 
343
- - [Original MiniMax-H3 repository](https://huggingface.co/MiniMaxAI/MiniMax-H3)
 
344
  - [Official ComfyOrg MiniMax-H3 files](https://huggingface.co/Comfy-Org/MiniMax-H3)
345
- - [ComfyUI](https://github.com/Comfy-Org/ComfyUI)
 
17
  - ref2va
18
  ---
19
 
20
+ # MiniMax-H3 INT8 Lean ConvRot — Stock ComfyUI Edition
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ This repository contains stock-compatible, quality-oriented mixed-precision
23
+ INT8 ConvRot conversions of
24
+ [`MiniMaxAI/MiniMax-H3`](https://huggingface.co/MiniMaxAI/MiniMax-H3), plus the
25
+ standard MiniMax-H3 visual and audio VAEs. FL2VA and Ref2VA are separate because
26
+ their diffusion-transformer weights are task-specific.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ These are community derivatives, not official MiniMax or ComfyOrg checkpoints.
29
+ The diffusion checkpoints use the standard MiniMax-H3 `adaln_t_table` layout
30
+ and load in unmodified ComfyUI. No core patch or custom node is required.
 
 
 
31
 
32
+ The experimental edition with the original FP32 time MLP and physically
33
+ separate Q/K/V projections has moved to
34
+ [`DmitryDB/MiniMax-H3-INT8-Lean-ConvRot-Dynamic-Time-Separate-QKV`](https://huggingface.co/DmitryDB/MiniMax-H3-INT8-Lean-ConvRot-Dynamic-Time-Separate-QKV).
35
+ It requires a ComfyUI core patch and is intentionally kept separate to avoid
36
+ confusion.
37
 
38
+ ## Included files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ | Path | Purpose |
41
+ |---|---|
42
+ | `FL2VA/minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors` | Stock-compatible FL2VA diffusion transformer, 20.940 GiB |
43
+ | `Ref2VA/minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors` | Stock-compatible Ref2VA diffusion transformer, 20.940 GiB |
44
+ | `vae/minimax_h3_video_vae_fp16.safetensors` | Stock ComfyUI MiniMax-H3 visual VAE, FP16, 4.850 GiB |
45
+ | `vae/minimax_h3_audio_vae_fp32.safetensors` | Stock ComfyUI MiniMax-H3 stereo audio VAE, FP32, 0.564 GiB |
46
+ | `reports/validation.json` / `validation_ref2va.json` | Structural, table-error, and clean-Comfy CPU-load validation |
47
+ | `reports/layer_policy.json` / `layer_policy_ref2va.json` | Exact BF16/INT8 layer policy |
48
+ | `reports/mm_quant_profile_fl2va.json` / `mm_quant_profile_ref2va.json` | Row-sampled reconstruction profiles |
49
+
50
+ The MiniMax-H3 Qwen3-VL text encoder is not included in this repository. A
51
+ standard workflow needs one selected diffusion checkpoint, both VAEs, and a
52
+ compatible MiniMax-H3 text encoder installed separately.
53
+
54
+ ## Quantization policy
55
+
56
+ The original FL2VA and Ref2VA transformers each contain 50 main transformer
57
+ blocks. Each block has four attention projections and two MLP matrices, for 300
58
+ main matrices. The quality21 policy keeps the high-risk matrices in their
59
+ source precision and compresses the rest:
60
+
61
+ - 170 main matrices use INT8 ConvRot with Hadamard group size 256;
62
+ - 30 high-risk main matrices remain BF16;
63
+ - token-refiner attention/MLP weights remain BF16;
64
+ - normalization tensors remain BF16;
65
+ - patch projections and video/audio output heads retain source FP32;
66
+ - 51 AdaLN projections are represented through separate FP32 rank-16 table
67
+ projections.
68
+
69
+ Q, K, and V originate as separate Diffusers tensors. For stock ComfyUI they are
70
+ packed as global `cat(Q,K,V)` into `qkv_proj`, which is the layout expected by
71
+ the unmodified runtime.
72
+
73
+ The BF16 islands were selected by deterministic row-sampled reconstruction
74
+ analysis rather than by a blanket first/last-block rule. FL2VA and Ref2VA were
75
+ profiled independently and selected the same 30 matrices.
76
+
77
+ ## Time conditioning
78
+
79
+ The raw model uses a wide FP32 time MLP followed by 51 large AdaLN projections.
80
+ The release samples the original FP32 time path on 4,097 points, derives a
81
+ shared 16-dimensional basis, and stores one independent FP32 projection for
82
+ every transformer block plus the final layer.
83
+
84
+ The saved `adaln_t_table` has shape `[4097, 16]`. ComfyUI linearly interpolates
85
+ the 16 coordinates and applies the per-layer projection. On 19 validation
86
+ timesteps, relative AdaLN output error against the raw HF dynamic path was:
87
+
88
+ - FL2VA: about `3.04e-7` to `3.82e-7`;
89
+ - Ref2VA: about `3.42e-7` to `4.46e-7`.
90
+
91
+ This is substantially more accurate than using a direct wide cached table at
92
+ the same grid density while remaining compatible with stock ComfyUI.
93
 
94
+ ## Comparison with official ComfyOrg files
 
 
95
 
96
+ | Checkpoint | Size | Main matrices | Time/AdaLN representation |
97
+ |---|---:|---:|---|
98
+ | Official full INT8 ConvRot | 27.557 GiB | 300 INT8 | Wide FP32 AdaLN table |
99
+ | Official pruned INT8 ConvRot | 19.530 GiB | 200 INT8 | Wide FP32 AdaLN table |
100
+ | This stock quality21 edition | 20.940 GiB | 170 INT8 + 30 BF16 | FP32 `[4097,16]` table + 51 projections |
101
 
102
+ Each file is about 1.410 GiB larger than its official pruned INT8 counterpart.
103
+ The additional space is intentionally spent on the rank-16 time representation
104
+ and BF16 islands. The sampled weight-reconstruction proxy improved from about
105
+ `0.9345%` mean relative error for official-style absmax INT8 to about `0.7639%`
106
+ for this mixed profile. This is a proxy, not an end-to-end perceptual result.
107
 
108
+ ## Installation
 
 
 
 
 
 
109
 
110
+ Place one or both diffusion checkpoints in:
111
 
112
+ ```text
113
+ ComfyUI/models/diffusion_models/
114
+ ```
 
115
 
116
+ Place both VAE files in:
 
 
 
117
 
118
  ```text
119
+ ComfyUI/models/vae/
 
 
120
  ```
121
 
122
+ Install a compatible MiniMax-H3 Qwen3-VL text encoder separately, then use the
123
+ matching stock MiniMax-H3 FL2VA or Ref2VA workflow.
124
 
125
+ ## Validation performed
 
 
 
 
 
126
 
127
+ - safetensors structure, shapes, and dtypes;
128
+ - 170/170 INT8 ConvRot blobs with group size 256;
129
+ - all 30 BF16 main matrices present according to the published policy;
130
+ - non-quantized source tensors compared against the raw MiniMax-H3 shards;
131
+ - FP32 rank-16 time tables and 51 projections checked numerically;
132
+ - full CPU load through clean, unmodified ComfyUI commit `14b05228` as
133
+ `ModelPatcher -> MiniMaxH3Model`, table mode enabled and no dynamic time MLP;
134
+ - both VAE files fully loaded through the same clean ComfyUI;
135
+ - VAE checksums match the standard ComfyOrg repackaged files.
136
 
137
+ SHA-256:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  ```text
140
+ ad0cf8b50ba92068b5a4477527d5da73412a22db99cded35b07195504e78cf6a FL2VA/minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
141
+ f4b2a8b4a53446f5d696a39deb693b09ac7ce37013793a8b19340644e38b154f Ref2VA/minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
142
+ 7c1f131492e7eddacaac9069a61b81bdd39de5cc96561e677c5eab1cdce5e522 vae/minimax_h3_video_vae_fp16.safetensors
143
+ 8e505d95dd1561d47abd43d4238fd40d9bb1ae9e147ed0a4cba778d76ae4db48 vae/minimax_h3_audio_vae_fp32.safetensors
 
 
 
 
144
  ```
145
 
146
+ ## Validation not yet completed
147
+
148
+ - GPU loading and peak-VRAM measurement;
149
+ - fixed-seed end-to-end FL2VA/Ref2VA generation;
150
+ - video and audio A/B quality comparison against BF16 and official INT8.
151
+
152
+ The 20.940 GiB file size is a disk-weight target, not a guarantee that every
153
+ 24 GiB workflow will fit. Runtime memory also depends on activation size,
154
+ resolution, frame count, attention implementation, and offload settings.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  ## License
157
 
158
+ MiniMax H3 is distributed under the MiniMax H3 Community License Agreement.
159
+ Read `LICENSE` before using or redistributing these derivatives. The
160
+ modification summary is provided in `NOTICE`.
 
 
 
161
 
162
  ## Links
163
 
164
+ - [Original MiniMax-H3](https://huggingface.co/MiniMaxAI/MiniMax-H3)
165
+ - [Experimental dynamic-time / separate-QKV edition](https://huggingface.co/DmitryDB/MiniMax-H3-INT8-Lean-ConvRot-Dynamic-Time-Separate-QKV)
166
  - [Official ComfyOrg MiniMax-H3 files](https://huggingface.co/Comfy-Org/MiniMax-H3)
167
+ - [ComfyUI](https://github.com/comfyanonymous/ComfyUI)
Ref2VA/SHA256SUMS CHANGED
@@ -1,2 +1 @@
1
  f4b2a8b4a53446f5d696a39deb693b09ac7ce37013793a8b19340644e38b154f minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
2
- 82d16de12bee9d006c83c80b8843f2bb7e05cd25320724113ca7d128c6be6a04 minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors
 
1
  f4b2a8b4a53446f5d696a39deb693b09ac7ce37013793a8b19340644e38b154f minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors
 
Ref2VA/minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:82d16de12bee9d006c83c80b8843f2bb7e05cd25320724113ca7d128c6be6a04
3
- size 22547376168
 
 
 
 
patches/comfyui-minimax-h3-dynamic-time-separate-qkv.patch DELETED
@@ -1,220 +0,0 @@
1
- diff --git a/comfy/ldm/minimax/model.py b/comfy/ldm/minimax/model.py
2
- --- a/comfy/ldm/minimax/model.py
3
- +++ b/comfy/ldm/minimax/model.py
4
- @@ -143,19 +143,29 @@ def rope_rotation_table(angles, dtype):
5
-
6
-
7
- class Attention(nn.Module):
8
- - def __init__(self, hidden, heads, head_dim, eps, dtype=None, device=None, operations=None):
9
- + def __init__(self, hidden, heads, head_dim, eps, separate_qkv=False,
10
- + dtype=None, device=None, operations=None):
11
- super().__init__()
12
- self.heads = heads
13
- self.head_dim = head_dim
14
- + self.separate_qkv = separate_qkv
15
- inner = heads * head_dim
16
- - self.qkv_proj = operations.Linear(hidden, inner * 3, bias=False, dtype=dtype, device=device)
17
- + if separate_qkv:
18
- + self.q_proj = operations.Linear(hidden, inner, bias=False, dtype=dtype, device=device)
19
- + self.k_proj = operations.Linear(hidden, inner, bias=False, dtype=dtype, device=device)
20
- + self.v_proj = operations.Linear(hidden, inner, bias=False, dtype=dtype, device=device)
21
- + else:
22
- + self.qkv_proj = operations.Linear(hidden, inner * 3, bias=False, dtype=dtype, device=device)
23
- self.q_norm = operations.RMSNorm(head_dim, eps=eps, dtype=dtype, device=device)
24
- self.k_norm = operations.RMSNorm(head_dim, eps=eps, dtype=dtype, device=device)
25
- self.out_proj = operations.Linear(inner, hidden, bias=False, dtype=dtype, device=device)
26
-
27
- def forward(self, x, rope_freqs=None, transformer_options={}):
28
- s = x.shape[0]
29
- - q, k, v = self.qkv_proj(x).split(self.heads * self.head_dim, dim=-1)
30
- + if self.separate_qkv:
31
- + q, k, v = self.q_proj(x), self.k_proj(x), self.v_proj(x)
32
- + else:
33
- + q, k, v = self.qkv_proj(x).split(self.heads * self.head_dim, dim=-1)
34
- v = v.view(s, self.heads, self.head_dim)
35
- if rope_freqs is not None:
36
- # fused per-head RMSNorm + partial split-half rope, in place on the qkv buffer
37
- @@ -224,11 +234,13 @@ def _mod_gate(x, gate, other, segments):
38
-
39
-
40
- class RefinerBlock(nn.Module):
41
- - def __init__(self, hidden, heads, head_dim, ffn, eps, qk_eps, dtype=None, device=None, operations=None):
42
- + def __init__(self, hidden, heads, head_dim, ffn, eps, qk_eps, separate_qkv=False,
43
- + dtype=None, device=None, operations=None):
44
- super().__init__()
45
- self.norm1 = operations.RMSNorm(hidden, eps=eps, dtype=dtype, device=device)
46
- self.norm2 = operations.RMSNorm(hidden, eps=eps, dtype=dtype, device=device)
47
- - self.attn = Attention(hidden, heads, head_dim, qk_eps, dtype=dtype, device=device, operations=operations)
48
- + self.attn = Attention(hidden, heads, head_dim, qk_eps, separate_qkv=separate_qkv,
49
- + dtype=dtype, device=device, operations=operations)
50
- self.mlp = MLP(hidden, ffn, dtype=dtype, device=device, operations=operations)
51
-
52
- def forward(self, x, transformer_options={}):
53
- @@ -239,10 +251,11 @@ class RefinerBlock(nn.Module):
54
-
55
- class TokenRefiner(nn.Module):
56
- def __init__(self, num_layers, hidden, heads, head_dim, ffn, eps, qk_eps, final_eps,
57
- - dtype=None, device=None, operations=None):
58
- + separate_qkv=False, dtype=None, device=None, operations=None):
59
- super().__init__()
60
- self.blocks = nn.ModuleList([
61
- - RefinerBlock(hidden, heads, head_dim, ffn, eps, qk_eps, dtype=dtype, device=device, operations=operations)
62
- + RefinerBlock(hidden, heads, head_dim, ffn, eps, qk_eps, separate_qkv=separate_qkv,
63
- + dtype=dtype, device=device, operations=operations)
64
- for _ in range(num_layers)])
65
- self.final_norm = operations.RMSNorm(hidden, eps=final_eps, dtype=dtype, device=device)
66
-
67
- @@ -254,11 +267,13 @@ class TokenRefiner(nn.Module):
68
-
69
- class DiTBlock(nn.Module):
70
- def __init__(self, hidden, heads, head_dim, ffn, t_dim, eps, qk_eps,
71
- - apply_silu=True, adaln_dtype=None, dtype=None, device=None, operations=None):
72
- + apply_silu=True, adaln_dtype=None, separate_qkv=False,
73
- + dtype=None, device=None, operations=None):
74
- super().__init__()
75
- self.norm1 = operations.RMSNorm(hidden, eps=eps, dtype=dtype, device=device)
76
- self.norm2 = operations.RMSNorm(hidden, eps=eps, dtype=dtype, device=device)
77
- - self.attn = Attention(hidden, heads, head_dim, qk_eps, dtype=dtype, device=device, operations=operations)
78
- + self.attn = Attention(hidden, heads, head_dim, qk_eps, separate_qkv=separate_qkv,
79
- + dtype=dtype, device=device, operations=operations)
80
- self.mlp = MLP(hidden, ffn, dtype=dtype, device=device, operations=operations)
81
- self.adaln_proj = AdalnProj(t_dim, hidden, 6, 3, apply_silu=apply_silu,
82
- dtype=adaln_dtype if adaln_dtype is not None else dtype,
83
- @@ -416,7 +431,7 @@ class MiniMaxH3Model(nn.Module):
84
- timestep_input_dim=256, time_embed_hidden_size=5376, time_embed_dim=2688,
85
- rope_inv_freq_len=16, norm_eps=1e-5, qk_norm_eps=1e-5, final_norm_eps=1e-5,
86
- sigma_shift_video=12.0, sigma_shift_audio=3.0,
87
- - adaln_curve_grid=None,
88
- + adaln_curve_grid=None, adaln_curve_basis_dim=None, separate_qkv=False,
89
- image_model=None, dtype=None, device=None, operations=None, **kwargs):
90
- super().__init__()
91
- self.dtype = dtype
92
- @@ -426,30 +441,43 @@ class MiniMaxH3Model(nn.Module):
93
- self.audio_latents_dim = audio_latents_dim
94
- self.sigma_shift_video = sigma_shift_video
95
- self.sigma_shift_audio = sigma_shift_audio
96
- - self.use_adaln_curves = adaln_curve_grid is not None
97
- - # curve-form checkpoints replace the time embedder and full-width adaln weights with a small shared basis of the time-embedding curve
98
- + self.separate_qkv = separate_qkv
99
- + if adaln_curve_grid is not None and adaln_curve_basis_dim is not None:
100
- + raise ValueError("adaln table and dynamic basis modes are mutually exclusive")
101
- + self.use_adaln_table = adaln_curve_grid is not None
102
- + self.use_adaln_basis = adaln_curve_basis_dim is not None
103
- + self.use_adaln_curves = self.use_adaln_table or self.use_adaln_basis
104
- + # Curve checkpoints replace full-width adaLN weights with projections
105
- + # over a small shared basis. Table mode also replaces the time MLP;
106
- + # dynamic-basis mode retains it and projects its exact fp32 output.
107
- curve = {"apply_silu": not self.use_adaln_curves,
108
- "adaln_dtype": torch.float32 if self.use_adaln_curves else dtype}
109
- + adaln_dim = adaln_curve_basis_dim if self.use_adaln_basis else time_embed_dim
110
- video_patch_dim = latents_dim * self.patch_size[0] * self.patch_size[1] * self.patch_size[2]
111
-
112
- self.video_patch_proj = operations.Linear(video_patch_dim, hidden_size, bias=True, dtype=torch.float32, device=device)
113
- self.audio_patch_proj = operations.Linear(audio_latents_dim, hidden_size, bias=True, dtype=torch.float32, device=device)
114
- self.condition_proj = operations.Linear(text_dim, hidden_size, bias=True, dtype=dtype, device=device)
115
- - if self.use_adaln_curves:
116
- + if self.use_adaln_table:
117
- self.register_buffer("adaln_t_table", torch.empty(adaln_curve_grid, time_embed_dim, dtype=torch.float32))
118
- else:
119
- self.time_embedder = TimeEmbedder(timestep_input_dim, time_embed_hidden_size, time_embed_dim,
120
- dtype=torch.float32, device=device, operations=operations)
121
- + if self.use_adaln_basis:
122
- + self.register_buffer("adaln_curve_basis", torch.empty(time_embed_dim, adaln_curve_basis_dim, dtype=torch.float32))
123
- + self.register_buffer("adaln_curve_mean", torch.empty(time_embed_dim, dtype=torch.float32))
124
- self.rope = nn.Module()
125
- self.rope.register_buffer("inv_freq", torch.empty(rope_inv_freq_len, dtype=torch.float32))
126
- self.token_refiner = TokenRefiner(token_refiner_num_layers, hidden_size, num_attention_heads,
127
- attention_head_dim, ffn_hidden_size, norm_eps, qk_norm_eps,
128
- - final_norm_eps, dtype=dtype, device=device, operations=operations)
129
- + final_norm_eps, separate_qkv=separate_qkv,
130
- + dtype=dtype, device=device, operations=operations)
131
- self.blocks = nn.ModuleList([
132
- DiTBlock(hidden_size, num_attention_heads, attention_head_dim, ffn_hidden_size,
133
- - time_embed_dim, norm_eps, qk_norm_eps, **curve, dtype=dtype, device=device, operations=operations)
134
- + adaln_dim, norm_eps, qk_norm_eps, separate_qkv=separate_qkv,
135
- + **curve, dtype=dtype, device=device, operations=operations)
136
- for _ in range(num_layers)])
137
- - self.final_layer = FinalLayer(hidden_size, time_embed_dim, video_patch_dim, audio_latents_dim,
138
- + self.final_layer = FinalLayer(hidden_size, adaln_dim, video_patch_dim, audio_latents_dim,
139
- final_norm_eps, **curve, dtype=dtype, device=device, operations=operations)
140
-
141
- def preprocess_text_embeds(self, text_states):
142
- @@ -599,12 +627,19 @@ class MiniMaxH3Model(nn.Module):
143
- aoff += n
144
-
145
- t_vals = torch.tensor(unique_t, dtype=torch.float32, device=device)
146
- - if self.use_adaln_curves:
147
- + if self.use_adaln_table:
148
- # adaln projections consume interpolated coordinates of the time-embedding curve
149
- table = comfy.model_management.cast_to(self.adaln_t_table, device=device)
150
- pos = t_vals.clamp(0.0, 1.0) * (table.shape[0] - 1) # t in [0,1] -> fractional grid index, out-of-range t clamps to the curve ends
151
- i0 = pos.floor().long().clamp(max=table.shape[0] - 2) # lower grid row, max-clamp keeps t=1.0 on the last interval instead of reading past the table
152
- t_emb = torch.lerp(table[i0], table[i0 + 1], (pos - i0).unsqueeze(1)) # blend the two rows by the fractional part
153
- + elif self.use_adaln_basis:
154
- + # Preserve the original fp32 time MLP and remove only the redundant
155
- + # directions that its smooth one-dimensional output curve never uses.
156
- + full_t_emb = nn.functional.silu(self.time_embedder(t_vals))
157
- + basis = comfy.model_management.cast_to(self.adaln_curve_basis, device=device)
158
- + mean = comfy.model_management.cast_to(self.adaln_curve_mean, device=device)
159
- + t_emb = (full_t_emb - mean) @ basis
160
- else:
161
- t_emb = self.time_embedder(t_vals).to(dtype)
162
-
163
- diff --git a/comfy/model_detection.py b/comfy/model_detection.py
164
- --- a/comfy/model_detection.py
165
- +++ b/comfy/model_detection.py
166
- @@ -368,11 +368,23 @@ def detect_unet_config(state_dict, key_prefix, metadata=None):
167
- dit_config["latents_dim"] = state_dict['{}final_layer.video_out.weight'.format(key_prefix)].shape[0] // 4 # patch 1x2x2
168
- dit_config["audio_latents_dim"] = state_dict['{}final_layer.audio_out.weight'.format(key_prefix)].shape[0]
169
- dit_config["attention_head_dim"] = state_dict['{}blocks.0.attn.q_norm.weight'.format(key_prefix)].shape[0]
170
- - qkv = state_dict['{}blocks.0.attn.qkv_proj.weight'.format(key_prefix)]
171
- - dit_config["num_attention_heads"] = qkv.shape[0] // (3 * dit_config["attention_head_dim"])
172
- + qkv_key = '{}blocks.0.attn.qkv_proj.weight'.format(key_prefix)
173
- + separate_keys = tuple('{}blocks.0.attn.{}_proj.weight'.format(key_prefix, name) for name in ('q', 'k', 'v'))
174
- + if qkv_key in state_dict_keys:
175
- + qkv = state_dict[qkv_key]
176
- + dit_config["num_attention_heads"] = qkv.shape[0] // (3 * dit_config["attention_head_dim"])
177
- + elif all(k in state_dict_keys for k in separate_keys):
178
- + q, k, v = (state_dict[name] for name in separate_keys)
179
- + if q.shape != k.shape or q.shape != v.shape:
180
- + raise ValueError("MiniMax H3 separate Q/K/V projection shapes do not match")
181
- + dit_config["num_attention_heads"] = q.shape[0] // dit_config["attention_head_dim"]
182
- + dit_config["separate_qkv"] = True
183
- + else:
184
- + raise ValueError("MiniMax H3 checkpoint has neither fused nor separate Q/K/V projections")
185
- dit_config["ffn_hidden_size"] = state_dict['{}blocks.0.mlp.fc1.weight'.format(key_prefix)].shape[0] // 2
186
- dit_config["text_dim"] = state_dict['{}condition_proj.weight'.format(key_prefix)].shape[1]
187
- table_key = '{}adaln_t_table'.format(key_prefix)
188
- + basis_key = '{}adaln_curve_basis'.format(key_prefix)
189
- if table_key in state_dict_keys:
190
- # adaln shipped over a precomputed curve basis: the adaln linears span a small shared basis of the time-embedding curve (no time embedder)
191
- table = state_dict[table_key].shape # [grid, k]
192
- @@ -383,6 +395,11 @@ def detect_unet_config(state_dict, key_prefix, metadata=None):
193
- dit_config["timestep_input_dim"] = te.shape[1]
194
- dit_config["time_embed_hidden_size"] = te.shape[0]
195
- dit_config["time_embed_dim"] = state_dict['{}time_embedder.proj_out.weight'.format(key_prefix)].shape[0]
196
- + if basis_key in state_dict_keys:
197
- + basis = state_dict[basis_key].shape # [full time dim, compact adaLN dim]
198
- + if basis[0] != dit_config["time_embed_dim"]:
199
- + raise ValueError("MiniMax H3 adaLN basis input does not match time embedder output")
200
- + dit_config["adaln_curve_basis_dim"] = basis[1]
201
- dit_config["rope_inv_freq_len"] = state_dict['{}rope.inv_freq'.format(key_prefix)].shape[0]
202
- if metadata is not None and "config" in metadata:
203
- dit_config.update(json.loads(metadata["config"]).get("transformer", {}))
204
- diff --git a/comfy/model_patcher.py b/comfy/model_patcher.py
205
- --- a/comfy/model_patcher.py
206
- +++ b/comfy/model_patcher.py
207
- @@ -231,8 +231,11 @@ def get_key_weight(model, key):
208
- except AttributeError:
209
- pass
210
-
211
- - weight = getattr(op, op_keys[1])
212
- - if convert_func is not None:
213
- + # Quantized comfy_kitchen layers (int8/fp4) may not expose a regular
214
- + # .weight attribute. Returning None lets the existing caller skip
215
- + # those packed weights during partial-offload bookkeeping.
216
- + weight = getattr(op, op_keys[1], None)
217
- + if weight is not None and convert_func is not None:
218
- weight = comfy.utils.get_attr(model, key)
219
-
220
- return weight, set_func, convert_func
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
reports/loadtest_dynamic_separate_fl2va.json DELETED
@@ -1,31 +0,0 @@
1
- {
2
- "checkpoint": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors",
3
- "bytes": 22547374816,
4
- "load_device": "cpu",
5
- "elapsed_seconds": 8.17470669746399,
6
- "checks": {
7
- "model_class": "MiniMaxH3Model",
8
- "separate_qkv": true,
9
- "dynamic_basis": true,
10
- "table_mode": false,
11
- "basis_shape": [
12
- 2688,
13
- 16
14
- ],
15
- "has_main_q_proj": true,
16
- "has_main_k_proj": true,
17
- "has_main_v_proj": true,
18
- "has_main_qkv_proj": false,
19
- "has_refiner_q_proj": true,
20
- "has_refiner_qkv_proj": false,
21
- "time_proj_in_shape": [
22
- 5376,
23
- 256
24
- ],
25
- "time_proj_out_shape": [
26
- 2688,
27
- 5376
28
- ]
29
- },
30
- "status": "pass"
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
reports/loadtest_dynamic_separate_ref2va.json DELETED
@@ -1,31 +0,0 @@
1
- {
2
- "checkpoint": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors",
3
- "bytes": 22547376168,
4
- "load_device": "cpu",
5
- "elapsed_seconds": 8.223532438278198,
6
- "checks": {
7
- "model_class": "MiniMaxH3Model",
8
- "separate_qkv": true,
9
- "dynamic_basis": true,
10
- "table_mode": false,
11
- "basis_shape": [
12
- 2688,
13
- 16
14
- ],
15
- "has_main_q_proj": true,
16
- "has_main_k_proj": true,
17
- "has_main_v_proj": true,
18
- "has_main_qkv_proj": false,
19
- "has_refiner_q_proj": true,
20
- "has_refiner_qkv_proj": false,
21
- "time_proj_in_shape": [
22
- 5376,
23
- 256
24
- ],
25
- "time_proj_out_shape": [
26
- 2688,
27
- 5376
28
- ]
29
- },
30
- "status": "pass"
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
reports/validation_dynamic_separate_fl2va.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "variant": "fl2va",
3
- "checkpoint": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-fl2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors",
4
- "table_source": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-fl2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors",
5
- "bytes": 22547374816,
6
- "gib": 20.99887916445732,
7
- "keys": 1181,
8
- "quantized_linears": 270,
9
- "quant_groups": {
10
- "256": 270
11
- },
12
- "fused_qkv_keys": 0,
13
- "separate_qkv_projection_weights": 156,
14
- "qkv_split_tensors_bitwise": 156,
15
- "common_tensors_bitwise": 719,
16
- "bf16_main": 30,
17
- "time_embedder_bitwise_raw_hf": true,
18
- "basis_shape": [
19
- 2688,
20
- 16
21
- ],
22
- "basis_orthogonality_max_abs": 5.364418029785156e-07,
23
- "dynamic_vs_released_table_relative": 0.0,
24
- "dynamic_vs_released_table_max_abs": 0.0,
25
- "adaln_curve_samples": 19,
26
- "adaln_relative_errors": {
27
- "block_0": 3.2893751722440356e-07,
28
- "block_24": 3.324676356442069e-07,
29
- "block_49": 3.217328412574716e-07,
30
- "final": 2.851764975275728e-07
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
reports/validation_dynamic_separate_ref2va.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "variant": "ref2va",
3
- "checkpoint": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-ref2va-int8-lean-convrot-dynamic-k16-separate-qkv-quality21.safetensors",
4
- "table_source": "F:\\AI\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\minimax-h3\\minimax-h3-ref2va-int8-lean-convrot-table-k16-g4097-quality21.safetensors",
5
- "bytes": 22547376168,
6
- "gib": 20.998880423605442,
7
- "keys": 1181,
8
- "quantized_linears": 270,
9
- "quant_groups": {
10
- "256": 270
11
- },
12
- "fused_qkv_keys": 0,
13
- "separate_qkv_projection_weights": 156,
14
- "qkv_split_tensors_bitwise": 156,
15
- "common_tensors_bitwise": 719,
16
- "bf16_main": 30,
17
- "time_embedder_bitwise_raw_hf": true,
18
- "basis_shape": [
19
- 2688,
20
- 16
21
- ],
22
- "basis_orthogonality_max_abs": 2.384185791015625e-07,
23
- "dynamic_vs_released_table_relative": 2.8884949188068276e-07,
24
- "dynamic_vs_released_table_max_abs": 1.30385160446167e-06,
25
- "adaln_curve_samples": 19,
26
- "adaln_relative_errors": {
27
- "block_0": 3.29813104826826e-07,
28
- "block_24": 3.3073698091357073e-07,
29
- "block_49": 3.2451748666062485e-07,
30
- "final": 2.9567746651082416e-07
31
- }
32
- }