Skip to content

Accept tensor ip_adapter_image_embeds in SD3 ControlNet inpainting - #14674

Open
Devam0311 wants to merge 1 commit into
huggingface:mainfrom
Devam0311:sd3-controlnet-inpaint-ip-adapter
Open

Accept tensor ip_adapter_image_embeds in SD3 ControlNet inpainting#14674
Devam0311 wants to merge 1 commit into
huggingface:mainfrom
Devam0311:sd3-controlnet-inpaint-ip-adapter

Conversation

@Devam0311

@Devam0311 Devam0311 commented Sep 1, 2026

Copy link
Copy Markdown

Issue link: this addresses Issue 5 of #13611.
I have deliberately not used a Fixes keyword: #13611 tracks 6 separate findings, so a closing keyword would close it as soon as this one merges while the others are still open. Happy for the no-issue-needed label to be applied, or I can add a closing keyword if you would rather the review issue be closed and reopened.

What does this PR do?

Fixes Issue 5 of #13611.

StableDiffusion3ControlNetInpaintingPipeline contradicts itself about the type of ip_adapter_image_embeds:

Location Contract
__call__ docstring (L1111) "torch.Tensor … a tensor of shape (batch_size, num_images, emb_dim)"
prepare_ip_adapter_image_embeds (L932) typed torch.Tensor | None, and calls .chunk(2) on it
check_inputs (L780) rejects anything that is not a list

So passing the documented tensor always failed validation, and precomputed IP-Adapter embeddings could not be used at all. Passing a list to satisfy check_inputs would then break in prepare_ip_adapter_image_embeds, which calls .chunk(2).

The base StableDiffusion3Pipeline does not validate this argument in check_inputs at all — the list check here appears to be a leftover from the older list-based IP-Adapter API.

Solution

Validate the tensor's rank instead of its container type:

if ip_adapter_image_embeds is not None and ip_adapter_image_embeds.ndim not in [3, 4]:
    raise ValueError(
        f"`ip_adapter_image_embeds` has to be a 3D or 4D tensor but is {ip_adapter_image_embeds.ndim}D"
    )

Testing

Two tests, driving check_inputs directly:

  • test_check_inputs_accepts_ip_adapter_image_embeds_tensor — the documented 3D tensor now passes
  • test_check_inputs_rejects_ip_adapter_image_embeds_with_bad_ndim — a 2D tensor still raises, with the new message

Verified both catch the bug: with the fix reverted, both fail.

pytest tests/pipelines/controlnet_sd3/   -> 41 passed, 30 skipped
ruff check / ruff format --check         -> clean
git diff --check                         -> clean

Before submitting

Self-review notes

Reviewed against .ai/references/review-rules.md and pipelines.md. No blocking issues.

For the reviewer:

  1. This loosens validation on a public argument. Anyone currently passing a list to work around the old check would now fail later inside prepare_ip_adapter_image_embeds rather than early in check_inputs. I judged that acceptable because the list path was already broken downstream — there is no working list-based caller to preserve — but flagging it since it is technically a behaviour change.
  2. I kept the ip_adapter_image / ip_adapter_image_embeds mutual-exclusion check above it untouched.
  3. Scope kept to Issue 5. Issues 1, 3 and 4 of stable_diffusion_3 model/pipeline review #13611 are in Apply the VAE shift factor when decoding in SD3 inpaint #14671, Fix controlnet_pooled_projections tensor handling in SD3 ControlNet pipelines #14673 and Do not mutate the source transformer config in SD3ControlNetModel.from_transformer #14672.

Who can review?

@yiyixuxu @asomoza @hlky

`StableDiffusion3ControlNetInpaintingPipeline.check_inputs` required
`ip_adapter_image_embeds` to be a `list`, but the `__call__` docstring
documents a tensor of shape `(batch_size, num_images, emb_dim)` and
`prepare_ip_adapter_image_embeds` types it as `torch.Tensor` and calls
`.chunk(2)` on it. Passing the documented tensor therefore always failed
validation, so precomputed IP-Adapter embeddings could not be used at all.

Validate the tensor's rank instead, matching the documented contract.

Add regression tests for both the accepted tensor and the rejected rank.

Ref huggingface#13611 (Issue 5)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XBYeq5vB4DNZDEaqUsroKR
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Hi @Devam0311, thanks for the PR! It does not appear to link an issue it fixes. If this PR addresses an existing issue, please add a closing keyword (e.g. Fixes #1234) to the PR description so the issue is linked. See the contribution guide for more details. If this PR intentionally does not fix a tracked issue, a maintainer can add the no-issue-needed label to silence this reminder.

Please note that PRs without a linked issue are likely to be automatically closed 10 days after this notice.

Once the PR links an issue (or gets the no-issue-needed label), you can ignore this message — it stays here as a comment, but it no longer applies.

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

Labels

pipelines size/S PR with diff < 50 LOC tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant