Skip to content

Add Bria fibo-2 - #14991

Open
muhammadali-afridi wants to merge 1 commit into
huggingface:mainfrom
muhammadali-afridi:ali/fibo2
Open

muhammadali-afridi wants to merge 1 commit into
huggingface:mainfrom
muhammadali-afridi:ali/fibo2

Conversation

@muhammadali-afridi

@muhammadali-afridi muhammadali-afridi commented Oct 8, 2026 •

Copy link
Copy Markdown

What does this PR do?

Adds fibo-2, Bria's text-to-image and image-editing model.

  • BriaFibo2Transformer2DModel: an 8.1B flow-matching transformer with a single token stream, in the style of Z-Image. Its text encoder is Qwen3-VL-4B.

    • A Perceiver condenses Qwen3-VL's hidden states into gist tokens, which join the image tokens.
    • Five blocks also read Qwen3-VL through gated cross-attention.
    • Images to edit come in as context_latents. Each is patchified by the shared embedder and gets its own RoPE plane.
  • BriaFibo2Pipeline:

    • text-to-image from structured JSON captions;
    • editing of up to 5 images, with an optional mask;
    • captions cleaned and serialized the way training did, for generation and edits, in every caption form fibo-2 was trained with: a full caption, a short description (plain text, or "structured_caption": "..." in an edit), or a short description with its text_render list;
    • images of the caption's text, which Qwen3-VL sees beside the prompt. The pipeline draws them the way training did, by default (render_text_images=False turns them off), or the caller passes them as text_images.

    The checkpoint runs 30 steps with guidance 5, the pipeline's defaults. The pipeline also runs few-step distilled checkpoints: guidance_scale=1.0 turns guidance off.

  • scripts/convert_bria_fibo2_to_diffusers.py converts the original checkpoints.

  • Docs and tests.

Weights: the docs point to briaai/fibo-2, where the weights will be released. The repo is private until then, and we're happy to give reviewers early access.

Verification

I compared the pipeline against Bria's reference inference code, using the original checkpoints, the same seeds and bf16:

  • A100, SDPA:

    • Text-to-image is pixel-identical, for the full checkpoint and a 4-step distilled one.
    • Editing is pixel-identical when the text encoder gets the same images as the reference.
  • H100: the reference code runs FlashAttention-3 there. With pipe.transformer.set_attention_backend("_flash_3_varlen_hub"):

    • text-to-image is pixel-identical for both checkpoints;
    • editing is pixel-identical too (2 full-checkpoint cases and 4 distilled ones).
  • Prompts and text images: compared with Bria's training and evaluation code, every prompt is byte-identical:

    • the 215 captions of a text-to-image benchmark, in the full and short forms, compact and pretty-printed (860 prompts), with the prompts that mark and blank their text images, and the images;
    • the 115 captions of an edit benchmark, in the full and short forms, with and without text images (460 prompts).

    The drawn images are also byte-identical on 17 test strings, including non-Latin scripts, wrapped lines and characters no font has.

  • Text-encoder images: by default the pipeline thumbnails each image straight to 768 px for Qwen3-VL, as in training. The reference code upsamples 4脳 first, which changes that input slightly.

  • Batching: in float32, a batch of prompts of different lengths matches the separate single-prompt calls. This includes the varlen attention backends; see the self-review notes.

  • Checks (rebased on main):

    • make style, make quality and make fix-copies pass.
    • check_copies, check_dummies, check_support_list, check_forward_call_docstrings and check_return_annotations pass.
  • New tests: they pass on a Mac (CPU/MPS), except the group offloading and layerwise casting memory tests. Those fail the same way for Z-Image and Flux 2 on that machine, because MPS has no CUDA streams and no float8.

Notes

  • Weights: the diffusers-format weights go up to briaai/fibo-2 before the release.
  • mask: fibo-2 was trained on edits whose image has the region to regenerate greyed out. The pipeline does the same: flat (128, 128, 128) grey, through the mask made binary at 128.
  • Fonts for text images: Pillow's built-in font draws most text. For characters it lacks, the pipeline uses Aileron (CC0) and DejaVu Sans (Bitstream Vera license), as training did. It reads them from the fonts folder of briaai/fibo-2 only when a text first needs them, so ASCII text never downloads anything. The fonts are already in briaai/fibo-2/fonts/.
  • Caption cleaning: no training caption had empty values or the aesthetic_score and preference_score fields. The pipeline drops them from text-to-image and edit captions alike and serializes compactly. The negative prompt is used as given.
  • Standard vs modular: this is a standard pipeline. Happy to add a modular one if that's preferred.

Self-review notes

I ran the self-review skill on the diff.

Fixed:

  • The transformer forward docstring had no Returns: section, which check_forward_call_docstrings flags.
  • Varlen backends kept the wrong keys.
    • With prompts of different lengths, the padded gist tokens sat between the real gist tokens and the image tokens.
    • The varlen backends (flash_varlen, _flash_3_varlen_hub, sage_varlen) keep the first mask.sum() keys, so they kept the wrong ones.
    • Padded gist tokens now go last. test_padded_batch_matches_single_prompts covers this.
  • Removed dead code: a PyTorch 2.0 check in the attention processor, and casts that changed nothing.
  • __call__ read the first image's size before check_inputs had validated it.

Not fixed, on purpose:

  • Full-graph compile tests are skipped. RopeEmbedder, copied from Z-Image, builds its frequency table under a device context on first use. Z-Image skips these tests for the same reason.
  • Gist counts break the graph under torch.compile(transformer).
    • With a text mask, the gist count per prompt comes from the text lengths through .tolist().
    • Regional compilation (compile_repeated_blocks) is not affected.

Before submitting

  • Did you use an AI agent (Claude Code, Codex, Cursor, etc.) to help with this PR? If so:
    • Did you read the Coding with AI agents guide?
    • Did you run the self-review skill on the diff?
    • Did you share the final self-review notes in the PR description or a comment?
  • Did you read the contributor guideline?
  • Did you read our philosophy doc? (important for complex PRs)
  • Was this discussed/approved via a GitHub issue or the forum? Please add a link to it if that's the case.
  • Did you make sure to update the documentation with your changes?
  • Did you write any new necessary tests?
  • Are you the author (or part of the team) of the model/pipeline (only applicable for model/pipeline related PRs)?

Who can review?

@yiyixuxu @sayakpaul @DN6

馃 Generated with Claude Code

@github-actions github-actions Bot added documentation Improvements or additions to documentation models tests utils pipelines size/L PR with diff > 200 LOC labels Oct 8, 2026
@muhammadali-afridi
muhammadali-afridi force-pushed the ali/fibo2 branch 2 times, most recently from e3fdebc to 2b7b792 Compare October 15, 2026 08:47
@muhammadali-afridi
muhammadali-afridi marked this pull request as ready for review October 15, 2026 08:51
@muhammadali-afridi
muhammadali-afridi force-pushed the ali/fibo2 branch 2 times, most recently from 553af68 to 5c38cb1 Compare October 15, 2026 09:36
fibo-2 is Bria's 8.1B flow-matching DiT, built on the Z-Image block and
conditioned on Qwen3-VL hidden states two ways: a Perceiver resampler turns
them into gist tokens that share the stream with the image tokens, and five
blocks add gated cross-attention to their own bundle of Qwen3-VL layers. It
uses the Flux 2 VAE.

One pipeline class covers both of the model's jobs and both checkpoints:
text-to-image generation, instruction editing of up to five images with an
optional mask, the turbo checkpoint (4 steps, no guidance) and the guided one.

- BriaFibo2Transformer2DModel, with images to edit passed as context latents
- BriaFibo2Pipeline, including:
  - captions cleaned and serialized the way training did, for generation and
    edits, in every caption form fibo-2 was trained with: a full caption, a
    short description, or a short description with its text_render list
  - images of the caption's text, which Qwen3-VL sees beside the prompt:
    drawn the way training drew them, by default (`render_text_images`), or
    passed as `text_images`
  - masked edits, the region greyed out through a binary mask as in training
- a conversion script from the original checkpoint layout
- model and pipeline tests, and docs

Verified against Bria's reference implementation on an A100 and an H100.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation models pipelines size/L PR with diff > 200 LOC tests utils

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant