Support stateful KV cache for multimodal decoder - #2469
Support stateful KV cache for multimodal decoder#2469Anirudh Swaminathan (Anirudh-Swaminathan) wants to merge 3 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR updates the multimodal decoder/pipeline state handling so stateful decoders (e.g., OpenVINO VLM with session-managed KV cache) can work correctly, and so generator rewind/continuous decoding can reset multimodal state consistently.
Changes:
- Replaces
DecoderState’s hardcodedDefaultKeyValueCachewith astd::unique_ptr<KeyValueCache>created viaCreateKeyValueCache(), and adds null guards for KV cache call sites. - Adds
DecoderState::RewindTo()to rewind position inputs, KV cache, and recurrent state. - Adds
MultiModalPipelineState::RewindTo()to forward rewind to the decoder and resetis_prompt_when rewinding to index 0.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/models/multi_modal.h | Adds RewindTo() overrides and switches decoder KV cache storage to a std::unique_ptr<KeyValueCache>. |
| src/models/multi_modal.cpp | Implements KV cache factory usage + null-guards, and adds rewind implementations for decoder and multimodal pipeline. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/models/multi_modal.cpp:666
- After switching DecoderState::kv_cache_ to a std::unique_ptr, there is still a remaining call site using the old value-type API: DecoderState::RunPrefillWithChunking() calls
kv_cache_.Update(next_indices, length)(multi_modal.cpp:754). This will not compile (unique_ptr has no Update()), and it also bypasses the intended null-cache guard for models where CreateKeyValueCache() returns nullptr.
model_{model},
position_inputs_{CreatePositionInputs(*this, sequence_lengths, model_.config_->model.decoder.inputs.attention_mask)},
kv_cache_{CreateKeyValueCache(*this)},
recurrent_state_{CreateRecurrentState(*this)} {
| void MultiModalPipelineState::RewindTo(size_t index) { | ||
| if (decoder_state_) | ||
| decoder_state_->RewindTo(index); | ||
| if (index == 0) | ||
| is_prompt_ = true; | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
src/models/multi_modal.cpp:665
- Changing
kv_cache_to a pointer leavesRunPrefillWithChunkingcallingkv_cache_.Update(...)at line 754. This no longer compiles; that call also needs the same null guard andkv_cache_->Update(...)used by the other update paths.
kv_cache_{CreateKeyValueCache(*this)},
src/models/multi_modal.cpp:945
- A full rewind cannot restore the multimodal prompt stage by toggling this flag alone. The first prompt destroys
vision_state_/speech_state_(lines 927-928), whileMultiModalFeatures::Update(false)replaces nonempty feature inputs with empty tensors. Consequently,RewindTo(0)followed by a new prefill silently runs without the original image/audio features. Preserve reusable encoder outputs, or recreate the encoder states and rebind the original extra inputs/features before settingis_prompt_.
if (index == 0)
is_prompt_ = true;
| if (decoder_state_) | ||
| decoder_state_->RewindTo(index); |
The multimodal DecoderState previously hardcoded a DefaultKeyValueCache, which prevented stateful OpenVINO/QNN VLM decoders (whose KV cache is managed inside the ORT session) from working. - Replace the fixed DefaultKeyValueCache with a CreateKeyValueCache factory result (std::unique_ptr<KeyValueCache>), so a ModelManagedKeyValueCache is selected for stateful models; guard all Add/Update call sites for the null (no-cache) case. - Add DecoderState::RewindTo to reset position inputs, KV cache, and recurrent state, mirroring DecoderOnly_State. - Add MultiModalPipelineState::RewindTo to forward to the decoder state and reset is_prompt_ so continuous decoding re-enters the prompt stage.
Updated comment for MultiModal models KeyValueCache to clarify usage in stateful models
887ed07 to
dda7969
Compare
Fix kv_cache update to check for existence before updating
The multimodal DecoderState previously hardcoded a DefaultKeyValueCache, which prevented stateful OpenVINO VLM decoders (whose KV cache is managed inside the ORT session) from working.