KV cache
This folder contains the modular KV-cache backend used by causal video models.
Current scope:
- vanilla KV cache only
- multi-branch routing supported at the
CausalContext/ model layer
This README describes the structure. Entry payloads, lifecycles, and error cases are documented in the module docstrings of base.py and vanilla_engine.py.
Files
base.py: shared cache storage, registration, cross-attention entries, and block-mask helpersvanilla_engine.py: baseline raw-chunk self-cache + dense cross-cache engine (VanillaKVCacheEngine, exported asKVCacheEngine)__init__.py: package exports for the active KV-cache backend
Layering
The design is split into three layers:
-
Model layer The model owns named KV-cache engine branches on
transformer.kv_cache_engines. -
Context layer
CausalContextcarries the branch map for the current rollout incache_engines. -
Engine layer Each engine stores per-block cache entries keyed by
cache_tag.
Model-Level Structure Example for Wan T2V / WanI2V / VACE-Wan
Causal Wan T2V / WanI2V:
Causal VACE:
"main" owns transformer.blocks[*] and "vace" owns transformer.vace_blocks[*]. Each branch registers only the attention modules it owns.
Context-Level Structure
CausalContext (fastgen/networks/network_causal.py) stores rollout metadata plus references to the named engine objects owned by the causal model; its docstring lists the fields. Two keys and a block index select one cache entry:
Engine-Level Structure
Each engine is single-branch internally. Shared storage in BaseKVCacheEngine:
All block_idx values are local to the engine branch, not global across the transformer:
Self-attention entries
The vanilla engine keeps each block’s K/V as a list with one tensor per stored chunk, plus the cached token count len:
ensure_capacity()creates each entry empty.append_self_kv()appends each chunk’s K/V.- Attention runs on
[cached_prefix | current_chunk], reading the prefix withget_self_prefix(). clear(), called throughclear_caches()at the start of each rollout, empties every entry.
Cross-attention entries
Each entry holds the K/V of the full cross-attention context (the text tokens, preceded by the image tokens for Wan2.1 I2V) and is written once, then read many times per rollout:
ensure_capacity()allocates zero K/V withis_init=False.- The first forward with
store_kv=Truefills the entry. - Later no-grad forwards read it and skip the K/V projections; forwards with gradients enabled recompute K/V.
clear()zeros every entry; clear before changing a tag’s conditioning or starting a new rollout.
Concrete Hierarchy
Routing Rule
Attention processors do not hardcode a branch. They resolve the active engine by asking which registered engine owns the current attention module (CausalContext.resolve_registered_engine). That lets Wan T2V and WanI2V stay single-branch and VACE use separate "main" and "vace" caches without changing the engine internals.