[None][feat] BREAKING: add per-model KV cache manager v2 auto selection - #15823
Conversation
67a9fe0 to
5ea1d1a
Compare
|
/bot run --disable-fail-fast |
📝 WalkthroughWalkthroughChanges ChangesKV Cache Manager V2 Auto Resolution
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tensorrt_llm/_torch/pyexecutor/model_loader.py (1)
338-357: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winAuto-resolution log never fires for the exact scenario this PR targets (e.g. DeepseekV4).
apply_model_defaults_to_llm_args(called at lines 342-343) mutatesllm_args.kv_cache_config.use_kv_cache_manager_v2in place viasetattrfor every field innew_args, overriding the"auto"sentinel with the model's explicit default (e.g.TrueforDeepseekV4ForCausalLM) whenever the user hasn't explicitly set it. By line 349,use_kv_cache_manager_v2is therefore alreadyTrue/False, not"auto"— soif use_kv_cache_manager_v2 == "auto":at line 351 isFalseand the "Resolved use_kv_cache_manager_v2='auto' to %s for %s" log never prints for models that supply an explicituse_kv_cache_manager_v2default. The final resolved boolean is still correct, but the dedicated auto-resolution log — the primary observability feature this PR adds — is dead code for this case.Capture whether the setting was
"auto"before model defaults are applied, and gate the log on that captured flag instead of re-reading the already-mutated value.🐛 Proposed fix
+ use_kv_cache_manager_v2_was_auto = ( + llm_args.kv_cache_config.use_kv_cache_manager_v2 == "auto") model_defaults = {} if model_cls and hasattr(model_cls, 'get_model_defaults'): model_defaults = model_cls.get_model_defaults(llm_args) or {} if model_defaults: applied_defaults = apply_model_defaults_to_llm_args( llm_args, model_defaults) if applied_defaults: logger.info( f"Applied model defaults for {model_cls.__name__}: {applied_defaults}" ) - use_kv_cache_manager_v2 = llm_args.kv_cache_config.use_kv_cache_manager_v2 _resolve_kv_cache_manager_v2_auto(llm_args, model_defaults) - if use_kv_cache_manager_v2 == "auto": + if use_kv_cache_manager_v2_was_auto: logger.info( "Resolved use_kv_cache_manager_v2='auto' to %s for %s", llm_args.kv_cache_config.use_kv_cache_manager_v2, model_cls.__name__ if model_cls is not None else "unknown model")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tensorrt_llm/_torch/pyexecutor/model_loader.py` around lines 338 - 357, Capture the original `llm_args.kv_cache_config.use_kv_cache_manager_v2` value before calling `apply_model_defaults_to_llm_args` in `model_loader.py`, since that helper mutates the field in place. Use that pre-মutation flag to detect whether the user had `"auto"` set, and gate the `logger.info` message on it instead of re-reading the updated value. Keep the existing resolution logic in `_resolve_kv_cache_manager_v2_auto` unchanged, but ensure the auto-resolution log still fires for models like `DeepseekV4ForCausalLM` that provide an explicit default.
🧹 Nitpick comments (2)
tests/unittest/_torch/modeling/test_modeling_deepseekv4.py (1)
151-162: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest correctly covers the static defaults dict; add end-to-end coverage separately.
This unit test is sufficient for validating
DeepseekV4ForCausalLM.get_model_defaults()'s static return value. However, it doesn't cover the end-to-end auto-resolution behavior inmodel_loader.py(e.g., that"auto"+DeepseekV4model default correctly resolves toTrueand is logged). Given the log-gating bug flagged inmodel_loader.py(lines 338-357), consider adding a regression test — likely intests/unittest/llmapi/test_llm_args.pyor a dedicatedmodel_loadertest — asserting the resolved value and log behavior for a model with an explicituse_kv_cache_manager_v2default.As per path instructions, "Keep feedback actionable: suggest concrete list file names and whether coverage is sufficient, insufficient, or needs follow-up outside the PR."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/_torch/modeling/test_modeling_deepseekv4.py` around lines 151 - 162, The current test only verifies the static defaults returned by DeepseekV4ForCausalLM.get_model_defaults(), but it does not cover the end-to-end auto-resolution path in model_loader.py. Add a separate regression test in tests/unittest/llmapi/test_llm_args.py or a dedicated model_loader test that exercises a DeepseekV4 model with an explicit use_kv_cache_manager_v2 default, asserts that "auto" resolves to True, and verifies the expected logging behavior from the auto-resolution flow. Keep the existing test as-is since it is sufficient for the static defaults dict, and use the new test to cover the log-gating behavior in model_loader and the LlmArgs/DeepseekV4ForCausalLM interaction.Source: Path instructions
tensorrt_llm/_torch/pyexecutor/model_loader.py (1)
18-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPrivate helper imported across module boundary.
_resolve_kv_cache_manager_v2_autois underscore-prefixed inllm_utils.py, signaling it's module-private, yet it's now imported and called frommodel_loader.py. Consider renaming it to a public name (drop the leading underscore) inllm_utils.pysince it's part of the cross-module contract now.As per coding guidelines, "Variables and functions not part of a class's or module's public interface should be prefixed with an underscore."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tensorrt_llm/_torch/pyexecutor/model_loader.py` around lines 18 - 19, The imported helper _resolve_kv_cache_manager_v2_auto is being used across a module boundary even though its leading underscore marks it as private. Update the symbol in llm_utils.py to a public name without the underscore, and then change model_loader.py to import and call the renamed public helper consistently. Keep apply_model_defaults_to_llm_args unchanged and make sure the new name reflects the intended cross-module API.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/llm-api/quickstart_advanced.py`:
- Around line 132-138: The --use_kv_cache_manager_v2 argument in
quickstart_advanced.py is not truly tri-state because action='store_true' only
produces auto or True, so users cannot explicitly disable it when model defaults
enable it. Update the parser setup for this option to accept auto/true/false as
a string-valued CLI flag, and adjust the downstream handling in the code that
consumes this argument so it maps those values to the corresponding
enabled/disabled/auto behavior.
---
Outside diff comments:
In `@tensorrt_llm/_torch/pyexecutor/model_loader.py`:
- Around line 338-357: Capture the original
`llm_args.kv_cache_config.use_kv_cache_manager_v2` value before calling
`apply_model_defaults_to_llm_args` in `model_loader.py`, since that helper
mutates the field in place. Use that pre-মutation flag to detect whether the
user had `"auto"` set, and gate the `logger.info` message on it instead of
re-reading the updated value. Keep the existing resolution logic in
`_resolve_kv_cache_manager_v2_auto` unchanged, but ensure the auto-resolution
log still fires for models like `DeepseekV4ForCausalLM` that provide an explicit
default.
---
Nitpick comments:
In `@tensorrt_llm/_torch/pyexecutor/model_loader.py`:
- Around line 18-19: The imported helper _resolve_kv_cache_manager_v2_auto is
being used across a module boundary even though its leading underscore marks it
as private. Update the symbol in llm_utils.py to a public name without the
underscore, and then change model_loader.py to import and call the renamed
public helper consistently. Keep apply_model_defaults_to_llm_args unchanged and
make sure the new name reflects the intended cross-module API.
In `@tests/unittest/_torch/modeling/test_modeling_deepseekv4.py`:
- Around line 151-162: The current test only verifies the static defaults
returned by DeepseekV4ForCausalLM.get_model_defaults(), but it does not cover
the end-to-end auto-resolution path in model_loader.py. Add a separate
regression test in tests/unittest/llmapi/test_llm_args.py or a dedicated
model_loader test that exercises a DeepseekV4 model with an explicit
use_kv_cache_manager_v2 default, asserts that "auto" resolves to True, and
verifies the expected logging behavior from the auto-resolution flow. Keep the
existing test as-is since it is sufficient for the static defaults dict, and use
the new test to cover the log-gating behavior in model_loader and the
LlmArgs/DeepseekV4ForCausalLM interaction.
🪄 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: Enterprise
Run ID: 8a31798e-a203-4fac-8728-a663b4c935e2
📒 Files selected for processing (9)
examples/llm-api/quickstart_advanced.pytensorrt_llm/_torch/models/modeling_deepseekv4.pytensorrt_llm/_torch/pyexecutor/_util.pytensorrt_llm/_torch/pyexecutor/model_loader.pytensorrt_llm/llmapi/llm_args.pytensorrt_llm/llmapi/llm_utils.pytensorrt_llm/usage/llm_args_golden_manifest.jsontests/unittest/_torch/modeling/test_modeling_deepseekv4.pytests/unittest/llmapi/test_llm_args.py
|
PR_Github #56894 [ run ] triggered by Bot. Commit: |
|
/bot run --disable-fail-fast |
|
PR_Github #56985 [ run ] triggered by Bot. Commit: |
|
PR_Github #56894 [ run ] completed with state |
|
PR_Github #56985 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #57363 [ run ] triggered by Bot. Commit: |
|
PR_Github #57363 [ run ] completed with state
|
Signed-off-by: Yi Zhang <187001205+yizhang-nv@users.noreply.github.com>
5ea1d1a to
e9bcb46
Compare
|
/bot run --disable-fail-fast |
|
PR_Github #57678 [ run ] triggered by Bot. Commit: |
|
PR_Github #57678 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #57917 [ run ] triggered by Bot. Commit: |
Signed-off-by: Yi Zhang <187001205+yizhang-nv@users.noreply.github.com>
|
/bot run --disable-fail-fast |
|
PR_Github #58398 [ run ] triggered by Bot. Commit: |
|
PR_Github #58398 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #58859 [ run ] triggered by Bot. Commit: |
|
PR_Github #58859 [ run ] completed with state |
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Follows the proven pattern from examples/disaggregated/slurm/cache_transceiver_test (which exercises V2 with the Python transceiver end-to-end): a KvCacheConfigV2 dataclass stand-in, prepare_context/resize_context (ctx) and prepare_disagg_gen_init (gen) for allocation, free_resources() for release (also frees the IndexMapper slot), and is_disagg=True for in-flight-transfer slot headroom. fill/verify are unchanged -- get_buffers()/get_batch_cache_indices() alias the real pool on both V1 and V2. vocab_size (a V2 ctor input) now comes from the model's config.json. Manager version and transceiver runtime resolve exactly like serving (PR NVIDIA#15823): explicit yaml values win; an absent use_kv_cache_manager_v2 means 'auto' and adopts the model class's get_model_defaults() (e.g. DeepseekV4 defaults to V2), and transceiver_runtime 'auto' resolves through the REAL llm_utils._resolve_transceiver_runtime_auto against model_cls.get_preferred_transceiver_runtime() with the same NIXL gate. The model class comes from config.json architectures via MODEL_CLASS_MAPPING, mirroring the automodel path. Effective values are printed by the leader and recorded in the status json. V2 only works with the Python transceiver (see cache_transceiver_test/report.py), so a V2 + CPP pairing is rejected up front with a clear INIT_ERROR instead of a C++ binding type error. Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Description
Add
"auto"as the default value ofKvCacheConfig.use_kv_cache_manager_v2so models can opt in to KV cache manager V2 through their model defaults. Explicit user-providedtrueorfalsevalues continue to take precedence, while models without a V2 default resolve tofalse.DeepSeek V4 opts in to V2. Gemma and DeepSeek R1 defaults are unchanged.
Test Coverage
pytesttargeted KV cache auto-resolution and DeepSeek V4 model-default tests: 7 passed.pre-commit run --files <changed files>: passed.KVCacheManagerV2andKVCacheV2Scheduler; MMLU and GSM8K completed and passed their accuracy thresholds. The remaining CNN/DailyMail evaluation could not start because the local cachedtestsplit contained zero samples. The temporary R1 default was reverted before this PR.PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.