[Feat] support cache-dit for SenseNova-U1 (#3906)

Signed-off-by: hanzheli <hanzheli@kuaishou.com>
This commit is contained in:
fywc authored and GitHub committed 2026-05-29 17:40:54 +00:00
1 parent 5377108438
commit 272e626100
11 files changed
+256 -6

No files matched your search

+158
View File
@@ -18,6 +18,7 @@ from cache_dit import BlockAdapter, DBCacheConfig, ForwardPattern, ParamsModifie
from cache_dit.caching.block_adapters import FakeDiffusionPipeline
from cache_dit.caching.cache_adapters.cache_adapter import CachedAdapter
from cache_dit.caching.cache_blocks.pattern_0_1_2 import CachedBlocks_Pattern_0_1_2
from cache_dit.caching.cache_blocks.pattern_3_4_5 import CachedBlocks_Pattern_3_4_5
from cache_dit.caching.cache_contexts import BasicCacheConfig
from cache_dit.caching.cache_contexts.cache_manager import CachedContextManager
from vllm.logger import init_logger
@@ -1170,6 +1171,162 @@ def enable_cache_for_bagel(pipeline: Any, cache_config: Any) -> Callable[[int],
return refresh_cache_context
class SensenovaCachedBlocks(CachedBlocks_Pattern_3_4_5):
"""
Custom CachedBlocks for SenseNova-U1 that only caches image-token hidden
states during denoising.
"""
@classmethod
def _is_denoising_call(cls, kwargs: dict[str, Any]) -> bool:
if kwargs.get("cache_dit_skip", False):
return False
# Prefix/text forwards either omit image_gen_indicators or update the
# DynamicCache. Denoising forwards are gen-only and use update_cache=False.
if kwargs.get("update_cache", True):
return False
exist_gen = kwargs.get("exist_gen")
exist_und = kwargs.get("exist_und")
if exist_gen is None or exist_und is None:
image_gen_indicators = kwargs.get("image_gen_indicators")
if image_gen_indicators is None:
return False
exist_gen = image_gen_indicators.any().item()
exist_und = (~image_gen_indicators).any().item()
return exist_gen and not exist_und
@staticmethod
def _strip_cache_only_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
kwargs = dict(kwargs)
kwargs.pop("cache_dit_skip", None)
return kwargs
def forward(self, hidden_states: torch.Tensor, *args, **kwargs):
block_kwargs = self._strip_cache_only_kwargs(kwargs)
if not self._is_denoising_call(kwargs):
hidden_states, new_encoder_hidden_states = self.call_blocks(
hidden_states,
*args,
**block_kwargs,
)
return self._process_forward_outputs(hidden_states, new_encoder_hidden_states)
return super().forward(hidden_states, *args, **block_kwargs)
class SensenovaCachedAdapter(CachedAdapter):
"""Custom CachedAdapter for SenseNova-U1 that uses SensenovaCachedBlocks."""
@classmethod
def collect_unified_blocks(
cls,
block_adapter: BlockAdapter,
contexts_kwargs: list[dict],
) -> list[dict[str, torch.nn.ModuleList]]:
BlockAdapter.assert_normalized(block_adapter)
total_cached_blocks: list[dict[str, torch.nn.ModuleList]] = []
assert hasattr(block_adapter.pipe, "_context_manager")
for i in range(len(block_adapter.transformer)):
unified_blocks_bind_context = {}
for j in range(len(block_adapter.blocks[i])):
cache_config: BasicCacheConfig = contexts_kwargs[i * len(block_adapter.blocks[i]) + j]["cache_config"]
unified_blocks_bind_context[block_adapter.unique_blocks_name[i][j]] = torch.nn.ModuleList(
[
SensenovaCachedBlocks(
# 0. Transformer blocks configuration
block_adapter.blocks[i][j],
transformer=block_adapter.transformer[i],
forward_pattern=block_adapter.forward_pattern[i][j],
check_forward_pattern=block_adapter.check_forward_pattern,
check_num_outputs=block_adapter.check_num_outputs,
# 1. Cache/Prune context configuration
cache_prefix=block_adapter.blocks_name[i][j],
cache_context=block_adapter.unique_blocks_name[i][j],
context_manager=block_adapter.pipe._context_manager,
cache_type=cache_config.cache_type,
)
]
)
total_cached_blocks.append(unified_blocks_bind_context)
return total_cached_blocks
def enable_cache_for_sensenova_u1(pipeline: Any, cache_config: Any) -> Callable[[int], None]:
"""Enable cache-dit for SenseNova-U1 model.
Args:
pipeline: The SenseNova-U1 pipeline instance.
cache_config: DiffusionCacheConfig instance with cache configuration.
Returns:
A refresh function that can be called to update cache context with new num_inference_steps.
"""
transformer = getattr(getattr(pipeline, "language_model", None), "model", None)
if transformer is None or not hasattr(transformer, "layers"):
raise ValueError("SenseNovaU1Pipeline cache-dit expects pipeline.language_model.model.layers.")
# Build DBCacheConfig
db_cache_config = _build_db_cache_config(cache_config)
calibrator_config = None
if cache_config.enable_taylorseer:
taylorseer_order = cache_config.taylorseer_order
calibrator_config = TaylorSeerCalibratorConfig(taylorseer_order=taylorseer_order)
logger.info(f"TaylorSeer enabled with order={taylorseer_order}")
modifier = ParamsModifier(
cache_config=db_cache_config,
calibrator_config=calibrator_config,
)
logger.info(
f"Enabling cache-dit on SenseNova-U1 decoder layers: "
f"Fn={db_cache_config.Fn_compute_blocks}, "
f"Bn={db_cache_config.Bn_compute_blocks}, "
f"W={db_cache_config.max_warmup_steps}, "
)
SensenovaCachedAdapter.apply(
BlockAdapter(
transformer=transformer,
blocks=transformer.layers,
forward_pattern=ForwardPattern.Pattern_3,
params_modifiers=[modifier],
check_forward_pattern=True,
has_separate_cfg=True,
),
cache_config=db_cache_config,
calibrator_config=calibrator_config,
)
def refresh_cache_context(pipeline: Any, num_inference_steps: int, verbose: bool = True) -> None:
transformer = pipeline.language_model.model
if cache_config.scm_steps_mask_policy is None:
cache_dit.refresh_context(transformer, num_inference_steps=num_inference_steps, verbose=verbose)
else:
cache_dit.refresh_context(
transformer,
cache_config=DBCacheConfig().reset(
num_inference_steps=num_inference_steps,
steps_computation_mask=cache_dit.steps_mask(
mask_policy=cache_config.scm_steps_mask_policy,
total_steps=num_inference_steps,
),
steps_computation_policy=cache_config.scm_steps_policy,
),
verbose=verbose,
)
return refresh_cache_context
def enable_cache_for_flux2(pipeline: Any, cache_config: Any) -> Callable[[int], None]:
"""Enable cache-dit for Flux.2-dev pipeline.
@@ -1587,6 +1744,7 @@ CUSTOM_DIT_ENABLERS.update(
"LTX23Pipeline": enable_cache_for_ltx2,
"LTX23ImageToVideoPipeline": enable_cache_for_ltx2,
"BagelPipeline": enable_cache_for_bagel,
"SenseNovaU1Pipeline": enable_cache_for_sensenova_u1,
"GlmImagePipeline": enable_cache_for_glm_image,
"Flux2Pipeline": enable_cache_for_flux2,
"DreamIDOmniPipeline": enable_cache_for_dreamid_omni,