A text-to-image model in one file of 1,208 MB that paints a 512 Γ 512 picture in one, two or four steps, in a web browser, on WebGPU, with no server: try it in this model's Space or on the mindview site, in a desktop browser with WebGPU. On a MacBook Air (M4) in Chrome a picture takes about 4 s in one step, 6 s in two and 15 s in four. It has 4.61 billion weights, and all but 165 million of them are β1, 0 or +1.
It is mindview-t2i with everything added for speed: three side branches trained on this ternary painter, for one, two and four steps, and a 2-step schedule whose first step sketches at a quarter of the size. Each branch is trained to paint like a full-precision teacher: EPFL's 1-step fine-tune of FLUX.2 [klein] 4B for one step, klein with a 2-step LoRA for two, and klein itself for four. It came out of mindview, an art installation that shows these models computing. Most of it is the work of others (see Sources and licenses).
| Mode | Steps | What runs | Time (M4 Air, Chrome) |
|---|---|---|---|
| Instant | 1 | the painter with the 1-step branch, the prompt's own text rows | about 4 s |
| Fast | 2 | a sketch at 256 Γ 256, then the picture at 512 Γ 512, with the 2-step branch | about 6 s |
| Best | 4 | the painter with the 4-step branch | about 15 s |
Times are for a first picture on a cool machine, from the prompt to the pixels. The Air has no fan and slows by about a third after minutes of painting.
The same prompts and seed in each mode, as painted in the browser:

Best is the most faithful to the prompt: its lettering is clean and its faces whole. Fast has the most detail but sometimes repeats things (the sign above says OPEN twice). Instant is a little softer.
| Part | What it does | Weights | Stored |
|---|---|---|---|
| reader | Ternary Bonsai 1.7B with its tokenizer, cut to its first 9 of 28 layers. It reads the prompt. | 764 M, ternary | 158.4 MB |
| cond | One linear map from the reader's states at layers 3, 6 and 9 to the painter's text stream (6,144 β 3,072), trained for this model. | 18.9 M, f16 | 35.3 MB |
| painter | The diffusion transformer of Bonsai Image 4B, which is FLUX.2 [klein] 4B with ternary weights. | 3,682 M, ternary | 761.3 MB |
| decoder | TAEF2, which turns the latent into pixels. | 1.3 M, f16 | 2.5 MB |
| 1-step branch | A side branch of rank 32 on each of the painter's 100 ternary matrices, trained on this painter to paint like epfl-vita/flux2-klein-1step-rdm (see One step). | 48.0 M, f16 | 82.7 MB |
| 2-step branch | A side branch of rank 32 on the same matrices, trained on this painter to paint like klein with radames/FLUX.2-klein-Sana-Sprint in two steps (see Two and four steps). | 48.0 M, f16 | 82.6 MB |
| 4-step branch | The same again, trained to paint like klein in four steps. | 48.0 M, f16 | 82.6 MB |
| schedules | Noise levels and the painter's modulation for 1, 2, 3 and 4 steps, and for 1 step with the 1-step branch; the branches' trained offsets are in the modulation for 1, 2 and 4 steps. | 2.1 MB |
The decoder also carries two colour probes (390 numbers) that show its 128 Γ 128 and 256 Γ 256 stages as pictures, for mindview's visuals; painting does not use them. That is about 2.1 bits per weight on average, all parts included. The reader, the map and the way they are joined are described on the mindview-t2i card; they are the same here.
EPFL's RDM distils FLUX.2 [klein] 4B to a single step with a full fine-tune. Its change to klein carries over to the ternary transformer of Bonsai Image 4B without retraining, in two parts:
1r), and this part costs nothing at run time.Carried over like that, it painted in 1 step but softly, with defects: a cat's face doubled, a fox as a ball of fur. RDM itself, on the full-precision klein, paints sharply from the same conditioning, so the gap is the ternary weights. The branch in this file is trained to close it:
A second run, at rank 64 with three noises per prompt, did a little better by that measure but painted the same, so the file keeps rank 32. RDM also changed the image and text embedders and the output layer, by 0.08 to 0.3%; leaving those out changes nothing visible, so the file does not carry them.
The 2-step schedule goes from Ο = 1 to 0.885 to 0: after the first step the picture is still 88% noise, so the first step only has to place things. Here it runs at 256 Γ 256 (256 patches instead of 1,024) and reads only the first 128 of the prompt's 256 text rows. The reader is causal, so those rows are exactly what a 128-row encoding would give. Its guess of the clean picture is upsampled to 512 Γ 512 in the latent space (bilinear, per channel), noised back to Ο = 0.885 with fresh noise, and the second step paints at full size.
That takes about a third less time than two full steps, and on the test prompts the pictures are as good or better.
The 2-step LoRA was trained on the full-precision klein and carried over to the ternary painter with some loss, and four steps of the ternary painter alone are close to klein but not the same. Both now have a branch trained on this painter, the way the 1-step branch is:
In the pictures, four steps gained the most: lettering that came out as "OPENI" now reads "OPEN", and a helmet that cut through a cat's face now sits around it. Two steps gained detail.
The file is read by the mindview browser runtime (WebGPU and WGSL, no server):
src/lib/runtime/packed.ts reads the file,
bonsai-llm.ts runs the reader and
painter.ts the rest
(setSteps('1r'), setSteps(2) with setNoise(β¦, low) and upsampleLatent, setSteps(4); each turns on its branch). The page at
neovand.github.io/mindview/paint loads it from this repository with range
requests, so it is never all in memory at once, and the browser keeps what it downloaded.
It is a GGUF file (v3), but its architecture is its own (mindview-t2i) and four of its tensor types are new, so
llama.cpp and other GGUF tools cannot run it as it is. The format is described on the
mindview-t2i card. The branches are stored as
<branch>.<matrix>.a and <branch>.<matrix>.bt, with the branch rdm for one step, lora for two and best for
four; mindview.rdm, mindview.lora and mindview.best give their ranks and sources.
From the mindview repository, with the source models in static/models and
the Hugging Face cache:
python research/scripts/adapter_layers.py final 3 6 9 # the map (see mindview-t2i)
python research/scripts/rdm_delta.py # RDM minus klein: rank-256 SVDs of the 100 matrices
python research/scripts/distill_1step.py prepare # the map and the branch's start, for the training
modal run research/cloud/distill_modal.py --step upload # then --step fetch, targets, train, pull (one H100)
python research/scripts/distill_1step.py export 32 # the trained 1-step branch
RDM_STUDENT=research/data/distill/student_r32.pt python research/scripts/export_painter_schedules.py
# two and four steps (scripts/distill_steps.py), each with --mode fast and --mode best:
modal run research/cloud/distill_modal.py --script steps --step targets --mode fast --n 2000
modal run research/cloud/distill_modal.py --script steps --step train --mode fast --steps 3000 --rank 32 --lr 1e-4
modal run research/cloud/distill_modal.py --step pull --only fast_
python research/scripts/distill_steps.py export fast 32 # fast_trained_r32.safetensors, fast_offsets.pt
python research/scripts/pack_model.py --fused research/data/adapter/fused_final_layers_3_6_9.pt --float \
--lora research/data/distill/fast_trained_r32.safetensors --lora-rank 32 \
--fast-offsets research/data/distill/fast_offsets.pt \
--best research/data/distill/best_trained_r32.safetensors --best-rank 32 \
--best-offsets research/data/distill/best_offsets.pt \
--rdm research/data/distill/rdm_trained_r32.safetensors --rdm-rank 32
distill_1step.py and distill_steps.py also run on a Mac (MPS), about a hundred times slower. rdm_test.py, rdm_rank.py, progressive.py and
progressive_rows.py hold the experiments behind the other choices above.
Ternary-Bonsai-1.7B-Q2_0.gguf, with every ternary weight exact.A text-to-image model in one file of 1,208 MB that paints a 512 Γ 512 picture in one, two or four steps, in a web browser, on WebGPU, with no server: try it in this model's Space or on the mindview site, in a desktop browser with WebGPU. On a MacBook Air (M4) in Chrome a picture takes about 4 s in one step, 6 s in two and 15 s in four. It has 4.61 billion weights, and all but 165 million of them are β1, 0 or +1.
It is mindview-t2i with everything added for speed: three side branches trained on this ternary painter, for one, two and four steps, and a 2-step schedule whose first step sketches at a quarter of the size. Each branch is trained to paint like a full-precision teacher: EPFL's 1-step fine-tune of FLUX.2 [klein] 4B for one step, klein with a 2-step LoRA for two, and klein itself for four. It came out of mindview, an art installation that shows these models computing. Most of it is the work of others (see Sources and licenses).
| Mode | Steps | What runs | Time (M4 Air, Chrome) |
|---|---|---|---|
| Instant | 1 | the painter with the 1-step branch, the prompt's own text rows | about 4 s |
| Fast | 2 | a sketch at 256 Γ 256, then the picture at 512 Γ 512, with the 2-step branch | about 6 s |
| Best | 4 | the painter with the 4-step branch | about 15 s |
Times are for a first picture on a cool machine, from the prompt to the pixels. The Air has no fan and slows by about a third after minutes of painting.
The same prompts and seed in each mode, as painted in the browser:

Best is the most faithful to the prompt: its lettering is clean and its faces whole. Fast has the most detail but sometimes repeats things (the sign above says OPEN twice). Instant is a little softer.
| Part | What it does | Weights | Stored |
|---|---|---|---|
| reader | Ternary Bonsai 1.7B with its tokenizer, cut to its first 9 of 28 layers. It reads the prompt. | 764 M, ternary | 158.4 MB |
| cond | One linear map from the reader's states at layers 3, 6 and 9 to the painter's text stream (6,144 β 3,072), trained for this model. | 18.9 M, f16 | 35.3 MB |
| painter | The diffusion transformer of Bonsai Image 4B, which is FLUX.2 [klein] 4B with ternary weights. | 3,682 M, ternary | 761.3 MB |
| decoder | TAEF2, which turns the latent into pixels. | 1.3 M, f16 | 2.5 MB |
| 1-step branch | A side branch of rank 32 on each of the painter's 100 ternary matrices, trained on this painter to paint like epfl-vita/flux2-klein-1step-rdm (see One step). | 48.0 M, f16 | 82.7 MB |
| 2-step branch | A side branch of rank 32 on the same matrices, trained on this painter to paint like klein with radames/FLUX.2-klein-Sana-Sprint in two steps (see Two and four steps). | 48.0 M, f16 | 82.6 MB |
| 4-step branch | The same again, trained to paint like klein in four steps. | 48.0 M, f16 | 82.6 MB |
| schedules | Noise levels and the painter's modulation for 1, 2, 3 and 4 steps, and for 1 step with the 1-step branch; the branches' trained offsets are in the modulation for 1, 2 and 4 steps. | 2.1 MB |
The decoder also carries two colour probes (390 numbers) that show its 128 Γ 128 and 256 Γ 256 stages as pictures, for mindview's visuals; painting does not use them. That is about 2.1 bits per weight on average, all parts included. The reader, the map and the way they are joined are described on the mindview-t2i card; they are the same here.
EPFL's RDM distils FLUX.2 [klein] 4B to a single step with a full fine-tune. Its change to klein carries over to the ternary transformer of Bonsai Image 4B without retraining, in two parts:
1r), and this part costs nothing at run time.Carried over like that, it painted in 1 step but softly, with defects: a cat's face doubled, a fox as a ball of fur. RDM itself, on the full-precision klein, paints sharply from the same conditioning, so the gap is the ternary weights. The branch in this file is trained to close it:
A second run, at rank 64 with three noises per prompt, did a little better by that measure but painted the same, so the file keeps rank 32. RDM also changed the image and text embedders and the output layer, by 0.08 to 0.3%; leaving those out changes nothing visible, so the file does not carry them.
The 2-step schedule goes from Ο = 1 to 0.885 to 0: after the first step the picture is still 88% noise, so the first step only has to place things. Here it runs at 256 Γ 256 (256 patches instead of 1,024) and reads only the first 128 of the prompt's 256 text rows. The reader is causal, so those rows are exactly what a 128-row encoding would give. Its guess of the clean picture is upsampled to 512 Γ 512 in the latent space (bilinear, per channel), noised back to Ο = 0.885 with fresh noise, and the second step paints at full size.
That takes about a third less time than two full steps, and on the test prompts the pictures are as good or better.
The 2-step LoRA was trained on the full-precision klein and carried over to the ternary painter with some loss, and four steps of the ternary painter alone are close to klein but not the same. Both now have a branch trained on this painter, the way the 1-step branch is:
In the pictures, four steps gained the most: lettering that came out as "OPENI" now reads "OPEN", and a helmet that cut through a cat's face now sits around it. Two steps gained detail.
The file is read by the mindview browser runtime (WebGPU and WGSL, no server):
src/lib/runtime/packed.ts reads the file,
bonsai-llm.ts runs the reader and
painter.ts the rest
(setSteps('1r'), setSteps(2) with setNoise(β¦, low) and upsampleLatent, setSteps(4); each turns on its branch). The page at
neovand.github.io/mindview/paint loads it from this repository with range
requests, so it is never all in memory at once, and the browser keeps what it downloaded.
It is a GGUF file (v3), but its architecture is its own (mindview-t2i) and four of its tensor types are new, so
llama.cpp and other GGUF tools cannot run it as it is. The format is described on the
mindview-t2i card. The branches are stored as
<branch>.<matrix>.a and <branch>.<matrix>.bt, with the branch rdm for one step, lora for two and best for
four; mindview.rdm, mindview.lora and mindview.best give their ranks and sources.
From the mindview repository, with the source models in static/models and
the Hugging Face cache:
python research/scripts/adapter_layers.py final 3 6 9 # the map (see mindview-t2i)
python research/scripts/rdm_delta.py # RDM minus klein: rank-256 SVDs of the 100 matrices
python research/scripts/distill_1step.py prepare # the map and the branch's start, for the training
modal run research/cloud/distill_modal.py --step upload # then --step fetch, targets, train, pull (one H100)
python research/scripts/distill_1step.py export 32 # the trained 1-step branch
RDM_STUDENT=research/data/distill/student_r32.pt python research/scripts/export_painter_schedules.py
# two and four steps (scripts/distill_steps.py), each with --mode fast and --mode best:
modal run research/cloud/distill_modal.py --script steps --step targets --mode fast --n 2000
modal run research/cloud/distill_modal.py --script steps --step train --mode fast --steps 3000 --rank 32 --lr 1e-4
modal run research/cloud/distill_modal.py --step pull --only fast_
python research/scripts/distill_steps.py export fast 32 # fast_trained_r32.safetensors, fast_offsets.pt
python research/scripts/pack_model.py --fused research/data/adapter/fused_final_layers_3_6_9.pt --float \
--lora research/data/distill/fast_trained_r32.safetensors --lora-rank 32 \
--fast-offsets research/data/distill/fast_offsets.pt \
--best research/data/distill/best_trained_r32.safetensors --best-rank 32 \
--best-offsets research/data/distill/best_offsets.pt \
--rdm research/data/distill/rdm_trained_r32.safetensors --rdm-rank 32
distill_1step.py and distill_steps.py also run on a Mac (MPS), about a hundred times slower. rdm_test.py, rdm_rank.py, progressive.py and
progressive_rows.py hold the experiments behind the other choices above.
Ternary-Bonsai-1.7B-Q2_0.gguf, with every ternary weight exact.