feat: add crop() to StaticCache layers for assisted generation#45745
feat: add crop() to StaticCache layers for assisted generation#45745ArkaD171717 wants to merge 5 commits into
Conversation
|
I think @LagunaModelTest test_tp_generation failure is unrelated to this PR its a gloo transport layer mismatch in the tensor parallel test harness. All the other tests passed. Could a maintainer re-run the failed |
|
Hi, Assisted decoding always calls Severity: action required | Category: correctness How to fix: Support static in EncoderDecoderCache.crop Agent prompt to fix - you can give this to your LLM of choice:
We noticed a couple of other issues in this PR as well - happy to share if helpful. Found by Qodo code review |
|
Thank you for catching that, @Qodo-Free-For-OSS. It's now fixed and pushed. Please do share those other issues! I don't need agent prompts. |
StaticLayer.crop() zeros out evicted KV slots in-place and updates cumulative_length via fill_(), preserving static tensor addresses for torch.compile/cudagraphs. StaticSlidingWindowLayer.crop() delegates to the above with a ValueError guard matching dynamic semantics. Remove the hard ValueError in _assisted_decoding that blocked StaticCache. Propagate the main model's cache_implementation to the assistant model in AssistedCandidateGenerator instead of always falling back to dynamic_full. 11 unit tests for crop(), 8 integration tests for assisted generation with static cache. Closes huggingface#32946
EncoderDecoderCache.crop() does not support static sub-caches, so encoder-decoder models must keep using dynamic_full for assisted generation. Only decoder-only models benefit from static cache here.
96a1f3f to
2b3e8b2
Compare
|
Fixed Merge conflict |
|
cc @Cyrilvallez for generation |
Cyrilvallez
left a comment
There was a problem hiding this comment.
Hey! In general I'm not against, but could you please share your motivations for this? Since we need to rollback all the time, we basically lose the advantages of a StaticCache, so I'm not super sure it makes sense.
Also, please do not add new test files, add tests to existing test files!
|
Hello @Cyrilvallez thanks for the reply, The motivation is torch.compile / CUDA graphs; DynamicCache allocates new tensors on every grow/slice which forces graph recompilation and StaticCache pins tensor addresses via mark_static_address() so the compiled graph stays valid across calls. Assisted gen needs crop() to roll back rejected candidates but because of all the above slicing would create new tensors and break the compiled graph Sorry about the test files issue, I moved all of them into existing files and will push that shortly |
|
accidentally closed wrong PR 😭😭Just to be clear this one is still open |
Cyrilvallez
left a comment
There was a problem hiding this comment.
Hey! Overall, I don't think this is worth the effort as it is in the curent state... We could ad the method, but it would lead us nowhere... The big issues are the following:
- assisted decoding does not trigger compilation under static cache anyway
cropdoes not work with sliding window, so all static caches cannot be used
| # We need to roll back the cache in assisted generation. Static caches now support | ||
| # rollback via StaticLayer.crop(), so propagate the main model's cache_implementation | ||
| # when it is a static type; otherwise fall back to "dynamic_full". | ||
| if generation_config.cache_implementation in ALL_STATIC_CACHE_IMPLEMENTATIONS: | ||
| self.generation_config.cache_implementation = generation_config.cache_implementation |
There was a problem hiding this comment.
This will not work with sliding window layers
Assisted generation needs to roll back the KV cache when candidate tokens get
rejected
DynamicLayer.crop()does this by slicing, butStaticLayercan't slicebecause its tensors have static memory addresses pinned by
mark_static_address()for torch.compile/cudagraphsStaticLayer.crop()zeros out the evicted slots withfill_()/indexing andupdates
cumulative_lengthin-placeTensor identity is preserved so torch.compile doesn't break
StaticSlidingWindowLayer.crop()delegates to the above but raises ValueErrorif the window has already been exceeded (same semantics as the dynamic version,
evicted tokens are gone)
Removes the hard ValueError in
_assisted_decodingthat was blockingStaticCache entirely
Also propagates the main model's
cache_implementationto the assistant modelin
AssistedCandidateGeneratorinstead of always falling back to"dynamic_full", per the reviewer request on #3479711 unit tests for crop() (basic, negative, overflow clamp, tensor identity,
crop-then-update, sliding window)
8 integration tests for assisted generation with static cache (including
output-matching against dynamic cache)
Closes #32946