[TRTLLM-15947][refactor] BREAKING: Remove C++ state left dead by the TRTLLMSampler removal - #18532
Conversation
Funatiq
left a comment
There was a problem hiding this comment.
defaultDecodingParams.h can also be removed now.
Its only consumer was runtime::SamplingConfig, deleted earlier in this PR. NVIDIA#18233 had moved the header from layers/ to runtime/ to empty out layers/, which kept it alive one step longer than the code that used it. Nothing else includes it and no CMake list names it; an incremental build after deleting it has no work to do. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…decoder Both are compatibility shims for representations only the removed decoder needed, which the surviving readers immediately undid. beam_width_array: LlmRequest.get_beam_width_by_iter, PyExecutor._validate_request and _get_max_beam_width each handled a nested [[...]] form. That nesting came from runtime::SamplingConfig's one-vector-per-request storage; executor::SamplingConfig::getBeamWidthArray returns a flat OptVec<SizeType32> and always has, so the branch is unreachable now that LlmRequest holds the executor type. test_beam_width_array_max_accepts_nested_shape asserted that shape specifically and goes with it; the flat-list test alongside it stays. embedding_bias: GenericLlmRequest unsqueezed it to [1, vocab] because, per the comment, "that's what IFB code expects". The only remaining reader is sampler_features, via _py_embedding_bias_1d, which squeezed the dimension back off. Store it 1-D and drop both steps; the executor-side tensor was already 1-D (requestTest.cpp:55), so the two sides now agree. Verified locally: full C++ rebuild clean, 113 gtests pass including llmRequestTest whose shape assertions this changes, and the sampler and bindings Python tests pass. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
I had edited the manifest by hand because the generator needs torch, which is unavailable on my host. That missed three entries belonging to the removed LookaheadDecodingConfig: speculative_config.max_ngram_size, max_verification_set_size and max_window_size. Regenerated with scripts/generate_llm_args_golden_manifest.py inside the build container; the only difference from the hand-edited file is those three stale entries. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…indings The previous commit removed the unsqueeze in the executor::Request-based GenericLlmRequest constructor, but the nanobind LlmRequest constructor has its own copy: makeOptionalTensor was called with unsqueeze=true for embedding_bias. That is the constructor production uses -- llm_request.py builds LlmRequest(embedding_bias=...) directly -- so the bias stayed 2-D there while the Python squeeze that used to undo it was gone. embedding_bias was the only caller passing the flag, so drop the parameter rather than leave an unused knob. The bias is now 1-D end to end. Adds test_llm_request_embedding_bias_stays_1d, which goes through the nanobind constructor. The existing coverage went through the executor Request path and the sampler tests never set embedding_bias, which is why neither caught this. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
Per review: nothing in C++ read it. The bias was stored on the request, marshalled back to torch through the bindings, and only ever consumed by the TorchSampler via the Python-side copy. Keeping it in two places is also what let the previous commit fix one unsqueeze and miss the other. LlmRequest now takes no embedding_bias parameter; llm_request.py pops the kwarg and owns the tensor as py_embedding_bias (renamed from the private _py_embedding_bias_1d, which no longer needs to distinguish itself from a C++ copy). executor::Request::mEmbeddingBias is untouched — base_worker passes it in and it is part of the Request pickle. Also drops the argument from the 34 positional LlmRequest constructions that would otherwise shift, and the llmRequestTest assertions on the removed getter. Verified locally: full rebuild clean, llmRequestTest/requestTest/ blockKeyTest/serializeUtilsTest all pass. The 9 kvCacheManagerTest PartialCopy failures are a local sm90-build-on-B200 mismatch, unrelated to this change. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…t binding test_llm_request constructs the binding directly and asserted the value back off it. The parameter is gone now that the tensor is owned on the Python side, so drop both the kwarg and the assertion. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…pler tests These build SimpleNamespace stubs by hand rather than going through the bindings, so they kept wrapping sampling parameters in singleton lists the way runtime::SamplingConfig used to. The production readers now treat them as scalars, giving TypeError: '<' not supported between 'int' and 'list' in penalties.py and token_ban.py, and 50 != [50] in the capture test. Fix the stubs; production code is already correct (llm_request.py assigns py_min_length from sampling_config.min_tokens, a scalar). Swept the rest of the tests for other singleton-list sampling params; none left. test_penalties and test_token_ban pass locally (65 tests). Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
aa18fe8 to
757d943
Compare
|
/bot run --disable-fail-fast |
|
PR_Github #71124 [ run ] triggered by Bot. Commit: |
Deleting _first_or_none from _scan_one_model_sampling means the stubs no longer get their singleton lists unwrapped, so they have to hand over scalars like the real sampling config does. test_capture_sampling_params: my earlier pass only fixed top_k, leaving temperature and top_p wrapped -- hence [1.0] != 1.0 and [([0.7], 50, [0.9])] != [(0.7, 50, 0.9)] on x86 single-GPU. test_group_all_greedy_sync: same stub shape, found by grepping the tests for singleton-wrapped sampling params rather than waiting for CI to reach it. Note this file has a separate pre-existing failure on main (SimpleNamespace lacks _scan_one_model_sampling, which update_is_all_greedy_sample calls); it is not in any CI test list, so CI never runs it. Out of scope here. A repo-wide sweep for the pattern now comes back empty. Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
|
/bot run --disable-fail-fast |
|
PR_Github #71188 [ run ] triggered by Bot. Commit: |
|
PR_Github #71124 [ run ] completed with state |
|
PR_Github #71188 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #71376 [ run ] triggered by Bot. Commit: |
|
PR_Github #71376 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #71457 [ run ] triggered by Bot. Commit: |
|
PR_Github #71457 [ run ] completed with state |
Dev Engineer Review
runtime::SamplingConfigwithexecutor::SamplingConfig.ExecutorConfig, obsolete speculative-decoding classes, debug utilities, and related bindings and serialization.LlmRequest, sampling scalar fields, seed names, API references, telemetry, benchmarks, and documentation.SamplingConfigbinding as an alias.QA Engineer Review
test_SamplingConfig_is_executor_alias.ExecutorConfig,ExternalDraftTokensConfig, Eagle and speculative-decoding configuration, runtimeSamplingConfig, and related serialization and pickle behavior.Description
Follow-up cleanup to #18232 / #18233 (TRTLLM-15405), which removed
TRTLLMSamplerand the C++ decoder stack behind it. That removal left a large amount of C++ state that exists only to be constructed, stored, and marshalled across the nanobind boundary — with no remaining consumer on either side.This PR is a dead-code sweep, not a behavior change. Net ~4500 lines removed. It is split into reviewable commits, each independently justified. The first five cover the original sweep:
LlmRequest::mBadWordsList/mStopWordsList(Python already owns the authoritative copies aspy_bad_words/py_stop_words_list, so the bindings only cost atorch.tensor()allocation per request on the submit path),ExternalDraftTokensConfig,SpeculativeDecodingConfig, plusruntime::SamplingConfig's batch-fusing constructor and the fields whose only consumer it was.runtime::SamplingConfig—outputLogProbs/cumLogProbswere not sampling parameters but a single boolean stowed on the decoder's parameter struct. Backed byLlmRequest::mReturnLogProbsinstead. This also fixes an uninitializedboolthat was being marshalled to Python.runtime::SamplingConfig— it existed to fuse per-request scalars intooptional<vector<T>>columns for the batched decoder. With that decoder gone, every reader was unwrapping the singletons again (_unwrap_singletonasserted exactly one element, andsampler_common.pycarried aTODOto drop the plumbing).LlmRequestnow holds anexecutor::SamplingConfigdirectly.EagleConfig,OrchestratorConfig,ParallelConfig,DebugConfig(+ the orphanedbatch_manager/utils/debugUtils.{h,cpp}),LogitsPostProcessorConfig.ExecutorConfigand its vestigial plumbing —ExecutorConfigconfiguredexecutor::Executor, which no longer exists; its getters were read only bySerialization, forming a closed loop. Python never constructed one, andTorchLlmArgs.get_executor_configwas already broken (it called asuper()method that had been deleted).Later commits address review feedback:
MedusaDecodingConfig.supports_backend()rejected both surviving backends, so the public LLM-API class was unreachable. Removes theDecodingConfigmember/accessors, theexecutor::MedusaChoicestypedef, serialization, the binding, the llmapi class andtrtllm-bench latency --medusa_choices.MedusaModule/EagleModule/LookaheadModuleintoSpeculativeDecodingModule— all three had degenerated into shells whose only additions (default trees,getNumTransformerLayers(),getExecutionConfig(), …) lost their last caller with the decoder.gptJsonConfigconstructs the base class directly with identical arguments.numReturnSequencespath,tle::alias usage, and a newtest_SamplingConfig_is_executor_alias.API-breaking changes
request.sampling_config.temperatureis now0.7rather than[0.7].tensorrt_llm.bindings.SamplingConfigis kept as an alias oftensorrt_llm.bindings.executor.SamplingConfig, and a copy constructor was added to the executor binding so the existingSamplingConfig(params._get_sampling_config())spelling keeps working.min_length→min_tokens,random_seed→seed.tensorrt_llm.bindings.SamplingConfigand for the removed config classes. Pickle tuple indices and size guards forRequest,ExecutorConfig,DecodingConfigandSamplingConfigare renumbered accordingly.ExecutorConfigis removed from thellmapi.serializationpickle allowlist and from thellm_utilsre-export.LookaheadDecodingConfig(llmapi) already raisedValueErroron both surviving backends.SamplingParams.lookahead_configwas not gated that way — it could be set, silently ignored, and forwarded into a C++ field that nothing has read since [TRTLLM-15405][refactor] Remove the C++ decoder stack behind TRTLLMSampler #18233. Both are gone, along with thebase_workerforwarding. The C++executor::LookaheadDecodingConfigand itsRequest/DecodingConfigfields stay for now; they will be removed in stages.RequestandDecodingConfiglose fields, andserialization.cppcarries no version tag (it never has onmain), so peers built before and after this commit will mis-parse each other rather than fail cleanly. Matched builds across all ranks — in particular context and generation processes in disaggregated serving — are a hard requirement.Notes for reviewers
Three same-name classes were deliberately kept, since a naive grep conflates them with the removed ones:
CacheState::ParallelConfig(dataTransceiverState.h) — live, used by the disagg cache transceiver.tensorrt_llm::DebugConfig(common/assert.h) — unrelated toexecutor::DebugConfig, still used byassert.cppand kv_cache_manager_v2.EagleConfigin_torch/auto_deploy/models/custom/modeling_eagle.py— an unrelated HuggingFace-style config class.This PR also drops
tests/unittest/llmapi/test_llm_args.py::test_executor_config_consistency, a governance test assertingBaseLlmArgsmirrored everyExecutorConfigoption. It guarded against C++ gaining an option the Python API forgot to expose; withExecutorConfiggone it has nothing left to guard.DecodingConfigandExtendedRuntimePerfKnobConfigare intentionally not removed here:benchbuilds them as kwargs forLLM(), not forExecutorConfig, so they remain reachable viallm_args.Test Coverage
This change removes code paths rather than adding them, so it is guarded by the existing suites that exercise the touched surfaces:
tests/unittest/bindings/test_bindings_ut.pytests/unittest/bindings/test_executor_bindings.pytests/unittest/_torch/sampler/test_torch_sampler.pytests/unittest/_torch/sampler/test_logits_logprobs.pytests/unittest/_torch/sampler/test_beam_search.pytests/unittest/_torch/executor/test_resource_manager.pytests/unittest/_torch/executor/test_pytorch_model_engine.pytests/unittest/_torch/speculative/test_capture_sampling_params.pytests/unittest/executor/test_base_worker.pytests/unittest/executor/test_rpc_proxy.pytests/unittest/llmapi/test_llm_args.pycpp/tests/unit_tests/batch_manager/llmRequestTest.cpp,cpp/tests/unit_tests/executor/serializeUtilsTest.cpp,cpp/tests/unit_tests/batch_manager/kvCacheManagerTest.cppNot yet validated: this branch has only been syntax-checked per-file against the devel container; a full CMake build and the suites above have not been run locally.
/bot runresults are the first real validation — please do not merge before they are green.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.