[None][feat] Preserve cache_salt string in KV cache events - #13051
Conversation
Add cache_salt support to the KV routing pipeline so that requests with different salts produce distinct block hashes, preventing cross-tenant KV cache reuse. The salt flows through: nvext → RoutingHints → router hash computation → TRT-LLM engine → KV events → indexer. A dedicated XXH3_SALT_SEED (0xCAFE) is used to hash the salt, avoiding collisions with lora_name. Depends on: NVIDIA/TensorRT-LLM#13051 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change introduces support for propagating an optional string Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
examples/cpp/executor/executorExampleKvEvents.cpp (1)
2-2:⚠️ Potential issue | 🟡 MinorUpdate copyright year on this modified source file.
The file now contains new changes, but Line 2 still ends at
2024.As per coding guidelines "Add NVIDIA copyright header on ALL new files and update year on modified files."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/cpp/executor/executorExampleKvEvents.cpp` at line 2, Update the SPDX copyright year range on this modified file so it reflects the current modification year; specifically, in executorExampleKvEvents.cpp replace the trailing year "2024" in the SPDX header comment with the current year (e.g., change "2022-2024" to "2022-2026") so the header complies with the project policy.cpp/include/tensorrt_llm/batch_manager/llmRequest.h (1)
2-2:⚠️ Potential issue | 🟡 MinorUpdate the copyright year in this modified header.
Line 2 still ends at
2025, but this file includes 2026 changes.As per coding guidelines "Add NVIDIA copyright header on ALL new files and update year on modified files."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cpp/include/tensorrt_llm/batch_manager/llmRequest.h` at line 2, Update the top-of-file copyright header in the modified header to include 2026: locate the copyright line that currently reads "Copyright (c) 2022-2025, NVIDIA CORPORATION." and change the year range to include 2026 (e.g., "2022-2026") so the header on tensorrt_llm/batch_manager/llmRequest.h reflects the modification year.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cpp/include/tensorrt_llm/executor/executor.h`:
- Around line 733-734: The Doxygen for the Request constructor is missing
documentation for the newly added parameter cacheSalt; update the constructor's
Doxygen comment (the one above the Request(...) declaration) to add a line
documenting the cacheSalt parameter (std::optional<std::string> cacheSalt =
std::nullopt), placed after the disaggRequestId entry, using the repository's
single-line Doxygen style (//! and `@param` or the existing param lines format) so
the Request constructor docs include cacheSalt and its default behavior;
reference the Request constructor signature and the cacheSalt parameter name
when adding the doc line.
In `@cpp/tensorrt_llm/executor/requestImpl.h`:
- Around line 51-52: The cacheSalt parameter and setCacheSalt(std::string) must
be validated and kept truly optional: add a single helper (e.g.,
normalizeCacheSaltOptional or sanitizeCacheSalt) that accepts
std::optional<std::string>, enforces a MAX_CACHE_SALT_LEN, truncates or rejects
overlong salts (prefer reject/log), and returns std::optional<std::string> to
store; call this helper from the constructor overloads (the ctor taking
std::optional<std::string> cacheSalt and any other ctors that accept cacheSalt)
and from setCacheSalt (change setCacheSalt(std::string) to route through the
helper or add an overload taking std::optional), preserving the ability to clear
to std::nullopt, and ensure BlockKey and stored-block serialization use the
validated optional value.
In `@tensorrt_llm/executor/request.py`:
- Line 107: Validate and bound the cache_salt parameter before attaching it to
Request objects: in the function(s) that accept cache_salt (the parameter
declared as cache_salt: Optional[str] and where the Request/requests are
created/annotated—e.g., the constructor or factory that stores cache_salt),
ensure cache_salt is either None or a str, and enforce a maximum length (define
a constant like MAX_CACHE_SALT_LEN); if it exceeds the limit either truncate it
to that max length or raise a ValueError (be consistent with existing input
validation policy). Apply the same guards where cache_salt is accepted again
(the other occurrence around the second signature) so per-block KV cache events
only carry type-checked, bounded strings.
---
Outside diff comments:
In `@cpp/include/tensorrt_llm/batch_manager/llmRequest.h`:
- Line 2: Update the top-of-file copyright header in the modified header to
include 2026: locate the copyright line that currently reads "Copyright (c)
2022-2025, NVIDIA CORPORATION." and change the year range to include 2026 (e.g.,
"2022-2026") so the header on tensorrt_llm/batch_manager/llmRequest.h reflects
the modification year.
In `@examples/cpp/executor/executorExampleKvEvents.cpp`:
- Line 2: Update the SPDX copyright year range on this modified file so it
reflects the current modification year; specifically, in
executorExampleKvEvents.cpp replace the trailing year "2024" in the SPDX header
comment with the current year (e.g., change "2022-2024" to "2022-2026") so the
header complies with the project policy.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: baf02ea9-81e4-422f-9df2-7441618cc6ac
📒 Files selected for processing (19)
cpp/include/tensorrt_llm/batch_manager/blockKey.hcpp/include/tensorrt_llm/batch_manager/llmRequest.hcpp/include/tensorrt_llm/executor/executor.hcpp/tensorrt_llm/batch_manager/blockKey.cppcpp/tensorrt_llm/batch_manager/kvCacheEventManager.cppcpp/tensorrt_llm/executor/request.cppcpp/tensorrt_llm/executor/requestImpl.hcpp/tensorrt_llm/executor/serialization.cppcpp/tensorrt_llm/nanobind/batch_manager/bindings.cppcpp/tensorrt_llm/nanobind/executor/bindings.cppcpp/tensorrt_llm/nanobind/executor/request.cppexamples/cpp/executor/executorExampleKvEvents.cpptensorrt_llm/_torch/pyexecutor/llm_request.pytensorrt_llm/_utils.pytensorrt_llm/executor/base_worker.pytensorrt_llm/executor/executor.pytensorrt_llm/executor/request.pytensorrt_llm/llmapi/llm.pytests/unittest/llmapi/test_llm_kv_cache_events.py
|
@eopXD @thorjohnsen could you review this? Thanks @lowsfer @yizhang-nv does this affect manager v2? Does v2 support this? |
c9cb6ba to
b75eb38
Compare
|
/bot run --disable-fail-fast |
|
PR_Github #44803 [ run ] triggered by Bot. Commit: |
|
PR_Github #44803 [ run ] completed with state
|
77e7b77 to
b0d90db
Compare
|
/bot run --disable-fail-fast |
|
PR_Github #45943 [ run ] triggered by Bot. Commit: |
|
PR_Github #45943 [ run ] completed with state |
|
/bot run --disable-fail-fast |
|
PR_Github #46156 [ run ] triggered by Bot. Commit: |
|
PR_Github #46156 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #46380 [ run ] triggered by Bot. Commit: |
|
/bot run --disable-fail-fast |
|
PR_Github #51883 [ run ] triggered by Bot. Commit: |
|
PR_Github #51883 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #52111 [ run ] triggered by Bot. Commit: |
|
PR_Github #52111 [ run ] completed with state
|
|
/bot skip --comment "Flaky CI" |
|
PR_Github #52376 [ skip ] triggered by Bot. Commit: |
|
PR_Github #52376 [ skip ] completed with state |
Thread the original cache_salt string through the full pipeline so it appears in KV cache stored-block events. Previously only the hashed uint64 cache_salt_id crossed into C++ and the original string was discarded, making it impossible for external cache managers to identify which tenant a cached block belongs to without a side-channel mapping. The string is carried alongside the existing cacheSaltID (uint64) at every layer: Python LLM API -> executor Request -> LlmRequest -> BlockKey -> KVCacheStoredBlockData -> nanobind -> Python serializer. The string does not participate in hashing or matching — only the uint64 does. This follows the precedent set by multimodal UUIDs (MmKey.uuid). Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
- Validate cache_salt against UTF-8 byte length, matching the C++ guard - Rename C++ helper normalizeCacheSalt -> validateCacheSalt - Thread cache_salt / cache_salt_id through GenerationExecutor.generate - Add tests for max-length validation and non-ASCII salt Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
…eded Remove cache_salt_id from the public C++ Executor Request, GenericLlmRequest, BlockKey, and Python GenerationRequest/GenerationExecutor. BlockKey now stores only the salt string; BlockKeyHasher mixes std::hash<std::string> on the salt for the first block in a sequence, and operator==/numMatchingTokens compare the string. The orphaned get_cache_salt_id helper and its export are removed from tensorrt_llm.inputs. Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
mAgentHierarchy is declared after mCacheSalt in GenericLlmRequest but was initialized before it in the main constructor's initializer list, triggering -Werror=reorder. Swap the initializer order to match the declaration order. Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
…est call createRequestWithHierarchy passed cacheSaltID positionally between arrivalTime and agentHierarchy. After cacheSaltID was removed from the LlmRequest constructor, the trailing agentHierarchy argument shifted into the multimodalItemRunCuOffsets slot (a std::vector<SizeType32>), producing a no-matching-constructor build error. Drop the now-extra nullopt. Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
27f1d9b to
2da8d93
Compare
|
/bot run --disable-fail-fast |
|
PR_Github #53113 [ run ] triggered by Bot. Commit: |
|
PR_Github #53113 [ run ] completed with state
|
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
|
/bot run --disable-fail-fast |
|
PR_Github #53232 [ run ] triggered by Bot. Commit: |
|
PR_Github #53232 [ run ] completed with state |
Summary
cache_saltstring through the full pipeline (Python LLM API → C++ Request → LlmRequest → BlockKey → KVCacheStoredBlockData → nanobind → Python serializer) so it appears in KV cache stored-block eventsuint64cache_salt_idcrossed into C++; the original string was discarded, making it impossible for external cache managers to identify which tenant a cached block belongs to without a side-channel mappingMmKey.uuid) — the string is carried alongside the existingcacheSaltID(uint64) and does not participate in hashing or matchingTest plan
pytest tests/unittest/llmapi/test_llm_kv_cache_events.py— verifiescache_saltfield presence in serialized events (Nonefor unsalted, original string for salted)pytest tests/unittest/bindings/test_executor_bindings.py— binding integrityserializeUtilsTest,kvCacheManagerTest)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
cache_saltparameter to generation requests. This parameter is now propagated and preserved throughout the system for event reporting and serialization purposes, complementing the existing cache salt ID mechanism.Tests