Skip to content

[meta issue] Systematic model/pipeline review findings / tracking #13656

Open

Description

@hlky

[meta issue] Systematic model/pipeline review findings / tracking

Commit tested: 0f1abc4ae8b0eb2a3b40e82a310507281144c423

Review performed against the repository review rules.

Summary

  • Reviewed 76 model/pipeline/shared/infrastructure targets
  • Aggregated 498 issue-level findings into recurring cross-family patterns
  • Findings suggest systemic inconsistencies rather than isolated bugs

These patterns are already generating duplicate low-effort PRs (often agent-generated) for the same underlying issues, increasing maintainer review load without addressing root causes.

Duplicate Check

Searches for broad/meta tracking issues or PRs did not find an existing systematic tracker. Some individual patterns are partially known through targeted issues/PRs, for example #11762, #9371, #8989, #12533, and PR #13532, but those do not address the recurring root causes across families.

Pattern 1: Batch and Conditioning Expansion Drift

Description:
Many pipelines accept batched prompts, images, masks, latents, or num_images_per_prompt / num_videos_per_prompt, but only expand part of the conditioning state.

Root cause:
Batch construction is duplicated per pipeline instead of enforced by a shared invariant after prompt/image/control/mask preparation.

Impact:
Incorrect conditioning, crashes, silently ignored extra outputs, and non-reproducible batched generation.

Representative examples:

Pattern 2: Public Arguments Accepted but Ignored

Description:
Several public APIs validate or document arguments such as latents, attention_kwargs, cross_attention_kwargs, max_sequence_length, timesteps, num_frames, masks, or callbacks, but do not actually consume them.

Root cause:
Signatures and validation are often copied from related pipelines without shared checks that accepted inputs affect execution.

Impact:
Silent no-op behavior is worse than an explicit error because users believe they controlled generation when they did not.

Representative examples:

Pattern 3: Mask Handling Is Inconsistent Across Layers

Description:
attention_mask, prompt masks, VAE masks, IP-Adapter masks, and padding masks are frequently accepted but dropped, duplicated in the wrong order, or passed into attention code with incompatible shapes.

Root cause:
Mask semantics are not centralized. Pipeline encoders, model forwards, and custom attention processors each implement partial conventions.

Impact:
Padded tokens can affect outputs, regional conditioning can silently fail, and valid shorter masks can crash.

Representative examples:

Pattern 4: Optional Parameters Are Not Actually Optional

Description:
Documented defaults such as None, omitted optional dependencies, or default constructor values often crash before fallback logic runs.

Root cause:
Validation order and kwargs.pop(...) patterns assume loader or caller internals rather than the public API contract.

Impact:
Public APIs fail on documented paths, offline/local-only workflows can unexpectedly hit the network, and dependency errors become confusing Python exceptions.

Representative examples:

Pattern 5: Dtype, Device, and Config Assumptions Leak

Description:
Provided tensors are often not moved/cast to execution dtype, helpers create float64/float32 tensors unconditionally, and pipelines hardcode VAE scale factors or latent channel counts.

Root cause:
Low-level model/config invariants are not enforced at pipeline boundaries, and shared dtype/device helpers are used unevenly.

Impact:
Mixed precision, NPU/MPS, CPU offload, device_map, and reproducibility paths fail or produce inconsistent behavior.

Representative examples:

Pattern 6: Output and Cleanup Contracts Diverge

Description:
output_type="latent", return_dict=False, output class exports, lazy imports, watermarking, and maybe_free_model_hooks() are handled differently across related families.

Root cause:
Finalization branches are duplicated and often return early before shared cleanup/output wrapping.

Impact:
Offload hooks can leak, return types become non-standard, imports fail, and downstream code cannot rely on pipeline output contracts.

Representative examples:

Pattern 7: Validation Does Not Match Runtime Requirements

Description:
Input validation accepts dimensions, scheduler paths, image types, or tensor/list combinations that later fail in patchification, latent packing, scheduler stepping, or preprocessing.

Root cause:
Validation is copied from neighboring pipelines instead of derived from actual transformer patch size, VAE scale factor, scheduler requirements, and supported input processors.

Impact:
Users get late runtime failures, silent truncation, or invalid generation states instead of actionable input errors.

Representative examples:

Pattern 8: Copy-Paste Divergence and Hidden Coupling

Description:
Variant pipelines drift from base pipelines, modular pipelines import classic pipeline internals, and generated docs or TODO placeholders remain in user-facing artifacts.

Root cause:
Families evolve through parallel copies rather than shared helpers or parity tests. Modular and classic implementations are not cleanly separated.

Impact:
Fixes land in one variant but not another, refactors create hidden breakage, and docs/tests stop reflecting actual public APIs.

Representative examples:

Pattern 9: Shared Infrastructure Invariants Are Weak

Description:
Shared model/pipeline APIs assume attention processors, cache contexts, offload hooks, QKV fuse/unfuse state, lazy exports, and _no_split_modules metadata are implemented consistently.

Root cause:
Mixins expose common public APIs, but custom model families can bypass required integration points without a shared compliance test.

Impact:
Optimization APIs become unreliable across families, and failures show up only when users enable attention backends, offload, parallelism, or device maps.

Representative examples:

Pattern 10: Slow and Integration Coverage Is Uneven

Description:
Fast tests often exist, but many are dummy-only, skipped, placeholder-based, nightly-only, or absent for public variants. Slow tests are missing for many real checkpoint paths.

Root cause:
Coverage is family-local and variant-local; there is no enforced matrix for exported public pipelines/models, real checkpoint smoke tests, output contracts, dtype/device paths, and batch/CFG behavior.

Impact:
Bugs survive in exactly the paths users exercise: real tokenizers, real schedulers, offload, mixed precision, latent outputs, batched generation, and model loading.

Representative examples:

Many of these issues can be addressed at the shared/infrastructure layer (e.g. batch construction, mask propagation, dtype/device normalization) rather than per-pipeline. Fixing them centrally would eliminate repeated PRs and prevent reintroduction across families.

Cross-Layer Connections

  • Mask bugs repeatedly cross the pipeline/model boundary: pipelines build masks, but model forwards or attention processors drop or reshape them inconsistently.
  • Dtype/device bugs appear both in pipeline inputs and shared model helpers, suggesting shared casting/config enforcement should happen before family-specific code runs.
  • Attention backend issues are model-level omissions that surface as pipeline API failures because public backend toggles appear to succeed.
  • Modular pipeline issues connect generated docs, block IO contracts, classic-pipeline imports, and infrastructure selection logic.

Test Coverage Analysis

Fast tests are present for many families, but they often cover tiny happy paths and do not exercise real checkpoint loading, public variant exports, mixed precision, CPU offload, callback mutation, or batch/CFG edge cases.

Slow/integration gaps correlate strongly with discovered bugs. Families with missing or weak slow coverage repeatedly contain failures in num_images_per_prompt, num_videos_per_prompt, output_type="latent", precomputed embeddings, and real tokenizer/scheduler behavior.

Explicit skipped TODO slow tests were called out for:

Other weak-test patterns include placeholder assertions in consisid, random/placeholder expected outputs in mochi, passing TODO stubs in hunyuandit, skipped offload/batch paths in shap_e, and non-meaningful decode coverage in allegro.

Suggested Prioritization

  1. Batch/conditioning invariants (Pattern 1)
  2. Ignored public arguments (Pattern 2)
  3. Mask propagation (Pattern 3)
  4. Dtype/device normalization (Pattern 5)
  5. Optional parameter handling (Pattern 4)
  6. Shared infrastructure invariants (Pattern 9)
  7. Validation/runtime alignment (Pattern 7)
  8. Output/cleanup consistency (Pattern 6)
  9. Copy-paste divergence (Pattern 8)
  10. Test coverage (Pattern 10)

Tracking

This issue is intended as a tracking and coordination layer for already identified problems. Individual issues contain reproductions and fixes and can be addressed incrementally.

Activity

  1. yiyixuxu commented on Apr 30, 2026

    @yiyixuxu
    Collaborator

    thanks for putting this together @hlky

    can we start with Pattern 1? in addition to fix the invidiual pipelines, can we also:

    1. add a test in test suit that would fail for all pipeines has this issue
    2. add a point in our agent doc to check for this pattern in their reviews?
  2. hlky commented on Apr 30, 2026

    @hlky
    ContributorAuthor

    @yiyixuxu There are currently a few different styles used across the codebase for expanding tensors when supporting num_*_per_prompt:

    • repeat + view (most common), often annotated as "MPS friendly"
    • repeat_interleave, used in a number of pipelines and helpers
    • torch.cat([x] * n, dim=0), which appears less frequently
    • x.repeat((n, ...)), which directly expands along the batch dimension

    The "MPS friendly" note on the reshape-based approach appears to be historical. To verify whether this is still relevant, I created a small benchmark comparing repeat + view vs repeat_interleave across representative shapes and dtypes used in Diffusers:

    • CLIP-style embeddings (e.g. [B, 77, 768/1024/1280])
    • T5-style embeddings (e.g. [B, 256/512, 4096])
    • 2D projection / pooled embeddings (e.g. [B, D])
    • dtypes: float32, float16, bfloat16
    • batch sizes {1, 2, 4} and repeat factors {1, 2, 3, 8}

    Benchmark script: https://gist.github.com/hlky/f2ead6ec0df4ceb10173a0b77350a666

    On ROCm (where performance differences tend to be more visible), the results show:

    • Correctness: outputs are identical in all tested cases
    • Performance: repeat_interleave is consistently at parity or slightly faster (typically ~1.03-1.13x)
    • Scaling: no repeat factor or batch size where repeat + view becomes meaningfully faster
    • Edge cases: minor regressions for very small 2D tensors (~5-10%), but these are negligible in practice

    The torch.cat([x] * n, dim=0) pattern is also worth avoiding as a standard approach:

    • it is less efficient, as it materializes multiple references before concatenation
    • it is less explicit semantically than batch-wise expansion
    • it can be error-prone (e.g. incorrect dimension, accidental shallow copies in more complex cases)
    • it does not compose well with more complex conditioning structures

    The x.repeat((n, ...)) pattern produces interleaved layouts (e.g. [A, B] → [A, B, A, B]) rather than contiguous per-prompt grouping ([A, A, B, B]), which can silently misalign conditioning.

    Given that:

    • repeat_interleave expresses the intended semantics directly (batch-wise expansion)
    • it avoids shape/layout assumptions required by the repeat + view pattern
    • it already appears in multiple parts of the codebase
    • and there is no measurable performance advantage to the reshape-based approach

    it seems reasonable to standardize on repeat_interleave(..., dim=0) as the default invariant for batch expansion.

    This would also help eliminate a number of subtle bugs observed across pipelines where partial or inconsistent expansion leads to mismatched conditioning, masks, or latents.

    That said, it would be useful to confirm this on MPS across Apple Silicon devices (e.g. M1/M2/M3), since the original rationale appears to have been backend-specific. If anyone is able to run the benchmark on MPS and share results, that would help validate that there are no remaining regressions there.

    Curious what you all think about standardizing on repeat_interleave going forward, and whether you’d prefer to:

    • adopt it as the default pattern for new code,
    • gradually migrate existing pipelines,
    • or introduce a small helper to enforce a consistent expansion invariant across families.[1]

    [1] Helper like:

    import torch
    from typing import Optional
    
    def _expand_batch(tensor: Optional[torch.Tensor], num_per_prompt: int) -> Optional[torch.Tensor]:
        if tensor is None:
            return None
        if num_per_prompt == 1:
            return tensor
        return torch.repeat_interleave(
            tensor,
            repeats=num_per_prompt,
            dim=0,
            output_size=tensor.shape[0] * num_per_prompt, # avoids sync https://docs.pytorch.org/docs/2.11/generated/torch.repeat_interleave.html
        )

    Pattern 5 could also benefit from a small helper:

    import torch
    
    def _preferred_float_dtype(device: torch.device) -> torch.dtype:
        if device.type in {"mps", "npu"}:
            return torch.float32
        return torch.float64
  3. hlky commented on May 6, 2026

    @hlky
    ContributorAuthor

    @yiyixuxu I found that fixing a recurring pattern across all models and pipelines in one pass is a bit tricky, since the agent tends to lose context due to the overall size of the changes. I think it would be better to go through them systematically, one model/pipeline at a time.

    For example, see #13684 and #13679. Handling these individually also makes room for deeper manual review alongside the pattern fix. In stable_video_diffusion, for instance, I was also able to fix some existing skipped tests while reviewing the pipeline.

    If you’re interested in the agent-assisted workflow, I’d be happy to share the prompts and process I’ve been using. This might also make it easier to open up the work to more contributors, since each model/pipeline can be tackled independently with a clearer scope.

  4. yiyixuxu commented on May 6, 2026

    @yiyixuxu
    Collaborator

    thanks @hlky

    per-pipeline PRs work for me. I think maintainers can start to review the issues, validate what's need to be fixed and then open it up to the community

    a few of the patterns I'd still want to tackle as a single refactor though, for example the batch expansion, I'd lean tow3ard adding a small helper that we copy across pipelines, but we can focus on the newer ones for now (qwen/wan/flux/flux2) since these are what people use as reference anyway. Thi can be done in parallel or after the per-pipeline fixes

    for the agent-assistend workflow, feele free to share with the community as a disucssion post. If you have any feedbacks on our claude CI workflow/ agents.mds and review rules, feel free to share with us too

  5. hlky commented on May 7, 2026

    @hlky
    ContributorAuthor

    @yiyixuxu As an example #13693 #13694 #13695 were produced with:

    Prompt

    Codex Desktop (subagents enabled)

    GPT5.5 Extra High

    You are working on `diffusers` (`huggingface/diffusers` is `upstream/main`).
    
    https://github.com/huggingface/diffusers/issues/13656 is a meta issue about a systemic review of models/pipelines.
    
    The meta issue identifies common patterns and tracks individual reviews.
    
    Individual reviews contain verified issues and fixes. The fix may be either a snippet for small fixes or guidance for larger fixes.
    
    Examples of completed work: https://github.com/huggingface/diffusers/issues/13577 https://github.com/huggingface/diffusers/pull/13679 https://github.com/huggingface/diffusers/pull/13684
    
    Choose a target from the meta issue. Use subagents to iteratively complete work on the target. Fix the identified issues in the individual review. Perform a final review + fix pass against the full checklist:
    
    Checklist:
    - `.ai/AGENTS.md`
    - `.ai/models.md`
    - `.ai/modular.md`
    - `.ai/pipelines.md`
    - `.ai/review-rules.md`
    - `.ai/skills/parity-testing/SKILL.md`
    - `.ai/skills/parity-testing/pitfalls.md`
    - Pattern 1: Batch and Conditioning Expansion Drift
    - Pattern 2: Public Arguments Accepted but Ignored
    - Pattern 3: Mask Handling Is Inconsistent Across Layers
    - Pattern 4: Optional Parameters Are Not Actually Optional
    - Pattern 5: Dtype, Device, and Config Assumptions Leak
    - Pattern 6: Output and Cleanup Contracts Diverge
    - Pattern 7: Validation Does Not Match Runtime Requirements
    - Pattern 8: Copy-Paste Divergence and Hidden Coupling
    - Pattern 9: Shared Infrastructure Invariants Are Weak
    - Pattern 10: Slow and Integration Coverage Is Uneven
    - Prefer shared processor utilities for standard pipeline output conversion. Use existing functions from Processors like VaeImageProcessor.preprocess(...) VaeImageProcessor.postprocess(...) VaeImageProcessor.normalize(...) VaeImageProcessor.denormalize(...) instead of hand-rolling denormalization, tensor-to-NumPy conversion, or PIL conversion logic inside the pipeline.
    - Keep public and helper type hints aligned with runtime behavior. If an argument accepts None, generator lists, tensor/list/int unions, or returns either an output dataclass or tuple, reflect that in the annotation.
    - Keep docstrings synchronized with signatures and behavior. Public docs should mention supported output_type values, generator-list support, and behavior that changes when optional inputs are omitted.
    - If an existing test is skipped, validate why, except where functionality is deprecated like `attention_slicing`.
    - If `test_fp16_inference` is failing check `prepare_latents`, use `torch.float32` in `prepare_latents` then cast to desired type afterwards if reproducability is a concern.
    
    Collate all work from subagents and prepare a PR for the completed work.
    
    Track Progress via Codex. When a work is completed, notify the user via Codex, and return the prepared PR title and body. When the user says exactly `CREATE PR`, submit the PR to `huggingface/diffusers`, if the user requests changes to the work or PR title or body, complete the changes and return the PR title and body.
    
    After a PR is created, continue with the next target until all targets are complete.

    The changes in each look good to me. I'll wait for review on those and any feedback, but I think this could be a good baseline for fixing the issues identified.

  6. sayakpaul commented on May 12, 2026

    @sayakpaul
    Member

    @hlky thanks, going to review Wan now. But I think instead of LongCat, we could maybe prioritize other more popular pipelines like Flux / Flux2, etc.

    Also, I would be interested in the knowing more about the system you used to get the reporting done.

  7. hlky commented on May 12, 2026

    @hlky
    ContributorAuthor

    Initial prompt was asking for a checklist of models and pipelines. The idea behind putting it under a .gitignore directory was that it wouldn't accidentally end up in a commit later on.

    Prompt

    Create an internal checklist of models and pipelines, this will not be committed, store it under some directory that is in .gitignore
    
    This is to keep track of reviews that we will be doing
    
    Organize by latest to oldest if possible, link together model + pipeline of the same family where possible
    

    This produced logs/review_checklists/models_and_pipelines.md

    models_and_pipelines.md

    # Models and Pipelines Review Checklist
    
    Generated: 2026-04-29
    
    Local-only tracker. This file is under `logs/`, which is ignored by `.gitignore`.
    
    Ordering: families are sorted latest to oldest by latest Git commit touching the listed source files. Untracked source files, if any, use local file mtime.
    
    ## Review rubric
    
    - [ ] Public imports, exports, and lazy-loading behavior are correct.
    - [ ] Config, serialization, loading, and backwards compatibility are covered.
    - [ ] Runtime paths, dtype/device handling, offload, and attention processor behavior are reviewed where applicable.
    - [ ] Fast tests, slow tests, docs, examples, and expected deprecation status are accounted for.
    - [ ] Known follow-ups have an issue, PR, or local note below the family entry.
    
    ## Linked family queue
    
    Families are listed latest to oldest and bundle matching pipeline, modular pipeline, and model files where names line up.
    
    ### 2026-04-27 - `ernie_image` (ernie image)
    
    - [ ] Review complete
    - Reviewer:
    - Notes / follow-ups:
    - Pipelines:
      - `src/diffusers/pipelines/ernie_image/__init__.py`
      - `src/diffusers/pipelines/ernie_image/pipeline_ernie_image.py`
      - `src/diffusers/pipelines/ernie_image/pipeline_output.py`
    - Modular pipelines:
      - `src/diffusers/modular_pipelines/ernie_image/__init__.py`
      - `src/diffusers/modular_pipelines/ernie_image/before_denoise.py`
      - `src/diffusers/modular_pipelines/ernie_image/decoders.py`
      - `src/diffusers/modular_pipelines/ernie_image/denoise.py`
      - `src/diffusers/modular_pipelines/ernie_image/encoders.py`
      - `src/diffusers/modular_pipelines/ernie_image/modular_blocks_ernie_image.py`
      - `src/diffusers/modular_pipelines/ernie_image/modular_pipeline.py`
    - Models:
      - `src/diffusers/models/transformers/transformer_ernie_image.py`
    
    ### 2026-04-22 - `wan` (wan)
    
    - [ ] Review complete
    - Reviewer:
    - Notes / follow-ups:
    - Pipelines:
      - `src/diffusers/pipelines/wan/__init__.py`
      - `src/diffusers/pipelines/wan/image_processor.py`
      - `src/diffusers/pipelines/wan/pipeline_output.py`
      - `src/diffusers/pipelines/wan/pipeline_wan.py`
      - `src/diffusers/pipelines/wan/pipeline_wan_animate.py`
      - `src/diffusers/pipelines/wan/pipeline_wan_i2v.py`
      - `src/diffusers/pipelines/wan/pipeline_wan_vace.py`
      - `src/diffusers/pipelines/wan/pipeline_wan_video2video.py`
    - Modular pipelines:
      - `src/diffusers/modular_pipelines/wan/__init__.py`
      - `src/diffusers/modular_pipelines/wan/before_denoise.py`
      - `src/diffusers/modular_pipelines/wan/decoders.py`
      - `src/diffusers/modular_pipelines/wan/denoise.py`
      - `src/diffusers/modular_pipelines/wan/encoders.py`
      - `src/diffusers/modular_pipelines/wan/modular_blocks_wan.py`
      - `src/diffusers/modular_pipelines/wan/modular_blocks_wan22.py`
      - `src/diffusers/modular_pipelines/wan/modular_blocks_wan22_i2v.py`
      - `src/diffusers/modular_pipelines/wan/modular_blocks_wan_i2v.py`
      - `src/diffusers/modular_pipelines/wan/modular_pipeline.py`
    - Models:
      - `src/diffusers/models/autoencoders/autoencoder_kl_wan.py`
      - `src/diffusers/models/transformers/transformer_wan.py`
      - `src/diffusers/models/transformers/transformer_wan_animate.py`
      - `src/diffusers/models/transformers/transformer_wan_vace.py`
    

    My original intent was for a single prompt to choose the next target but reading the large file inflated context.

    The prompt also needed refining anyway so I kept the checklist and refined the prompt over the first few runs. With the refined prompt the next target name and file list could just be copied in, I ran them in small batches to keep the human review context smaller.

    As the findings are constrained to set rules I only did a light review before creating the issue, just enough to validate the findings looked valid and it looked like everything that was supposed to be covered was covered.

    Editable part

    ## Task
    
    Target: `qwenimage`
    
    Files: 
    - Pipelines:
      - `src/diffusers/pipelines/qwenimage/__init__.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_output.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_controlnet.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_controlnet_inpaint.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_edit.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_edit_inpaint.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_edit_plus.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_img2img.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_inpaint.py`
      - `src/diffusers/pipelines/qwenimage/pipeline_qwenimage_layered.py`
    - Modular pipelines:
      - `src/diffusers/modular_pipelines/qwenimage/__init__.py`
      - `src/diffusers/modular_pipelines/qwenimage/before_denoise.py`
      - `src/diffusers/modular_pipelines/qwenimage/decoders.py`
      - `src/diffusers/modular_pipelines/qwenimage/denoise.py`
      - `src/diffusers/modular_pipelines/qwenimage/encoders.py`
      - `src/diffusers/modular_pipelines/qwenimage/inputs.py`
      - `src/diffusers/modular_pipelines/qwenimage/modular_blocks_qwenimage.py`
      - `src/diffusers/modular_pipelines/qwenimage/modular_blocks_qwenimage_edit.py`
      - `src/diffusers/modular_pipelines/qwenimage/modular_blocks_qwenimage_edit_plus.py`
      - `src/diffusers/modular_pipelines/qwenimage/modular_blocks_qwenimage_layered.py`
      - `src/diffusers/modular_pipelines/qwenimage/modular_pipeline.py`
      - `src/diffusers/modular_pipelines/qwenimage/prompt_templates.py`
    - Models:
      - `src/diffusers/models/autoencoders/autoencoder_kl_qwenimage.py`
      - `src/diffusers/models/controlnets/controlnet_qwenimage.py`
      - `src/diffusers/models/transformers/transformer_qwenimage.py`
    

    Rest of the prompt

    
    Audit the full model/pipeline family for the target and write an issue-style report. Do not create a GitHub issue unless I later say exactly: `CREATE ISSUE`, then use `gh issue create` to create an issue on `huggingface/diffusers`, the issue title should be: `{Target}` model/pipeline review
    
    ## Review Rules
    
    Follow `.ai/review-rules.md` completely, including every referenced rule file.
    
    Do not stop after finding the first issue. Continue until every file in the target family has been reviewed.
    
    If this prompt is repeated, either continue the prior audit if the report was incomplete, or recheck the existing report against the rules.
    
    ## Scope
    
    For the target family, review:
    
    - Public imports, exports, and lazy-loading behavior.
    - Config, serialization, loading, and backwards compatibility.
    - Runtime behavior, dtype/device handling, offload behavior, and attention processor behavior where applicable.
    - Pipeline/model consistency with related families.
    - Fast tests, slow tests, docs, examples, and deprecation status where applicable.
    - Test coverage under `tests/`, including whether fast and slow tests exist.
    
    If slow tests are missing, include that as a report item. Do not hide it in introductory notes.
    
    ## Execution Rules
    
    Use `.venv` for any code execution.
    
    If running a model or pipeline, prefer tiny fixtures/models from fast tests to avoid large downloads and excessive GPU use.
    
    Always use top-level imports from `diffusers` where available.
    
    ## Duplicate Check
    
    Before writing the final issue report, check existing GitHub Issues and PRs for likely duplicates in `huggingface/diffusers`.
    
    Use relevant searches for:
    
    - `{Target}`
    - the affected class/function/file names
    - the specific failure mode or missing coverage
    
    If a duplicate exists, mention it in the relevant report item and do not present the finding as new.
    
    ## Reproduction Requirements
    
    For each actionable issue, include a standalone `python` reproduction snippet directly next to that issue.
    
    Do not create or reference a generic `repro.py`.
    
    Prefer minimal snippets using tiny test components or synthetic tensors.
    
    ## Link Format
    
    Include links to relevant code using this exact format:
    
    https://github.com/huggingface/diffusers/blob/{commit_hash}/{file_path}#L{line_number}
    
    or for ranges:
    
    https://github.com/huggingface/diffusers/blob/{commit_hash}/{file_path}#L{start}-L{end}
    
    Do not wrap these links in Markdown formatting.
    
    ## Fix Guidance
    
    For each issue, provide a code fix when the fix is small enough to be clear inline.
    
    If the fix would be large or risky, describe the recommended implementation instead.
    
    Reference other models or pipelines where they provide the correct behavior or useful precedent.
    
    ## Final Report Format
    
    Use this structure:
    
    ```md
    # `{Target}` model/pipeline review
    
    Commit tested: `{commit_hash}`
    
    Review performed against the repository review rules.
    
    ## Issue 1: {short title}
    
    Affected code:
    {GitHub link}
    
    Problem:
    {Explain the bug or gap.}
    
    Impact:
    {Explain user-visible or maintenance impact.}
    
    Reproduction:
    ```python
    {standalone snippet}
    ``
    
    Relevant precedent:
    {Links or references to other models/pipelines, if applicable.}
    
    Suggested fix:
    ```python
    {small inline fix, if applicable}
    ``
    
    ## Issue 2: {short title}
    
    ``
    ..
    ``
    
    If no actionable bugs are found, still provide the report with:
    
    - the commit tested,
    - confirmation that the review rules were followed,
    - files/categories reviewed,
    - duplicate-search status,
    - test coverage status,
    - any missing slow tests as report items.
    
    If `{Target}` ends with _shared or _infrastructure, include the full file list and confirm that all files were reviewed.
    

    The meta issue was produced in a single session with the following prompt:

    Meta issue

    ## Task
    
    Aggregate all completed model/pipeline family reviews into a single meta-issue report, find these by searching Issues on `huggingface/diffusers` that are authored by `hlky` and the title is in format "{Target} model/pipeline review"
    
    Do not create a GitHub issue unless I later say exactly: `CREATE ISSUE`, then use `gh issue create` to create an issue on `huggingface/diffusers`.
    
    The goal is to identify **systematic patterns and root causes**, not to restate every individual issue.
    
    ## Input
    
    Each report contains:
    - individual issues
    - reproductions
    - affected code links
    - suggested fixes
    
    ## Scope
    
    - All pipeline families
    - All model families
    - All `_shared` and `_infrastructure` targets
    
    Assume all targets have been fully reviewed.
    
    ## Instructions
    
    ### 1. Do NOT list every issue
    
    Do not enumerate all issues individually.
    
    Instead:
    - group issues into **recurring patterns**
    - identify **root causes**
    - show how issues repeat across multiple families
    
    ### 2. Extract patterns
    
    Identify and group issues into categories such as:
    
    - Batch size / shape inconsistencies
    - API contract mismatches (accepted vs actually used arguments)
    - Mask handling inconsistencies (`attention_mask`, etc.)
    - Optional parameters that are not actually optional
    - Copy-paste divergence across pipeline families
    - Inconsistent validation vs runtime behavior
    - Silent incorrect behavior vs explicit errors
    - Missing slow/integration tests
    - Config / serialization inconsistencies
    - Shared infrastructure assumptions not enforced
    
    Only include patterns that appear in multiple families.
    
    ### 3. For each pattern
    
    For each pattern, include:
    
    - Short description
    - Why it occurs (root cause if identifiable)
    - Impact (correctness, reproducibility, usability, maintenance)
    - 2–5 representative issue links (not exhaustive)
    
    ### 4. Identify root causes
    
    Where possible, explain:
    
    - which shared utilities or infrastructure contribute
    - whether the issue is due to:
      - duplicated logic
      - missing abstractions
      - weak invariant enforcement
      - inconsistent historical evolution
    
    ### 5. Cross-layer connections
    
    Highlight when:
    
    - the same issue appears in pipelines AND models
    - or is caused by shared infrastructure
    
    These are especially important.
    
    ### 6. Test coverage analysis
    
    Summarize:
    
    - presence of fast tests
    - absence of slow/integration tests
    - correlation between missing tests and discovered bugs
    
    Explicitly call out:
    - families with skipped TODO slow tests
    
    ### 7. Duplicate check
    
    Before writing conclusions, check for existing issues/PRs that already identify:
    
    - major patterns
    - not just individual bugs
    
    Mention if:
    - patterns are already partially known
    - but not systematically addressed
    
    ### 8. Keep tone constructive
    
    Frame as:
    
    - applying existing review rules to legacy code
    - identifying opportunities for consistency improvements
    
    ## Output Format
    
    ```md
    # [meta issue] Systematic model/pipeline review findings / tracking
    
    Commit tested: `{commit_hash}`
    
    Review performed against the repository review rules.
    
    ## Summary
    
    - Reviewed {N} model/pipeline families
    - Identified recurring issue patterns across multiple components
    - Findings suggest systemic inconsistencies rather than isolated bugs
    
    ### Pattern 1: {short title}
    
    Description:
    {what the pattern is}
    
    Root cause:
    {why it happens}
    
    Impact:
    {why it matters}
    
    Representative examples:
    - {issue link}
    - {issue link}
    
    ### Pattern 2: {short title}
    
    ...
    
    ## Tracking
    
    - [ ] {Target}
    - ...
    
    

    The review and meta-issue prompts were written in rough form by hand first, rewritten by AI then manually refined.

  8. hlky commented on Jun 27, 2026

    @hlky
    ContributorAuthor

    @yiyixuxu @sayakpaul Gentle ping on this.

    I see that other contributors have started chipping away at the backlog this audit has produced, however I believe with the right process iteration this work can be completed in bulk. Solving low hanging fruit in older code that came before the review standards you have recently introduced and bringing it up to the same standards was the overall goal of doing the audit, because I see in many open source projects agents are overwhelming maintainers, so my thought is that if you remove that low hanging fruit then agent traffic should decrease.

    I have made some progress in that regard and refined the processes used to produce the existing PRs I made from this list. My own projects at the moment use extensive AI processes so coming back to this on occasion is a good test of those processes.

    One area I looked at that you may be interested in as it relates to the review bot you have introduced is an attempt at codifying the human review process by taking a sample of past PRs and issues, my thought there is that if you can trust the AI review is at a similar level to what humans would apply then you can reduce the bandwidth required for human review.

    Happy to share more details on any aspect of this, and if the team has available bandwidth I can make a few more PRs then iterate further on the processes from reviews on those until the processes can be trusted to complete the backlog.

  9. sayakpaul commented on Jun 28, 2026

    @sayakpaul
    Member

    Thanks @hlky for offering to help!

    We have https://huggingface.co/blog/huggingface/serge in place, which lets us stage the review generated by an agent and make our own edits. With the continuously updated rulesets, we have been seeing some reduced burden on the maintenance side along with other features like:

    With these implemented + better rules + Serge, I think we have made some progress towards:

    One area I looked at that you may be interested in as it relates to the review bot you have introduced is an attempt at codifying the human review process by taking a sample of past PRs and issues, my thought there is that if you can trust the AI review is at a similar level to what humans would apply then you can reduce the bandwidth required for human review.

    Additionally, we're working on providing some initial feedback to PRs. This would first use an agent to check for regular diffusers conventions, generate an initial review, and then notify the maintainers. A maintainer then has to sign it off to make sure things are looking good.

  10. Devam0311 commented on Sep 1, 2026

    @Devam0311

    I've opened 10 PRs against findings from this audit — 5 from #13611 (SD3), 4 from #13610 (SDXL), and 1 from #9635. They're listed below in the order I'd suggest reviewing them: smallest and lowest-risk first.

    Each one includes a reproduction of the reported behaviour, a regression test I verified fails without the fix and passes with it, the exact test commands and output, and self-review notes flagging the judgment calls I made. Where the same bug existed in files the issue didn't list — reached via # Copied from, or found by sweeping for the identical pattern — I fixed those together and said so explicitly in the PR.

    Pure bug fixes, no behaviour to preserve (the affected code path could not run without raising):

    PR Finding Size
    #14679 #13610 Issue 5 — modular inpaint VAE encoder references self.vae +41/−1
    #14672 #13611 Issue 4 — SD3ControlNetModel.from_transformer() mutates the source config +85/−2
    #14673 #13611 Issue 3 — controlnet_pooled_projections tensor path (also #9686) +32/−4
    #14674 #13611 Issue 5 — ControlNet inpaint rejects documented IP-Adapter embeds +34/−9

    Correctness fixes that change output or return type (each flagged in its own PR):

    PR Finding Size
    #14671 #13611 Issue 1 — SD3 inpaint decode drops the VAE shift (moves a pinned expected_slice) +31/−4
    #14678 #13610 Issue 4 — latent output passed through watermarking +36/−14
    #14680 #13610 Issue 3 — latent output bypasses cleanup and ignores return_dict=False +65/−33
    #14676 #13610 Issue 2 — negative crop coordinates ignored (8 files, via # Copied from) +43/−8

    Larger, and the two I'd most expect pushback on:

    PR Finding Size
    #14675 #13611 Issue 2 — SD3 ControlNet cannot use dynamic-shifting schedulers. Needs latents before timesteps, so it reorders two steps; the existing expected slices are unchanged, which is my evidence that the reorder is behaviour-preserving. +136/−24
    #14670 #9635 — true CFG for the two Flux ControlNet variants that lack it. A feature rather than a bug fix, and the largest diff here. +298/−2

    On the point in the issue description about agent-generated PRs adding review load: these are AI-assisted, and each discloses that on the PR per the contribution guide, with the self-review skill run on the diff.

    I'd rather not add to that load than add to it, so — genuinely, no attachment to any of these: happy to close any that aren't worth the review time, or to consolidate them into one batched PR per review issue if that's easier to review than ten separate ones. Just say which.

  11. Devam0311 commented on Sep 2, 2026

    @Devam0311

    Small follow-up on the ten PRs I listed above: nine of them have picked up the "does not appear to link an issue" bot notice, which warns they may be closed automatically in ten days.

    That is my doing rather than a bot misfire. Those nine each fix a single finding out of #13611 (six findings) and #13610 (seven), so I used a plain reference rather than a Fixes keyword — a closing keyword would close the whole review issue the moment one sub-fix merged, while the rest were still outstanding. Only #14670 has a Fixes, because it maps to a single issue, and that one was not flagged.

    I have edited the nine descriptions to state explicitly which finding each one addresses and why there is no closing keyword.

    Could a maintainer apply no-issue-needed to these nine? Alternatively, if you would rather have the closing keywords and simply reopen the review issues afterwards, say so and I will add them.

    #14671, #14672, #14673, #14674, #14675 — findings from #13611
    #14676, #14678, #14679, #14680 — findings from #13610

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions