Conversation
| torch.testing.assert_close(prediction, torch.full((1, 6, 4), 5.0)) | ||
|
|
||
|
|
||
| def test_update_keeps_finite_difference_when_shape_is_stable(): |
| # The feature shape can change between steps, e.g. Qwen-Image 2.1 returns prefix + target | ||
| # tokens on the KV-cache prefill step and target tokens only afterwards. Stale factors | ||
| # cannot be differenced against the new features, so restart the expansion from order 0. |
|
Thanks for the PR. Could you also provide a minimal working code snippet and expected results (along with the time savings)? |
|
/diffusers-bot pytest tests/models -k "taylorseer" |
|
✅ |
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
| state.update((features,)) | ||
|
|
||
|
|
||
| def test_update_restarts_when_feature_shape_changes(): |
There was a problem hiding this comment.
Can we structure the test in a similar manner to
There was a problem hiding this comment.
I think there's some confusion here. The current test follows what is here:
https://github.com/huggingface/diffusers/blob/main/tests/hooks/test_mag_cache.py
I guess what you're suggesting is to add a TestQwenImage21TaylorSeerCache class and add the respective QwenImage2.1 specific tests in it?
|
Thanks for running the tests! Here is a minimal snippet (the same one as in #14829): import torch
from diffusers import QwenImage21Pipeline, TaylorSeerCacheConfig
device = "cuda" if torch.cuda.is_available() else "mps"
pipe = QwenImage21Pipeline.from_pretrained("Qwen/Qwen-Image-2.1", torch_dtype=torch.bfloat16).to(device)
pipe.transformer.enable_cache(
TaylorSeerCacheConfig(cache_interval=3, disable_cache_before_step=3, max_order=1, use_lite_mode=True)
)
image = pipe(
prompt="a cat sitting on a wall",
width=512,
height=512,
num_inference_steps=8,
true_cfg_scale=1.0,
generator=torch.Generator("cpu").manual_seed(0),
).images[0] # use_kv_cache defaults to True
image.save("out.png")Expected results (M1 Max, MPS, bf16):
Time savings. These numbers were measured with the same fix applied as a monkeypatch (the workaround in #14829), not with this branch installed. It gives identical outputs, as above. Edit with one reference image, 832×1216, 40 steps, seed 42,
For text-to-image at the same size, it goes from 615 s (no cache) to 219 s (TaylorSeer + KV cache). The scripts I used are here: https://github.com/hide3tu/LiltingChannelLabo/tree/main/2026/09/22/qwen-image-2-1-taylorseer-cache-m1-max ( |
|
Thanks! Can you also show the actual outputs? |
What does this PR do?
Fixes #14829
QwenImage21Pipelinewith a TaylorSeer cache crashes on the second step when the KV cache is on (the default). With the KV cache, the transformer returns prefix + target tokens on the prefill step and target tokens only afterwards, soTaylorSeerState.updatetries to difference two tensors of different sequence lengths.This PR makes
updaterestart the Taylor expansion from order 0 when the feature shape changes, instead of differencing against stale factors. Nothing changes when the shape is stable.Tested on an M1 Max (MPS, bf16) only, on top of
mainat cc8644b. With this change the run completes, and the output is pixel-identical touse_kv_cache=False+ TaylorSeer. For an edit with one reference image at 832×1216 / 40 steps, generation goes from 484 s (use_kv_cache=False+ TaylorSeer) to 278 s (KV cache + TaylorSeer); the uncached baseline is 721 s.If you would rather fix this on the model side (e.g. only passing target tokens through
norm_out/proj_outon the prefill step), feel free to close this or push over it.Self-review notes
I used Claude Code to help with this PR and ran the
self-reviewskill on the diff.TaylorSeerStatedirectly. A pipeline-level regression test (tiny Qwen-Image 2.1 + TaylorSeer + KV cache) is not included, sincetesting.mdsays cache tests are added case by case.cachedmode, sodisable_cache_before_stepneeds to be >= 2. Lower values are not handled here.Before submitting
self-reviewskill on the diff?Who can review?
@sayakpaul