FIBO 2.0 Edit Turbo for text-to-image
Fibo 2.0 Edit Turbo is Bria's 4-step, guidance-free distillation of Fibo 2.0, built and presented as an image-editing model. It also generates images from text alone: called with no input image, it renders a prompt in 4 steps without classifier-free guidance, where the full Fibo 2.0 Dev model runs 50 steps with guidance.
This repository has two minimal ComfyUI workflows for that, one for the full bf16 model and one for GGUF quants, a Python script that does the same with diffusers, and two scripts that run the same model on Apple silicon with MLX.
No models are hosted here. The models are Bria AI's, and every model file downloads from its owners' repositories listed below. This repository holds only the workflows, the Python scripts and these notes; its contribution is the workflows, the scripts and the observation that Edit Turbo works for text-to-image.
Fibo 2.0 Edit Turbo, text to image: 4 steps, no CFG, 1024×1024, seed 4242. The prompt and the VGL caption it was rendered
from are in assets/lake-pier.json; more examples below.
Updates
| Date | What's new |
|---|---|
| 21 Oct 2026 | ComfyUI workflows for the full bf16 model and for GGUF, the diffusers script with 22 examples (each rendered from the prompt as typed and from a VGL caption), and the MLX scripts for Apple silicon |
Models and credits
| What | Made by | Where |
|---|---|---|
| Fibo 2.0 Edit Turbo, the model these workflows run | Bria AI | briaai/Fibo-2.0-edit-turbo |
| Fibo 2.0 Dev, the full model Edit Turbo is distilled from | Bria AI | briaai/Fibo-2.0-dev |
| ComfyUI single files: the diffusion models (bf16, int8), the Qwen3-VL-4B text encoder, the FLUX.2 VAE | Comfy-Org | Comfy-Org/Fibo-2.0 |
| Native Fibo 2.0 support in ComfyUI, including the TextEncodeFibo2 node | kijai, merged by Comfy-Org | ComfyUI PR #17240 |
| GGUF quants of Dev and Edit Turbo | vantagewithai | vantagewithai/Fibo-2.0-Dev-and-Edit-Turbo-ComfyUI-GGUF |
| GGUF loader for ComfyUI | city96 | ComfyUI-GGUF |
| VGL, Bria's structured prompt language, and bria-vgl, its prompt writer | Bria AI | docs.bria.ai/vgl, Bria-AI/vgl |
The diffusers pipeline (BriaFibo2Pipeline) |
Bria AI and Hugging Face | diffusers |
| MLX, the array framework the Apple silicon scripts run on | Apple (MLX contributors) | ml-explore/mlx |
| mlx-vlm, whose Qwen3-VL runs the text encoder in the MLX scripts | Prince Canuma | Blaizzy/mlx-vlm |
mflux, whose FLUX.2 VAE decodes in fibo2_edit_turbo_t2i_mflux.py |
Filip Strand and contributors | mflux-community/mflux |
ComfyUI
Needs ComfyUI's native Fibo 2.0 support, merged on 21 Oct 2026 (PR #17240, commit 87ed5a0) after the newest tagged release (v0.42.3, 20 Oct 2026): v0.42.3 and earlier releases do not have its TextEncodeFibo2 node (the node's source). Use the latest ComfyUI from GitHub: in the Comfy Desktop app, update to the "Latest on GitHub" version (shown as v0.42.3+N; Fibo 2.0 arrived at +16); on a git install, git pull on master and restart; or switch to the nightly version in ComfyUI Manager. The next tagged release will include it. The GGUF workflow also needs the ComfyUI-GGUF node pack (install it from ComfyUI Manager). Nothing else is custom.
These workflows use ComfyUI's built-in nodes, not the third-party ComfyUI-Fibo2 pack, which has its own loaders and its own Fibo2 Edit Conditioning node. Don't mix the two: the pack's conditioning node fed by the built-in Load CLIP fails with 'Image' object is not subscriptable.
| Workflow | Diffusion model it loads |
|---|---|
FIBO2-Edit-Turbo-T2I-ComfyUI.json |
fibo2_edit_turbo_bf16.safetensors (~16 GB), or fibo2_edit_turbo_int8_convrot.safetensors (~8.4 GB), from Comfy-Org/Fibo-2.0 |
FIBO2-Edit-Turbo-T2I-ComfyUI-GGUF.json |
fibo2_edit_turbo-Q8_0.gguf (9.4 GB), -Q6_K (7.5 GB) or -Q4_K_M (6.2 GB), from the turbo folder of vantagewithai's GGUF repository |
Both also load the same text encoder and VAE from Comfy-Org/Fibo-2.0. The files go here:
ComfyUI/models/
├── diffusion_models/ fibo2_edit_turbo_bf16.safetensors (or the int8 file, or a .gguf)
├── text_encoders/ qwen3vl_4b_bf16.safetensors (or qwen3vl_4b_int8_convrot.safetensors)
└── vae/ flux2-vae.safetensors
The workflows carry the download links, so ComfyUI's missing-models dialog can fetch the files. The models are gated: accept Bria's licence on the model page first if a download asks for it.
The graph, seven nodes and a note:
Load Diffusion Model (or Unet Loader (GGUF)) ───────────────────────────────► KSampler ─► VAE Decode ─► Save Image
Load CLIP (type: fibo2) ─► TextEncodeFibo2 ─► positive, negative, latent ──► ▲ ▲
Load VAE ─────────────────────────────────────────────────────────────────────────────────────┘
The full bf16 workflow in ComfyUI, tested on 21 Oct 2026: the lake-pier caption in TextEncodeFibo2 at 1024×1024, the KSampler's 4 steps with its live preview, and the result in Save Image. The GGUF workflow is the same graph, with Unet Loader (GGUF) in place of Load Diffusion Model. Click for the full-size screenshot.
- TextEncodeFibo2 takes the prompt and the image size, and makes the empty latent itself. For text to image, leave its image and VAE inputs empty.
- KSampler: 4 steps, CFG 1, sampler
euler, schedulersimple. At CFG 1 there is no negative pass, so the negative prompt is unused. - Size: width and height in multiples of 16, about one megapixel in total, for example 1024×1024, 1424×800, 800×1424, 1248×832, 832×1248 or 1152×896.
- Prompt: a VGL caption in JSON gives the most control; the workflows open with the caption of the image above. A plain sentence works too (see Prompts).
- Seed: the KSampler draws a new seed after every run (its control after generate is
randomize); set it tofixedto repeat an image.
Python (diffusers)
fibo2_edit_turbo_t2i.py generates images from text with Edit Turbo, one prompt or a batch.
Needs diffusers 0.42.0 or newer: BriaFibo2Pipeline is in diffusers' main branch since 20 Oct 2026, and the
latest release on PyPI, 0.41.0, doesn't have it yet. Until 0.42.0 is released, install diffusers from GitHub (version
0.42.0.dev0). It also needs transformers 5 or newer (the text encoder's config is in transformers 5's format),
accelerate, huggingface_hub and Pillow 10.1 or newer:
pip install -r requirements.txt # diffusers from GitHub main, transformers, accelerate, huggingface_hub, Pillow
hf auth login # after accepting the licence on https://huggingface.co/briaai/Fibo-2.0-edit-turbo
Run it:
# a plain idea: the model's own text encoder writes the VGL caption, then Edit Turbo renders it
python fibo2_edit_turbo_t2i.py "a red vintage bicycle leaning against a whitewashed wall on a narrow street"
# the prompt as typed, no caption
python fibo2_edit_turbo_t2i.py --plain "A red vintage bicycle leaning against a whitewashed wall."
# another take on the caption: sampled instead of greedy, from caption seed 2 (the image seed stays 4242)
python fibo2_edit_turbo_t2i.py --sample 2 --seed 4242 "a red vintage bicycle leaning against a whitewashed wall"
# another size, a fixed seed
python fibo2_edit_turbo_t2i.py "an origami whale above a paper city" --width 1424 --height 800 --seed 42
# a finished caption: reproduce the image above, or edit its JSON first
python fibo2_edit_turbo_t2i.py --json assets/lake-pier.json --seed 4242
# a batch: the 22 examples below, with captions and as typed (the model loads once per batch; finished images are skipped)
python fibo2_edit_turbo_t2i.py --prompts examples/prompts.json --out-dir examples/vgl --seed 4242 --vae-tiling
python fibo2_edit_turbo_t2i.py --prompts examples/prompts.json --out-dir examples/direct --seed 4242 --vae-tiling --plain
| Option | What it does |
|---|---|
--plain |
send the prompt as typed instead of writing a VGL caption |
--sample [N] |
write the caption by sampling (temperature 0.8, top-p 0.9) instead of greedily: another take on the same prompt, from caption seed N (default: the image's seed), recorded in the JSON |
--json FILE |
render a finished VGL caption: a caption object, or a saved result with a caption key |
--prompts FILE |
a batch: a JSON list of prompts (strings, or objects with prompt and a slug used as the file name) or a text file with one prompt per line |
--out-dir DIR, --out FILE |
where a batch, or a single image, is saved |
--width, --height |
the size, multiples of 16, about one megapixel (default 1024×1024) |
--seed |
a fixed seed; random for each image when omitted |
--steps, --guidance |
4 and 1.0 by default, Edit Turbo's own setting |
--model |
the Hub id (default briaai/Fibo-2.0-edit-turbo) or a local copy of its folder |
--device |
auto (CUDA, then Apple MPS, then CPU), or one of them |
--vae-tiling |
decode in tiles: a lower memory peak at the end of each image |
--offload |
keep one model part on the GPU at a time: less GPU memory, slower |
Every image is saved with a JSON file beside it: the prompt, the caption, the seed and the settings. Pass that file to
--json to render the same caption again, or edit the caption first.
How it works. Fibo 2.0 is trained on structured captions written in VGL, Bria's JSON language for images: the subject and every object, the background, lighting, composition, colour, camera and lens, the medium and style, and any text the image shows. Bria's own writer, bria-vgl, runs on Gemini. This script needs no API key: the pipeline's text encoder is a complete vision-language model, Qwen3-VL-4B-Instruct, so the script asks it to write the caption.
- Load
BriaFibo2Pipelinewith the Edit Turbo weights in bf16. - Write the captions: the pipeline's own Qwen3-VL-4B-Instruct receives bria-vgl's open "generate" instructions, its
system prompt and field guide (MIT, by Bria AI, downloaded from GitHub on the first run and cached), and your
prompt, and answers with a VGL caption in JSON. Decoding is greedy, so the same prompt gives the same caption;
--samplewrites another take. - Embed every prompt, then free the text encoder (see one stage at a time).
- Denoise every image: the pipeline is called with the embedded caption and no input image, which makes it a text-to-image run, 4 steps at guidance 1.0, and returns the latent; then free the transformer. Any text a caption asks for is also shown to the text encoder as small images, drawn with the model's fonts, as Fibo 2.0 was trained; such a caption keeps the encoder until here, since the pipeline needs the prompt itself to place them.
- Decode every latent with the VAE, and save the image and its JSON.
The heart of it, in diffusers:
import json, torch
from diffusers import BriaFibo2Pipeline
pipe = BriaFibo2Pipeline.from_pretrained("briaai/Fibo-2.0-edit-turbo", torch_dtype=torch.bfloat16).to("cuda")
# 2. the pipeline's own Qwen3-VL-4B-Instruct writes the VGL caption (system: bria-vgl's generate instructions)
messages = [{"role": "system", "content": system},
{"role": "user", "content": [{"type": "text", "text": user}]}]
text = pipe.processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = pipe.processor(text=[text], return_tensors="pt").to(pipe.device)
out = pipe.text_encoder.generate(**inputs, max_new_tokens=2048, do_sample=False)
caption = pipe.processor.batch_decode(out[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)[0]
# 3. Edit Turbo as text to image: no image, 4 steps, no CFG
image = pipe(prompt=caption, num_inference_steps=4, guidance_scale=1.0, width=1024, height=1024,
generator=torch.Generator().manual_seed(4242)).images[0]
The script adds the parts around it: reading the caption out of the reply, the batch, the stages, the fonts and the saved JSON.
Python on Apple silicon (MLX)
Two more scripts run the same model with Apple's MLX instead of PyTorch, on Macs with Apple silicon. The weights are the same: both read Bria's repository as it is (downloaded on the first run), and nothing is converted or hosted here. What the files hold is code: the FIBO 2.0 transformer, ported module for module from diffusers, the text encoder through mlx-vlm's Qwen3-VL, the layers of the FLUX.2 VAE decoder, and the pipeline's steps (the caption, the images of a caption's text, the schedule).
| Script | Uses | Install |
|---|---|---|
fibo2_edit_turbo_t2i_mlx.py |
MLX and mlx-vlm; everything else is in the file | pip install -r requirements-mlx.txt |
fibo2_edit_turbo_t2i_mflux.py |
the same, with mflux's FLUX.2 VAE for the final decode | pip install -r requirements-mflux.txt |
Run them like the diffusers script, with the same options except --device, --offload and --vae-tiling
(diffusers only), plus --precision:
python fibo2_edit_turbo_t2i_mlx.py "a red vintage bicycle leaning against a whitewashed wall on a narrow street"
python fibo2_edit_turbo_t2i_mlx.py --json assets/lake-pier.json --seed 4242
python fibo2_edit_turbo_t2i_mlx.py --prompts examples/prompts.json --out-dir out --seed 4242 --plain
python fibo2_edit_turbo_t2i_mflux.py "an origami whale above a paper city" --width 1424 --height 800
--precision |
|
|---|---|
float16 (default) |
attention and the feed-forward layers compute in float16, everything else in bfloat16: in the test done the 4 steps ran in 18.4 s instead of 24.8 s, and the image matched the bfloat16 one at 33-43 dB PSNR |
bfloat16 |
the model's own precision |
float32 |
twice the memory |
One stage at a time. All three scripts keep one part of the model in memory at a time: the text encoder writes the captions and embeds every prompt, then leaves; the transformer denoises every image, then leaves; the VAE decodes them. In the MLX script at 1024×1024 the largest stage is the transformer's, and the run peaked at 17.4 GB (it prints its peak at the end): plan for a Mac with at least 24 GB of memory, 32 GB to work beside it comfortably. The stages change nothing in the image: the diffusers script's staged renders are the same images, bit for bit, as the ones in the gallery. In the diffusers script a caption that asks for text keeps the text encoder through the denoising: the pipeline shows the text's images to the model from noise 0.9 down, which needs the prompt itself.
The same seed gives the same image when PyTorch is installed: it is optional for the MLX scripts, and only draws the starting noise, as diffusers does. In the tests done the MLX script's images matched the diffusers script's to the eye (31.8 to 38.6 dB PSNR, from the last bits of each step). Without PyTorch, MLX's own random generator draws the noise: an image as good, a different one for the same seed. A written caption can also come out slightly different from the diffusers script's: the same greedy writer, where a near-tie between two words can tip the other way (the portrait's caption matched for its first 716 characters).
MLX or mflux?
- The two give the same images: only the VAE decode differs (48 dB PSNR between them in the test done).
fibo2_edit_turbo_t2i_mlx.pyneeds only MLX, mlx-vlm and their dependencies.fibo2_edit_turbo_t2i_mflux.pyis for setups that already use mflux. It importsfibo2_edit_turbo_t2i_mlx.pyfor everything except the decode, so keep the two files together. FIBO 2.0 is not an mflux model; only its VAE, FLUX.2's, is, and the classes the script uses for it are mflux internals rather than a public API, so they may move between mflux releases (tested with mflux 0.22.0).- Dependency conflicts. mflux pins its own MLX range (0.22.0:
mlx>=0.32.0,<0.33.0) and installs PyTorch, while mlx-vlm 0.7.8 needsmlx>=0.32.4. Today the two ranges overlap. When a later mlx-vlm needs a newer MLX than mflux allows, pip cannot satisfy both, and upgrading one can downgrade the other's MLX. If pip reports a conflict, usefibo2_edit_turbo_t2i_mlx.py, which needs no mflux, or keep mflux in its own virtual environment.
Prompts
Fibo 2.0 reads two kinds of prompt:
- A VGL caption in JSON, the format it is trained on, and the one that gives the most control: counts, positions, lighting, camera and the exact text to render. The scripts write one from a plain idea by default; in ComfyUI, paste one into TextEncodeFibo2. Bria's VGL documentation describes every field.
- A plain prompt, a description in a sentence or a paragraph. Fibo 2.0 was also trained on short descriptions; use
--plainin the scripts, or type the sentence in ComfyUI. The examples show both kinds on the same 22 prompts.
A short caption looks like this; the full example, with objects, lighting, aesthetics and camera, is
assets/lake-pier.json:
{"short_description": "A bakery storefront at dawn with a hand-painted sign above the door.",
"lighting": {"conditions": "soft dawn light", "direction": "from the left"},
"style_medium": "photograph",
"text_render": [{"text": "FRESH BREAD", "location": "top-center", "font": "hand-painted serif"}]}
Examples
The 22 prompts in examples/prompts.json, rendered twice with the diffusers script from text alone, with
the same settings: Edit Turbo, 4 steps, no CFG, 1024×1024, seed 4242.
- Direct: the prompt as typed (
--plain), inexamples/direct/. - VGL: the model's own text encoder first writes the prompt into a VGL caption, and the caption is rendered, in
examples/vgl/. Writing a caption took about 70% as long as rendering the image in the runs done.
Each image has a JSON file of the same name beside it with the prompt, the caption (VGL only) and the settings. Click a thumbnail for the full image.
| Direct | VGL | Direct | VGL |
|---|---|---|---|
portrait |
portrait |
kingfisher |
kingfisher |
neonstreet |
neonstreet |
market |
market |
pizza |
pizza |
swordsman |
swordsman |
mecha |
mecha |
storybookfox |
storybookfox |
inventor |
inventor |
claychef |
claychef |
colonyship |
colonyship |
megacity |
megacity |
sorceress |
sorceress |
racecar |
racecar |
snowleopard |
snowleopard |
group5 |
group5 |
family4 |
family4 |
kittens3 |
kittens3 |
dogs2 |
dogs2 |
horserider |
horserider |
pianist |
pianist |
flamingos |
flamingos |
Three prompts it gets wrong: family4, pianist and colonyship
These prompts are explicit (four people, two hands, a detailed colony ship), so the misses below are not the prompts' fault. They come from the model, and in the VGL renders also from the caption the model's own text encoder wrote. A render from a caption corrected by hand shows which is which. All use the same seed and settings.
| Direct | VGL | Corrected caption | |
|---|---|---|---|
| family4 | |||
| pianist | |||
| colonyship |
family4: "A family of four having dinner at a round wooden table, seen from directly above, plates, glasses and bowls of food, warm evening light, photograph"
- Direct: six people around the table, with six place settings, seen from a high angle rather than straight down. With nothing but the prompt, the model miscounts on its own.
- VGL: six people as well. The written caption says "Four people — two adults and two children", but only in its summary sentence. The people are not listed as objects (their clothes and genders sit in the table's entry), while four place settings are. It also describes walls, a window and a framed family photo, none of which can be seen from directly above: the render shows the walls, and the photo adds more faces.
- Corrected caption: each person as their own object, one on each side of the table, a straight-down camera and
only the floor around the table: exactly four people, seen from directly above. The caption is in
examples/corrected/family4.json.
pianist: "Close-up of a pianist's two hands playing the keys of a grand piano, dramatic side light, photograph, sharp detail"
- VGL: the written caption adds "the curved body of the grand piano, visible from the side, with ornate legs", an eye-level camera and an 85 mm lens. A close-up of hands and the piano's legs seen from the side can't share one frame, so the render pulls back to a short keyboard on table legs, played by three hands.
- Direct: a much better picture: a grand piano and one pianist's two hands, but a second player's hands appear at the far end of the keyboard.
- Corrected caption: the left and the right hand of one pianist as two objects, and a keyboard close-up without the
piano's legs: one player's two hands, reflected in the glossy fallboard. The caption is in
examples/corrected/pianist.json. - In all three the black keys are wrong: they run evenly, three or four in a row, where a piano groups them in twos and threes. That one is the model's; the corrected caption asks for the groups and doesn't get them.
colonyship: "A gleaming white colony ship in orbit above a turquoise ocean planet, smooth curved hull, glowing cyan engine rings, brilliant sunlight, clean sci-fi concept art, bold simple shapes, vivid colors"
- Direct: a detailed ship, with panel lines, windows and engine housings, over an ocean planet with clouds, the sun overhead.
- VGL: a smooth, featureless hull under a pale daytime sky. The writer reads "clean sci-fi concept art, bold simple
shapes" as an order to remove detail: its caption asks for "no clutter, no noise", a hull with "no visible windows or
rivets", engine rings with "no visible mechanical parts", "a vast, empty space with no stars" and a sky in "a gradient
of soft white to pale blue". It isn't the seed: the same caption at seed 7 gives the same plain ship. It isn't one
unlucky caption either: three more, written with
--sample 1,2and3, ask for the same ("no visible doors or details", "no visible windows or detail", "no visible seams or rivets"). - Corrected caption: the same caption with those lines replaced by fine panel lines, rows of small windows,
docking ports and antennas, housings around the engine rings, clouds over the ocean and black space with stars: a
detailed ship over the planet's curved horizon, the sun in the corner. The caption is in
examples/corrected/colonyship.json.
When a count, a layout or the amount of detail matters, open the caption the script saved beside the image: give
every person or animal its own object, keep the camera and the background consistent with each other, remove what the
writer added against the prompt, and render it again with --json. --sample N writes another take of the caption.
Licences
- This repository (the workflows, the scripts and these notes): Apache-2.0, see
LICENSE. - The models are not part of this repository and keep their owners' licences. Fibo 2.0 Dev and Edit Turbo, and the ComfyUI files and GGUF quants made from them, are under Bria AI's CC BY-NC 4.0 licence: non-commercial use, with attribution to Bria. Commercial use needs an agreement with Bria, see the model page. The text encoder and the VAE keep their own licences.
- bria-vgl, whose instructions the scripts download to write captions, is MIT-licensed by Bria AI.
- MLX, mlx-vlm and mflux, which the Apple silicon scripts install, are MIT-licensed by their authors. The MLX scripts' transformer port and text-image drawing follow diffusers' FIBO 2.0 code (Apache-2.0, Bria AI and Hugging Face).