| # ClipProj v3 |
|
|
| Four new matrices, calibrated against `qwen3vl_32b_minimax_h3_nvfp4_awq` β the |
| base MiniMax H3 encoder, the one a plain `Load CLIP` gives you. |
|
|
| Requires node **0.1.13** or later. The `-v3-mlp` files carry no linear matrix, |
| and an older node raises `KeyError: 'W'` on load. |
|
|
| ## What changed |
|
|
| **Body descriptions.** While testing v2 we found that naming one part of a |
| body could rewrite the whole of it β build, height and face shifting together, |
| none of it asked for. Those matrices were calibrated against a modified 32B. |
| v3 is calibrated against the stock encoder, and we no longer observe the |
| problem: a build and an attribute stated in the same prompt are honoured |
| independently. |
|
|
| **Everything is measurably closer to the 32B.** Measured on a single reference |
| prompt, every projection encoded against the same stock 32B, so the numbers are |
| comparable to each other β which the figures published with v1 and v2 were not, |
| having been measured against different targets and in different spaces. The |
| `cos_test` written inside each file is the training-time figure against that |
| campaign's own target and does **not** compare across versions; the comparable |
| number is stored separately as `cos_prompt_reference`. |
|
|
| The render pipeline was verified deterministic before measuring anything: the |
| same workflow run twice, thirteen days apart, produced two files with identical |
| SHA-256. Any difference below therefore comes from the projection and nothing |
| else. |
|
|
| | projection | mean cosine vs 32B | |
| |---|---| |
| | 8B v3-mlp | 0.9449 | |
| | 8B v2 `celeb-mlp` | 0.9393 | |
| | 4B v3-mlp | 0.9381 | |
| | 4B v2 `celeb-mlp` | 0.9293 | |
| | 8B v3 | 0.9289 | |
| | 4B v3 | 0.9193 | |
|
|
| **The 8B now sees image tokens.** Until v3 the image corpus had only ever been |
| encoded with a 4B student, so both 8B matrices projected vision tokens without |
| having seen a single one β while the node accepts a reference image. Measured on |
| 100 held-out images, on the raw conditioning the diffusion model actually |
| receives: |
|
|
| | | vision tokens | text in the same sequences | |
| |---|---|---| |
| | 8B residual, before | 0.7692 | 0.9085 | |
| | 8B residual, after | 0.8578 | 0.9605 | |
| | 8B matrix, before | 0.7845 | 0.8926 | |
| | 8B matrix, after | 0.8457 | 0.9361 | |
|
|
| That costs 0.0027 of pure-text cosine on the residual and 0.0013 on the matrix β |
| which is why the 8B figures above are slightly below what a text-only corpus |
| would have given. |
|
|
| **Prefer the `-mlp` files on the measurement, not on this scene.** They sit |
| closer to the 32B, 0.9449 against 0.9289 on the 8B. But on this prompt the five |
| renders are faithful, plain matrices included: the pose, the dress, the white |
| pieces, the cat, the straw hat, the laundry, the bouncing knee all hold on all |
| five. A tightly written prompt survives even the linear baseline, and the |
| difference between the files shows up in the numbers well before it shows up on |
| screen. |
|
|
| ## What this does not fix, and will not |
|
|
| A projection cannot invent information the small encoder never had. Five hours |
| of training on a 3090, two more to encode the dataset, six and a half million |
| tokens β none of that changes what a 4B model wrote down in the first place. |
| The result is an approximation of the 32B's conditioning, not a copy of it. |
|
|
| In practice the line falls here: **what the prompt states, the projection |
| carries; what the prompt leaves open, the model fills from its own prior.** |
| Constrain a scene tightly and the projected renders track the 32B closely. |
| Leave the set dressing unstated β a cat somewhere, laundry on a line, furniture |
| β and it will be furnished differently. That is not a defect to be tuned away, |
| it is what a 20-degree angle between two conditioning vectors looks like on |
| screen. |
|
|
| ## Training data |
|
|
| The aim was to activate as much of the encoder's weight space as possible |
| rather than to cover one domain deeply. A matrix only learns to project the |
| directions it has actually seen used, so the corpus deliberately mixes |
| registers, languages and lengths. |
|
|
| | source | tokens | |
| |---|---| |
| | cinematic video prompts | 1 342 987 | |
| | native H3 format, 4 length draws | 3 169 879 | |
| | explicit register | 544 073 | |
| | Chinese | 532 302 | |
| | celebrity prompts, long form | 314 516 | |
| | filler sequences | 149 917 | |
| | celebrity prompts, short form | 99 668 | |
| | images, 3 blocks, 1 700 images | 349 244 | |
| | **total, both students** | **6 502 586** | |
|
|
| Both students now see the same corpus, images included β which makes the 4B and |
| the 8B comparable to each other for the first time. |
|
|
| 3 331 prompts for fitting, one in fifty held out for measurement. Tap 24 on |
| both students. Sequence lengths are drawn at random rather than truncated to a |
| fixed size, so a given word appears at many different positions instead of |
| always the same ones. |
|
|
| ## The demo folder |
|
|
| `demo/` holds five renders of the same scene. Same prompt, same seed 42, same |
| 8 steps, same turbo LoRA, same DiT, same VAE β only the projection changes. The |
| pipeline is reproducible bit for bit, verified by running it twice and comparing |
| the decoded video and audio streams, so every difference between these five |
| comes from the projection and nothing else. |
|
|
| | file | conditioning | |
| |---|---| |
| | `chess-32b-reference.mp4` | Qwen3-VL-32B, 15.7 GB | |
| | `chess-8b-mlp.mp4` | Qwen3-VL-8B + `v3-mlp`, 10.0 GB | |
| | `chess-4b-mlp.mp4` | Qwen3-VL-4B + `v3-mlp`, 4.8 GB | |
| | `chess-8b-ridge.mp4` | Qwen3-VL-8B + `v3`, matrix only | |
| | `chess-4b-ridge.mp4` | Qwen3-VL-4B + `v3`, matrix only | |
| | `chess-comparison.mp4` | the five in sequence, labelled | |
| | `chess-prompt.txt` | the prompt, verbatim | |
|
|
| The comparison runs matrix-only first, then the 32B, then the residuals β so the |
| reference sits in the middle and each half is read against it. |
|
|
| **You will not reproduce these files byte for byte, and that is normal.** Noticed |
| while testing something else, so take it as an observation rather than a study: |
| the result depends on the model of GPU the encoder runs on. Four cards, one |
| prompt, one seed, four different outputs β while two different RTX 3090s gave |
| byte-identical video. Not the architecture either: the 3060 and the 3090 are |
| both Ampere and disagree. Encoding the same prompt on two cards gives |
| conditioning that matches to a relative error of 7 Γ 10β»β·; eight denoising steps |
| turn that into a different piece of furniture. On one machine everything here is |
| reproducible to the bit, which is what makes the five-way comparison meaningful. |
|
|
| Watch her knee. The prompt asks for it three times, ending on a sentence of its |
| own: *"Her knee never stops bouncing."* It is the most redundant instruction in |
| the text, it is a continuous involuntary motion with no narrative purpose, and |
| it is the clearest single indicator that a projection carried what was written. |
| Then watch the cat, the laundry and the furniture, which are named once and |
| anchored nowhere β those move, and they are supposed to. |
|
|
| One thing none of the five gets right, including the 32B: she lifts a knight and |
| does not put it back on the same square. Object permanence through an occluding |
| hand on a grid of sixty-four identical squares is a limit of the video model, not |
| of the conditioning. It is listed here so nobody attributes it to the projection. |
|
|
| ## Files |
|
|
| | file | size | structure | encoder | |
| |---|---|---|---| |
| | `mmh3-4b-ClipProj-v3-mlp.safetensors` | 503 MB | residual only | Qwen3-VL-4B | |
| | `mmh3-8b-ClipProj-v3-mlp.safetensors` | 604 MB | residual only | Qwen3-VL-8B | |
| | `mmh3-4b-ClipProj-v3.safetensors` | 26 MB | matrix only | Qwen3-VL-4B | |
| | `mmh3-8b-ClipProj-v3.safetensors` | 42 MB | matrix only | Qwen3-VL-8B | |
|
|
| The residuals use a hidden width of 32 768 against 16 384 in v2, which is where |
| the extra download size comes from. |
|
|