infosave commited on
Commit
7097d8d
Β·
verified Β·
1 Parent(s): 2088e7b

ClipProj 4B encoder variant: 23.47 GB -> 13.16 GB, 2x faster, still four bits everywhere

Browse files
Files changed (1) hide show
  1. README.md +123 -1
README.md CHANGED
@@ -61,7 +61,9 @@ not ported.
61
 
62
  | file | size | |
63
  |---|---|---|
64
- | `mmh3-turbo-fl2va-q4tp.cmf` | 23.94 GB | **use this one** |
 
 
65
  | `mmh3-turbo-fl2va-q2tp.cmf` | 18.74 GB | two bits on the gate/up planes. Smaller, faster, and it stops following the prompt β€” kept for anyone who wants to push on it, not for rendering. See below |
66
 
67
  ## Keyframe to video
@@ -194,6 +196,11 @@ RAM at least the file's size β€” 24 GB β€” or every step faults on non-resident
194
  pages; the weights are memory-mapped, not read. Disk: 24 GB. A GPU is optional
195
  and wants ~14 GB of VRAM for the DiT's planes. No network access at run time.
196
 
 
 
 
 
 
197
  ## Two bits: smaller, faster, and answering a different question
198
 
199
  The obvious next cut is the DeepSeek-V4 policy: gate/up at two bits,
@@ -230,6 +237,121 @@ measuring next β€” the packer's policy is one predicate,
230
  that experiment starts from something rather than nothing; four bits is
231
  what to render with.
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  ## What it costs to run
234
 
235
  The file is memory-mapped, so plan on RAM at least its size or every step
 
61
 
62
  | file | size | |
63
  |---|---|---|
64
+ | `mmh3-turbo-fl2va-q4tp.cmf` | 23.94 GB | **use this one** β€” text-to-video AND keyframe-to-video |
65
+ | `mmh3-turbo-q4tp.cmf` | 23.47 GB | the same without the vision tower: text-to-video only |
66
+ | `mmh3-turbo-clipproj4b-q4tp.cmf` | **13.16 GB** | text-to-video with a 4B stand-in prompt encoder. Peaks at 15.1 GB of VRAM, so a 20 GB card holds the whole run; 2x faster, and still four bits everywhere. Costs some set dressing β€” see below |
67
  | `mmh3-turbo-fl2va-q2tp.cmf` | 18.74 GB | two bits on the gate/up planes. Smaller, faster, and it stops following the prompt β€” kept for anyone who wants to push on it, not for rendering. See below |
68
 
69
  ## Keyframe to video
 
196
  pages; the weights are memory-mapped, not read. Disk: 24 GB. A GPU is optional
197
  and wants ~14 GB of VRAM for the DiT's planes. No network access at run time.
198
 
199
+ `mmh3-turbo-clipproj4b-q4tp.cmf` asks for 14 GB of RAM and disk instead, and
200
+ peaks at 15.1 GB of VRAM β€” a whole-run maximum, polled, not a snapshot. That is
201
+ what makes it the one to reach for on a 20 GB card: below that the prompt
202
+ encoder pages, and on this workload paging costs more than any kernel.
203
+
204
  ## Two bits: smaller, faster, and answering a different question
205
 
206
  The obvious next cut is the DeepSeek-V4 policy: gate/up at two bits,
 
237
  that experiment starts from something rather than nothing; four bits is
238
  what to render with.
239
 
240
+ ## A smaller encoder instead of fewer bits
241
+
242
+ The two-bit section above ends on a diagnosis: half this file is the PROMPT
243
+ ENCODER, and squeezing it is what broke the prompt. There is a second way to act
244
+ on that diagnosis β€” **don't compress the encoder, replace it.**
245
+
246
+ [ClipProj](https://github.com/nicolab28/ComfyUI-ClipProj) fits a ridge
247
+ regression from a small Qwen3-VL's hidden state into the space the DiT was
248
+ conditioned on. Same tokenizer, same family, one affine map:
249
+
250
+ ```text
251
+ cond = ((h - mean_in) / std_in) @ W [+ GELU residual] * std_out + mean_out
252
+ ```
253
+
254
+ `mmh3-turbo-clipproj4b-q4tp.cmf` is the text-to-video file with Qwen3-VL-4B
255
+ tapped at layer 24 standing in for the 32B tapped at 50, plus the 304 MB
256
+ projection kept **exact** β€” f32, no quantization on the piece that carries the
257
+ whole substitution. Everything else is copied through byte for byte: DiT and
258
+ both VAE decoders, still `q4tp`. Nothing anywhere is two bits.
259
+
260
+ **23.47 GB β†’ 13.16 GB.** The encoder went from 552 tensors to 277.
261
+
262
+ ### Does it still mean the same thing?
263
+
264
+ That is measurable without rendering a frame: dump what the DiT actually
265
+ receives (`CMF_TE_DUMP=<path>`) from both files on one prompt, and take the
266
+ cosine per token.
267
+
268
+ | | mean cosine to the 32B | worst token |
269
+ |---|---|---|
270
+ | 4B tapped at **24** | **0.9198** | 0.7982 |
271
+ | 4B tapped at 25 | 0.8452 | 0.5910 |
272
+ | *floor β€” two different tokens of the 32B itself* | *0.5914* | |
273
+
274
+ The tap index is 0-based, and off-by-one is a real failure mode rather than a
275
+ theoretical one: at 25 the worst token sits **on the floor**, uncorrelated.
276
+ Token 0 is not projected at all but replaced by a stored `sink_out` β€” the
277
+ attention sink is an outlier no regression fits β€” and it lands at cosine
278
+ **0.9999** against the teacher's, which is the sharpest single confirmation
279
+ that the mechanism is wired right.
280
+
281
+ ### What it costs
282
+
283
+ Same prompt, same seed, same four steps, one RTX 3090, both files under
284
+ identical settings:
285
+
286
+ | | encode | denoise | video VAE | audio VAE | **total** |
287
+ |---|---|---|---|---|---|
288
+ | `mmh3-turbo-q4tp` | 49.2 s | 116.4 s | 101.9 s | 6.7 s | **281 s** |
289
+ | `mmh3-turbo-clipproj4b-q4tp` | **1.9 s** | 84.5 s | 45.6 s | 5.9 s | **140 s** |
290
+
291
+ Encoding is 26x faster, which is the part ClipProj actually replaced. The rest
292
+ is residency: 13.16 GB leaves the decoder room on a 24 GB card where 23.47 GB
293
+ does not, and the video VAE more than halves without a line of its own
294
+ changing. On the 20 GB card this variant exists for, that gap is the whole
295
+ point β€” a reader of this repo measured 20 minutes for one 512x288 clip on an
296
+ RTX 3080 20 GB, paging the encoder in and out of a ~19 GB weight budget.
297
+
298
+ The parity probe takes the device arm on both files at the same `rel rms
299
+ 4.65e-3`, which is its own small proof that the DiT came through untouched.
300
+
301
+ ### What it costs in quality
302
+
303
+ Judge it on the clip, not on a frame: a still catches the pancake at rest and
304
+ reads as a loss that is not there.
305
+
306
+ | four bits, 32B encoder | four bits, 4B + ClipProj | two bits, 32B encoder |
307
+ |---|---|---|
308
+ | ![32B](https://huggingface.co/infosave/MiniMax-H3-Turbo-cmf/resolve/main/samples/ab_q4tp.gif) | ![ClipProj](https://huggingface.co/infosave/MiniMax-H3-Turbo-cmf/resolve/main/samples/ab_clipproj.gif) | ![two bits](https://huggingface.co/infosave/MiniMax-H3-Turbo-cmf/resolve/main/samples/ab_q2tp.gif) |
309
+ | 23.94 GB | **13.16 GB** | 18.74 GB |
310
+
311
+ Across the 39 frames the 4B does the whole job: corgi, chef hat, flat clean
312
+ style, and the pancake **leaves the surface and comes back**, the dish empty
313
+ underneath at the top of the toss. The verb survives β€” that is what `q2tp`
314
+ lost, along with the animal and the pan.
315
+
316
+ What drifts is set dressing. The 32B renders the cooking surface as a griddle
317
+ and puts patterned wallpaper behind; the 4B gives a rimmed white plate and a
318
+ plain ground. A 0.92 cosine is close, not equal, and where it is not equal is
319
+ the scene's furniture rather than its subject or its action.
320
+
321
+ So the ordering is not "smaller is worse". The two-bit file answers a different
322
+ question; this one answers the right question with a plainer set, for 56% of
323
+ the size and half the time. If you have the VRAM for the 32B encoder, use it β€”
324
+ its framing is richer. If you are paging, this is the better trade, and unlike
325
+ the two-bit build it is a trade rather than a loss.
326
+
327
+ Sound is untouched either way: the audio branch never sees the prompt encoder.
328
+ [The clip with its audio.](https://huggingface.co/infosave/MiniMax-H3-Turbo-cmf/resolve/main/samples/ab_clipproj.mp4)
329
+
330
+ ### Building one
331
+
332
+ ```bash
333
+ cortiq animate-pack \
334
+ --in mmh3-turbo-q4tp.cmf \
335
+ --te qwen3vl_4b_bf16.safetensors --te-layers 24 \
336
+ --clip-proj mmh3-4b-ClipProj-celeb-mlp.safetensors \
337
+ --quant q4tp --out mmh3-turbo-clipproj4b-q4tp.cmf
338
+ ```
339
+
340
+ `--te-layers` is not a size knob, it is the tap: layers above it never execute,
341
+ so packing them is pure file. `--clip-proj` carries the projection in exact and
342
+ replaces the encoder **as a whole component** β€” matching tensor names alone
343
+ would leave `te.layers.24..49` of the 32B behind, six gigabytes that
344
+ `num_hidden_layers` then excludes from the forward while disk and VRAM budget
345
+ still pay for them.
346
+
347
+ The encoder is [`Comfy-Org/Qwen3-VL`](https://huggingface.co/Comfy-Org/Qwen3-VL)
348
+ `text_encoders/qwen3vl_4b_bf16.safetensors`, and the projection is
349
+ [`NicoLab28/ClipProj-MiniMax-H3`](https://huggingface.co/NicoLab28/ClipProj-MiniMax-H3)
350
+ `mmh3-4b-ClipProj-celeb-mlp.safetensors` β€” use the file the projection was
351
+ fitted on, since the map is only valid for those exact weights. An 8B
352
+ projection is published too and scores higher on its author's corpus (0.8037
353
+ against 0.7930); it costs about 4 GB more.
354
+
355
  ## What it costs to run
356
 
357
  The file is memory-mapped, so plan on RAM at least its size or every step