huggingface / huggingface/diffusers
bria_fibo model/pipeline review
- 主要言語
- Python
- スター
- 34.5k
- フォーク
- 7.3k
- 平均マージ
- 3日 3時間
- マージ済み PR(30日)
- 91
説明
# `bria_fibo` model/pipeline review
Commit tested: `0f1abc4ae8b0eb2a3b40e82a310507281144c423`
Review performed against the repository review rules.
Duplicate search: checked GitHub issues/PRs for `bria_fibo`, `BriaFibo`, `FIBO`, affected class names, and failure modes. Found integration/refactor PRs `#12545`, `#12688`, `#12731`, `#12930`, `#13341`; no duplicate for the issues below. Public top-level imports succeeded.
Test note: standalone reproductions ran with `.venv`. Full target pytest collection failed before running tests because this Windows torch build lacks `torch._C._distributed_c10d`.
## Issue 1: `prompt_embeds` is public but unusable
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L254-L332
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L412-L490
Problem:
Both pipelines expose `prompt_embeds`, but `encode_prompt()` only defines `prompt_layers` when it encodes `prompt` itself. Passing precomputed embeddings raises `UnboundLocalError`. `negative_prompt_embeds` is also not honored because negative embeddings are always recomputed when `guidance_scale > 1`.
Impact:
Users cannot use documented precomputed embedding workflows, prompt weighting, cached text encoder outputs, or callback-modified embeddings reliably.
Reproduction:
```python
import torch
from types import SimpleNamespace
from diffusers import BriaFiboPipeline
pipe = BriaFiboPipeline.__new__(BriaFiboPipeline)
pipe.transformer = SimpleNamespace(dtype=torch.float32)
pipe.text_encoder = SimpleNamespace(dtype=torch.float32)
pipe.encode_prompt(
prompt=None,
prompt_embeds=torch.zeros(1, 1, 64),
guidance_scale=1.0,
device=torch.device("cpu"),
)
```
Relevant precedent:
Flux validates all required precomputed conditioning inputs together:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/flux/pipeline_flux.py#L494-L500
Suggested fix:
```python
if prompt_embeds is not None and prompt_layers is None:
raise ValueError("`prompt_embeds` requires precomputed `prompt_layers`, or pass `prompt` instead.")
```
Better: add public `prompt_layers` / `negative_prompt_layers` inputs and honor `negative_prompt_embeds` instead of recomputing it.
## Issue 2: Custom `timesteps` are ignored
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L466-L480
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L674-L680
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L626-L642
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L892-L898
Problem:
`timesteps` is accepted and documented, but both pipelines call `retrieve_timesteps(..., timesteps=None, sigmas=sigmas, ...)`.
Impact:
Users requesting a custom timestep schedule silently get the default schedule.
Reproduction:
```python
import inspect
from diffusers import BriaFiboPipeline, BriaFiboEditPipeline
for cls in (BriaFiboPipeline, BriaFiboEditPipeline):
source = inspect.getsource(cls.__call__)
assert "timesteps=None" not in source, f"{cls.__name__} drops custom timesteps"
```
Relevant precedent:
The shared helper supports `timesteps`:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/flux/pipeline_flux.py#L88-L129
Suggested fix:
```python
sigmas = None if timesteps is not None else np.linspace(1.0, 1 / num_inference_steps, num_inference_steps)
timesteps, num_inference_steps = retrieve_timesteps(
self.scheduler,
num_inference_steps=num_inference_steps,
device=device,
timesteps=timesteps,
sigmas=sigmas,
mu=mu,
)
```
## Issue 3: Tensor images crash in `BriaFiboEditPipeline`
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L809-L812
Problem:
The tensor-image path reads `self.latent_channels`, but that attribute is never defined.
Impact:
`image=torch.Tensor(...)` is accepted by validation and documented typing, but crashes before preprocessing.
Reproduction:
```python
import torch
from diffusers import BriaFiboEditPipeline
pipe = BriaFiboEditPipeline.__new__(BriaFiboEditPipeline)
image = torch.zeros(1, 3, 32, 32)
if image is not None and not (isinstance(image, torch.Tensor) and image.size(1) == pipe.latent_channels):
pass
```
Relevant precedent:
N/A.
Suggested fix:
```python
if image is not None:
image = self.image_processor.resize(image, height, width)
image = self.image_processor.preprocess(image, height, width)
```
If latent image input is intended, define the latent channel count from `self.transformer.config.in_channels` and validate it explicitly.
## Issue 4: Multiple generated images get malformed output shape
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L772-L780
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L995-L1003
Problem:
Each per-sample `postprocess(..., output_type="np")` returns shape `(1, H, W, C)`, then the pipeline uses `np.stack`, producing `(N, 1, H, W, C)` instead of `(N, H, W, C)`. PIL output becomes nested lists.
Impact:
`num_images_per_prompt > 1` returns an incompatible output structure.
Reproduction:
```python
import numpy as np
per_sample = [np.zeros((1, 32, 32, 3)), np.zeros((1, 32, 32, 3))]
print(np.stack(per_sample, axis=0).shape) # (2, 1, 32, 32, 3)
```
Relevant precedent:
Bria decodes and postprocesses the batch directly:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria/pipeline_bria.py#L730-L733
Suggested fix:
```python
curr_image = self.image_processor.postprocess(curr_image.squeeze(dim=2), output_type=output_type)
if output_type == "np":
image.append(curr_image[0])
else:
image.extend(curr_image)
...
if output_type == "np":
image = np.stack(image, axis=0)
```
## Issue 5: Edit pipeline does not duplicate image latents for `num_images_per_prompt`
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L831-L842
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L1037-L1049
Problem:
`prepare_image_latents()` receives `batch_size * num_images_per_prompt`, but the encoded image batch remains at the original image batch size before reshape.
Impact:
`BriaFiboEditPipeline(..., image=..., num_images_per_prompt=2)` fails with an invalid reshape. The fast tests skip batching, so this is not covered.
Reproduction:
```python
import torch
from diffusers import BriaFiboEditPipeline
latents = torch.zeros(1, 16, 2, 2)
BriaFiboEditPipeline._pack_latents_no_patch(
latents=latents,
batch_size=2,
num_channels_latents=16,
height=2,
width=2,
)
```
Relevant precedent:
N/A.
Suggested fix:
```python
repeat_by = batch_size // image_latents_bchw.shape[0]
image_latents_bchw = image_latents_bchw.repeat_interleave(repeat_by, dim=0)
```
Also unskip/add batch tests for edit.
## Issue 6: `guidance_embeds=True` cannot construct the transformer
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_bria_fibo.py#L415-L426
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_bria_fibo.py#L472-L473
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_bria_fibo.py#L558-L559
Problem:
`BriaFiboTimestepProjEmbeddings` requires `time_theta`, but `guidance_embed` is constructed without it. The forward path also uses `if guidance:` on a tensor.
Impact:
Any config/checkpoint with `guidance_embeds=True` fails during model construction, and the forward branch would be ambiguous for multi-element tensors after construction is fixed.
Reproduction:
```python
from diffusers import BriaFiboTransformer2DModel
BriaFiboTransformer2DModel(
patch_size=1,
in_channels=16,
num_layers=1,
num_single_layers=1,
attention_head_dim=8,
num_attention_heads=2,
joint_attention_dim=64,
text_encoder_dim=32,
axes_dims_rope=[0, 4, 4],
guidance_embeds=True,
)
```
Relevant precedent:
Flux checks `guidance is None`, not tensor truthiness:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_flux.py#L682-L690
Suggested fix:
```python
if guidance_embeds:
self.guidance_embed = BriaFiboTimestepProjEmbeddings(
embedding_dim=self.inner_dim,
time_theta=time_theta,
)
...
if guidance is not None:
temb += self.guidance_embed(guidance, dtype=hidden_states.dtype)
```
## Issue 7: Dense additive attention masks disable flash/sage attention
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L647-L653
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L852-L871
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_bria_fibo.py#L111-L118
Problem:
The pipelines convert padding masks into dense `(B, 1, L, L)` additive float masks. This is only padding information and can be represented as a bool key mask, but dense masks hard-fail for flash-attn and sage backends.
Impact:
Users selecting optimized attention backends hit avoidable runtime failures.
Reproduction:
```python
import torch
from diffusers.pipelines.bria_fibo.pipeline_bria_fibo import BriaFiboPipeline
from diffusers.models.attention_dispatch import _flash_attention
mask = torch.tensor([[1, 1, 0, 1]], dtype=torch.float32)
dense_mask = BriaFiboPipeline._prepare_attention_mask(mask).unsqueeze(1)
q = k = v = torch.randn(1, 4, 2, 8)
_flash_attention(q, k, v, attn_mask=dense_mask)
```
Relevant precedent:
QwenImage builds a bool joint mask instead:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_qwenimage.py#L946-L952
Suggested fix:
```python
attention_mask = torch.cat([prompt_attention_mask, latent_attention_mask], dim=1).to(torch.bool)
attention_mask = attention_mask[:, None, None, :]
self._joint_attention_kwargs["attention_mask"] = attention_mask
```
## Issue 8: VAE scale factor is hardcoded instead of read from config
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L110-L112
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L268-L270
Problem:
Both pipelines set `self.vae_scale_factor = 16` even though `AutoencoderKLWan` stores `scale_factor_spatial` in config.
Impact:
Custom or future Fibo-compatible VAEs with a different spatial scale serialize/load correctly but produce wrong latent sizes in the pipeline.
Reproduction:
```python
from diffusers import AutoencoderKLWan, BriaFiboPipeline
vae = AutoencoderKLWan(base_dim=8, decoder_base_dim=8, num_res_blocks=1, z_dim=4, dim_mult=[1], temperal_downsample=[])
pipe = BriaFiboPipeline(transformer=None, scheduler=None, vae=vae, text_encoder=None, tokenizer=None)
print(vae.config.scale_factor_spatial) # 8
print(pipe.vae_scale_factor) # 16
```
Relevant precedent:
Wan reads the VAE scale factor from config:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/wan/pipeline_wan.py#L154-L156
Suggested fix:
```python
self.vae_scale_factor = self.vae.config.scale_factor_spatial if getattr(self, "vae", None) else 16
```
## Issue 9: Transformer is missing `_no_split_modules`
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_bria_fibo.py#L430-L445
Problem:
The model enables gradient checkpointing but does not declare `_no_split_modules` for its transformer blocks.
Impact:
`device_map` / offload placement can split residual attention blocks across devices, unlike comparable transformer integrations.
Reproduction:
```python
from diffusers import BriaFiboTransformer2DModel
print(getattr(BriaFiboTransformer2DModel, "_no_split_modules", None))
```
Relevant precedent:
Flux declares both block classes:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/models/transformers/transformer_flux.py#L565-L567
Suggested fix:
```python
_no_split_modules = ["BriaFiboTransformerBlock", "BriaFiboSingleTransformerBlock"]
```
## Issue 10: Edit example docstring is stale and not runnable
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo_edit.py#L53-L86
Problem:
The file contains `# TODO: Update example docstring`, imports `ModularPipeline`, then uses undefined `ModularPipelineBlocks`.
Impact:
Generated docs include a broken example, and the TODO violates the review rule against ephemeral PR-context comments.
Reproduction:
```python
namespace = {}
exec(
"from diffusers.modular_pipelines import ModularPipeline\n"
"ModularPipelineBlocks.from_pretrained('briaai/FIBO-VLM-prompt-to-JSON')",
namespace,
)
```
Relevant precedent:
The text-to-image Fibo example uses `ModularPipeline.from_pretrained`:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/src/diffusers/pipelines/bria_fibo/pipeline_bria_fibo.py#L51-L57
Suggested fix:
```python
vlm_pipe = ModularPipeline.from_pretrained("briaai/FIBO-VLM-prompt-to-JSON", trust_remote_code=True)
```
Also remove the TODO and verify the model id casing.
## Issue 11: Slow tests are missing
Affected code:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/tests/models/transformers/test_models_transformer_bria_fibo.py#L29-L37
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/tests/pipelines/bria_fibo/test_pipeline_bria_fibo.py#L39-L47
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/tests/pipelines/bria_fibo_edit/test_pipeline_bria_fibo_edit.py#L40-L47
Problem:
Fast model and pipeline tests exist, but there are no `@slow` tests for `BriaFiboPipeline` or `BriaFiboEditPipeline`.
Impact:
The gated real checkpoints are never exercised for loading, dtype/offload behavior, output shape, JSON prompt handling, or edit image/mask behavior.
Reproduction:
```python
from pathlib import Path
paths = [
Path("tests/models/transformers/test_models_transformer_bria_fibo.py"),
Path("tests/pipelines/bria_fibo/test_pipeline_bria_fibo.py"),
Path("tests/pipelines/bria_fibo_edit/test_pipeline_bria_fibo_edit.py"),
]
print({str(path): "@slow" in path.read_text() for path in paths})
```
Relevant precedent:
Bria has a slow pipeline test:
https://github.com/huggingface/diffusers/blob/0f1abc4ae8b0eb2a3b40e82a310507281144c423/tests/pipelines/bria/test_pipeline_bria.py#L241-L245
Suggested fix:
Add gated slow smoke tests for `briaai/FIBO` and `briaai/Fibo-Edit`, using `torch_dtype=torch.bfloat16`, `enable_model_cpu_offload()`, a short schedule, deterministic seed/generator, and expected output shape/value slices.
コントリビューションガイド
調査の方向性
Start with the affected files under src/diffusers/pipelines/bria_fibo/ and src/diffusers/models/transformers/transformer_bria_fibo.py, then run the standalone reproductions in the issue. Treat the eight findings as separate regressions and add targeted coverage for embeddings, timesteps, tensor images, batching, guidance, attention masks, and configuration-driven scaling. Done means the documented inputs work without the reported exceptions or malformed outputs, with regression tests passing where collection is available.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python, pytorch
- 領域
- computer-vision, machine-learning, testing
- issue の種類
- バグ
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 25/100