Skip to content

[TRTLLM-13212][refactor] Centralize sampling logic, split backends into isolated modules#15542

Merged
zhaoyangwang-nvidia merged 10 commits into
NVIDIA:mainfrom
zhaoyangwang-nvidia:fuse_sampler
Jul 8, 2026
Merged

[TRTLLM-13212][refactor] Centralize sampling logic, split backends into isolated modules#15542
zhaoyangwang-nvidia merged 10 commits into
NVIDIA:mainfrom
zhaoyangwang-nvidia:fuse_sampler

Conversation

@zhaoyangwang-nvidia

@zhaoyangwang-nvidia zhaoyangwang-nvidia commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added broader sampling backend support, including faster GPU-accelerated paths when available.
    • Improved decoding behavior for greedy, top-k, top-p, temperature, and beam-style sampling.
    • Speculative decoding now uses the same shared sampling behavior across workflows.
  • Bug Fixes

    • Made sampling backend selection more reliable at runtime.
    • Improved consistency in token selection and probability handling across different sampling modes.
    • Updated rejection and draft-token selection flows for better alignment with the active backend.

Description

Refactors the PyTorch backend sampling subsystem into a single public interface backed by separate backend implementation modules.

Before: Logic split across two overlapping stacks:

  • sampling_utils.py + sampling_utils_flashinfer.py — host-side strategy sampling
  • speculative/one_model_sampler.py — one-model spec-dec sampling (a separate stack)

After: One interface + three backend implementations:

pyexecutor/
├── sampling_utils.py ← single public interface
└── sampling_backends/
├── backend_torch.py ← pure PyTorch kernels
├── backend_flashinfer.py ← FlashInfer kernel wrappers
└── backend_custom.py ← C++ / custom op wrappers

This "interface + backend implementations" structure is designed to pave the way for future performance optimization and feature extension:

  • Unified entry point, isolated implementations: callers depend only on the single sampling_utils.py interface; which backend a kernel lives in and how it is implemented stays transparent to the caller. Whether we later replace, tune, or add kernels, the changes are confined to the backend implementation modules and never leak to the call sites.
  • backend_custom.py is the landing spot for new custom kernels: when we want to support new sampling capabilities for the sampler, or do kernel-level optimization for a specific scenario, we can drop the new custom kernel (C++ op / Triton / hand-written CUDA, etc.) straight into backend_custom.py and wire it into dispatch via resolve_sampling_backend() — without touching the interface API or the other backends.
  • No cross-dependencies between backend implementations: the three backends do not import each other and do not depend back on the interface, so adding or modifying one backend never drags in the others. This makes them independently evolvable, independently testable, and free of circular dependencies.
  • Static dispatch, CUDA-graph friendly: backends are bound once at init time by resolve_sampling_backend() into a BoundSamplingBackend, so there is no per-call backend selection at runtime. New custom kernels fall naturally into the same binding mechanism, making them easy to reuse inside the CUDA graph capture path.

Key Changes

  • Backend isolation constraint: backend implementation modules have no imports from sampling_utils or each other, preventing circular dependencies
  • sampling_utils_flashinfer.py deleted: _StrategyImpls and FlashInferGroupedStrategySampler merged directly into sampling_utils.py
  • one_model_sampler.py deleted: sampling functions migrated to sampling_utils.py; rejection_sampling_one_model moved to speculative/interface.py (draft-token acceptance logic belongs on the speculative side)
  • Static dispatch: BoundSamplingBackend binds all kernel functions at init time via resolve_sampling_backend(); no per-call backend selection inside CUDA graph capture
  • Cleaner API: use_flashinfer param removed from sampling_batch_spec_dec_one_model (auto-detects via IS_FLASHINFER_AVAILABLE)
  • sanitize_top_k: centralized top-k normalization in the spec-dec interface — top_k <= 0 (and oversized disable sentinels) map to vocab_size (keep-all), mirroring the C++ op, instead of breaking the flashinfer / torch top-k paths on a literal 0
  • Torch fallback: sampling_batch_spec_dec_one_model_for_rejection now supports a pure-torch path when FlashInfer is unavailable
  • Draft greedy unified: drafting_loops.py and dynamic_tree_ops.py now import directly from sampling_utils instead of one_model_sampler

Behavior fix included in this refactor

  • top-p renormalization: the torch top-p path used torch.cumsum(probs_sorted, dim=-1, out=probs_sorted), aliasing the cumulative-probability tensor that is reused as the renormalization denominator. The subsequent masked_fill_(...) corrupted that denominator, so probs no longer summed to 1. Fixed by removing the in-place out= so cumulative_probs is allocated separately (two call sites in backend_torch.py).

Files Changed

Operation Files
Created sampling_backends/__init__.py, backend_torch.py, backend_flashinfer.py, backend_custom.py
Modified sampling_utils.py, sampler.py, speculative/interface.py, speculative/drafting_loops.py, speculative/dynamic_tree_ops.py, speculative/eagle3_dynamic_tree.py
Tests tests/unittest/_torch/sampler/test_torch_sampler.py, test_logits_logprobs.py — updated for the new _bound_backend dispatch and module locations
Deleted sampling_utils_flashinfer.py, speculative/one_model_sampler.py

Testing

tests/unittest/_torch/sampler/test_torch_sampler.py passes (262 passed, 162 skipped) on B200 against a main-matched build.

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-compatible or api-breaking. For api-breaking, include BREAKING in 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.

@zhaoyangwang-nvidia zhaoyangwang-nvidia changed the title [TRTLLM-13212][refactor] Unify sampling stacks into single facade with leaf backend modules [TRTLLM-13212][refactor] Centralize sampling logic, split backends into isolated modules Jun 24, 2026
@zhaoyangwang-nvidia zhaoyangwang-nvidia force-pushed the fuse_sampler branch 6 times, most recently from 99b8457 to f21cb8a Compare June 30, 2026 03:26
@zhaoyangwang-nvidia zhaoyangwang-nvidia marked this pull request as ready for review June 30, 2026 05:58
@zhaoyangwang-nvidia zhaoyangwang-nvidia requested review from a team as code owners June 30, 2026 05:58
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Consolidates sampling logic from one_model_sampler.py and sampling_utils_flashinfer.py into a new sampling_backends/ package with backend_torch, backend_flashinfer, and backend_custom modules. Introduces BoundSamplingBackend/resolve_sampling_backend in sampling_utils.py and rewires TorchSampler and speculative decoding call sites through this unified abstraction.

Changes

Sampling Backend Abstraction

Layer / File(s) Summary
New sampling_backends package
tensorrt_llm/_torch/pyexecutor/sampling_backends/__init__.py, sampling_backends/backend_torch.py, sampling_backends/backend_flashinfer.py, sampling_backends/backend_custom.py
Introduces three backend modules: backend_torch with PyTorch-native kernels (top-k/p, beam search, rejection helpers, _Fusions); backend_flashinfer with FlashInfer-gated compute_probs/greedy/op wrappers; backend_custom delegating to torch.ops.trtllm.compute_probs_from_logits_op.
sampling_utils.py core refactor
tensorrt_llm/_torch/pyexecutor/sampling_utils.py
Removes the sample() dispatcher and per-strategy batch functions. Adds _StrategyImpls hierarchy for with-probs/sample-only modes, FlashInferGroupedStrategySampler, frozen StrategyMetadata/BeamSearchMetadata, SamplerConfig, BoundSamplingBackend, and resolve_sampling_backend(); re-exports compute_probs/sample_from_probs/sample_from_logits/greedy from the Torch backend. Also adds sanitize_top_k, compute_probs_from_logits (multi-backend dispatch), and the spec-dec sampling helpers sampling_batch_spec_dec_one_model/sampling_batch_spec_dec_one_model_for_rejection.
TorchSampler wired to BoundSamplingBackend
tensorrt_llm/_torch/pyexecutor/sampler.py
Replaces _grouped_sampler_cls conditional class selection with self._bound_backend = resolve_sampling_backend(...) and routes strategy_grouping_key, get_metadata_type_for_group, and sample_grouped_strategies through it. Removes SimpleGroupedStrategySampler/FlashInferGroupedStrategySampler imports.
Speculative decoding call sites
tensorrt_llm/_torch/speculative/interface.py, eagle3_dynamic_tree.py, dynamic_tree_ops.py, drafting_loops.py
Reimports sampling_batch_spec_dec_one_model/compute_probs_from_logits/greedy from sampling_utils; removes use_flashinfer= kwarg; switches torch.argmax to greedy(); inlines rejection_sampling_one_model into interface.py. Deletes one_model_sampler.py and sampling_utils_flashinfer.py.
Tests updated
tests/unittest/_torch/sampler/test_logits_logprobs.py, tests/unittest/_torch/sampler/test_torch_sampler.py
Updates imports to source _StrategyImpls/FlashInferGroupedStrategySampler from sampling_utils; changes test_backend_selection and _inject_batching_check assertions to target sampler._bound_backend instead of sampler._grouped_sampler_cls.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • NVIDIA/TensorRT-LLM#12588: Adds dynamic-tree rejection-sampling kernels that call into compute_probs_from_logits_op, which this PR refactors and relocates into sampling_utils.py.

Suggested reviewers

  • lancelly
  • laikhtewari
  • liji-nv
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.30% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the required ticket/type format and clearly summarizes the main refactor.
Description check ✅ Passed The description includes the summary, implementation details, testing, checklist, and completion checkbox, with only minor heading wording differences.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

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/speculative/eagle3_dynamic_tree.py (1)

780-787: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Keep the self.use_flashinfer gate on this sampling path. sampling_batch_spec_dec_one_model() only checks IS_FLASHINFER_AVAILABLE, while this worker still uses self.use_flashinfer to enforce the flashinfer>=0.6.4 version gate. Thread that condition through here or reintroduce the check before calling the helper.

🤖 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/speculative/eagle3_dynamic_tree.py` around lines 780 -
787, The sampling path in `Eagle3DynamicTree` is missing the
`self.use_flashinfer` guard, so it can call
`sampling_batch_spec_dec_one_model()` even when the worker should enforce the
flashinfer version gate. Update the logic around `sampled` in
`eagle3_dynamic_tree.py` to either thread `self.use_flashinfer` into this branch
or reintroduce the check before invoking `sampling_batch_spec_dec_one_model()`,
keeping the existing flashinfer availability/version behavior consistent.
🤖 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 `@tensorrt_llm/_torch/pyexecutor/sampling_backends/backend_torch.py`:
- Around line 460-475: Short-circuit greedy rows in compute_probs_from_logits_op
before calling _apply_temperature() so temperatures at or below
_GREEDY_TEMPERATURE_THRESHOLD never divide logits by zero or a near-zero
sentinel. Use the existing is_greedy check in compute_probs_from_logits_op to
split out those rows, return the one-hot argmax for them immediately, and only
run _apply_temperature() and _apply_top_k_top_p() on non-greedy rows to avoid
inf/nan in mixed batches.

In `@tensorrt_llm/_torch/pyexecutor/sampling_utils.py`:
- Around line 1019-1024: The FlashInfer path in compute_probs_from_logits()
ignores skip_temperature, so make the IS_FLASHINFER_AVAILABLE branch behave like
the custom backend branch by honoring that flag before applying temperatures.
Update the call through backend_flashinfer.compute_probs_from_logits_op in
sampling_utils.py (and any related helper it uses) so the public API produces
consistent probabilities regardless of whether FlashInfer is installed.
- Around line 1040-1046: Add a greedy fast path in the sampling helper before
calling backend_torch._apply_temperature so rows with temperature == 0 or <=
1e-4 are handled via argmax rather than scaled sampling. Update the logic around
sanitize_top_k, backend_torch._apply_temperature, and the flashinfer/native
sampling branch so mixed batches can split greedy rows from stochastic rows
safely and avoid passing inf/nan logits downstream.

In `@tensorrt_llm/_torch/speculative/interface.py`:
- Around line 57-69: rejection_sampling_one_model() currently only gates on
IS_FLASHINFER_AVAILABLE, so older FlashInfer installs can still reach
flashinfer.sampling.chain_speculative_sampling and fail later. Update the guard
in rejection_sampling_one_model() (and the
_sample_and_accept_draft_tokens_rejection() path that calls it) to match
SpecWorkerBase.__init__ by checking for FlashInfer 0.6.4+ and raising the same
flashinfer>=0.6.4 RuntimeError before calling chain_speculative_sampling.

In `@tests/unittest/_torch/sampler/test_torch_sampler.py`:
- Around line 1514-1520: The bound-backend contract check in the Torch sampler
test is incomplete because it only verifies sample_grouped_strategies, so a
partial bind could still pass. Update the test in test_torch_sampler.py to
assert that sampler._bound_backend matches expected_cls for
sample_grouped_strategies, strategy_grouping_key, and
get_metadata_type_for_group. Use the existing expected_cls selection
(FlashInferGroupedStrategySampler vs SimpleGroupedStrategySampler) and compare
each callable directly so the refactor coverage is complete.

---

Outside diff comments:
In `@tensorrt_llm/_torch/speculative/eagle3_dynamic_tree.py`:
- Around line 780-787: The sampling path in `Eagle3DynamicTree` is missing the
`self.use_flashinfer` guard, so it can call
`sampling_batch_spec_dec_one_model()` even when the worker should enforce the
flashinfer version gate. Update the logic around `sampled` in
`eagle3_dynamic_tree.py` to either thread `self.use_flashinfer` into this branch
or reintroduce the check before invoking `sampling_batch_spec_dec_one_model()`,
keeping the existing flashinfer availability/version behavior consistent.
🪄 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: 307a96cf-6f0e-4a31-8ec9-4dda2f274310

📥 Commits

Reviewing files that changed from the base of the PR and between 92147d6 and f21cb8a.

📒 Files selected for processing (14)
  • tensorrt_llm/_torch/pyexecutor/sampler.py
  • tensorrt_llm/_torch/pyexecutor/sampling_backends/__init__.py
  • tensorrt_llm/_torch/pyexecutor/sampling_backends/backend_custom.py
  • tensorrt_llm/_torch/pyexecutor/sampling_backends/backend_flashinfer.py
  • tensorrt_llm/_torch/pyexecutor/sampling_backends/backend_torch.py
  • tensorrt_llm/_torch/pyexecutor/sampling_utils.py
  • tensorrt_llm/_torch/pyexecutor/sampling_utils_flashinfer.py
  • tensorrt_llm/_torch/speculative/drafting_loops.py
  • tensorrt_llm/_torch/speculative/dynamic_tree_ops.py
  • tensorrt_llm/_torch/speculative/eagle3_dynamic_tree.py
  • tensorrt_llm/_torch/speculative/interface.py
  • tensorrt_llm/_torch/speculative/one_model_sampler.py
  • tests/unittest/_torch/sampler/test_logits_logprobs.py
  • tests/unittest/_torch/sampler/test_torch_sampler.py
💤 Files with no reviewable changes (2)
  • tensorrt_llm/_torch/pyexecutor/sampling_utils_flashinfer.py
  • tensorrt_llm/_torch/speculative/one_model_sampler.py

Comment thread tensorrt_llm/_torch/pyexecutor/sampler/kernels/vanilla.py Outdated
Comment thread tensorrt_llm/_torch/pyexecutor/sampling_utils.py
Comment thread tensorrt_llm/_torch/pyexecutor/sampling_utils.py Outdated
Comment thread tensorrt_llm/_torch/speculative/interface.py Outdated
Comment thread tests/unittest/_torch/sampler/test_torch_sampler.py Outdated
@xxi-nv

xxi-nv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@ixlmar ixlmar self-requested a review June 30, 2026 08:55
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56574 [ run ] triggered by Bot. Commit: df07465 Link to invocation

Comment thread tensorrt_llm/_torch/pyexecutor/sampler/ops/__init__.py
Comment thread tensorrt_llm/_torch/speculative/eagle3_dynamic_tree.py
@zhaoyangwang-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56586 [ run ] triggered by Bot. Commit: 83a8d27 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56574 [ run ] completed with state ABORTED. Commit: df07465

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56586 [ run ] completed with state SUCCESS. Commit: 83a8d27
/LLM/main/L0_MergeRequest_PR pipeline #45415 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@xxi-nv

xxi-nv commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56788 [ run ] triggered by Bot. Commit: 83a8d27 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #56788 [ run ] completed with state FAILURE. Commit: 83a8d27
/LLM/main/L0_MergeRequest_PR pipeline #45606 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@xxi-nv

xxi-nv commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57764 [ run ] completed with state SUCCESS. Commit: 4823b81
/LLM/main/L0_MergeRequest_PR pipeline #46467 completed with status: 'SUCCESS'
Pipeline passed with automatic retried tests. Check the rerun report for details.

CI Report

Link to invocation

…to isolated modules

- Merge sampling_utils_flashinfer.py into sampling_utils.py (deleted former)
- Move _StrategyImpls and FlashInferGroupedStrategySampler to sampling_utils.py
- Wrap all flashinfer kernel calls in backend_flashinfer.py wrapper functions
- Move _st_* helpers to backend_torch.py (drop prefix, rename to forward_native_sampling etc.)
- Move rejection_sampling_one_model to speculative/interface.py (draft acceptance logic)
- Remove use_flashinfer param from sampling_batch_spec_dec_one_model (auto-detect)
- Add sanitize_top_k (top_k<=0 means keep-all) and apply it in the spec-dec sampling facade
- Add torch fallback path to sampling_batch_spec_dec_one_model_for_rejection
- Fix top_p renormalization: drop in-place cumsum(out=probs_sorted) that corrupted the denominator
- Fix sampler.py import: FlashInferGroupedStrategySampler now from sampling_utils
- Move StrategyMetadata to backend_torch.py so BeamSearchMetadata can inherit it
- Use explicit re-export form for _Fusions, get_rejected_indices, sample_rejected
- Add type annotations to _StrategyImpls subclass sample() overrides and from_strategies
- Update sampler unit tests for the new _bound_backend dispatch + module locations

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…_backend

Address review feedback (naming consistency + a missed call site):

- Rename sampling_backends/ -> sampling_backend/ (singular, matching
  attention_backend/) and drop the redundant backend_ filename prefix:
  backend_torch.py -> vanilla.py, backend_flashinfer.py -> flashinfer.py,
  backend_custom.py -> trtllm.py (the latter wraps torch.ops.trtllm custom
  ops, so trtllm.py is more explicit than "custom").
- Move SamplerConfig / BoundSamplingBackend / resolve_sampling_backend into
  sampling_backend/interface.py (mirrors attention_backend/interface.py).
- Update all imports, attribute accesses, and docstrings accordingly.
- Fix eagle3_dynamic_tree.py: drop the stale use_flashinfer kwarg from the
  context-subset sampling_batch_spec_dec_one_model call (the parameter was
  removed earlier in this refactor); the call now matches the new signature.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…dSamplingBackend

Address review feedback: TorchSampler only consumes the strategy-grouping
callbacks (strategy_grouping_key / get_metadata_type_for_group /
sample_grouped_strategies). The compute_probs / sample_from_probs /
sample_from_logits / greedy fields bound into BoundSamplingBackend were never
read by any call site.

- Remove those 4 unused fields from BoundSamplingBackend and resolve_sampling_backend()
- Drop the now-dead generic wrappers they pointed at in vanilla.py and flashinfer.py
  (keep vanilla.greedy, still re-exported for drafting_loops / speculative.interface)
- Drop the corresponding aliases / re-exports in sampling_utils.py

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…ith kernels/ providers

Address review feedback: the sampling_backend/ name implied flashinfer /
vanilla / trtllm were three peer sampler backends for the upper layer to
select. Reorganize so the abstraction is operation-centric and the
implementation sources stay private.

- New package pyexecutor/sampler/:
    sampler.py            orchestration (Sampler / TorchSampler / TRTLLMSampler)
    sampling_utils.py     operation-level facade
    kernels/              private provider implementations, selected internally
      flashinfer.py, vanilla.py, interface.py
- sampler/__init__.py lazily (PEP 562) re-exports sampler.py symbols so existing
  `pyexecutor.sampler` import paths keep working while importing lightweight
  submodules (e.g. sampling_utils) avoids pulling in sampler.py's heavy
  dependency chain — this also breaks the import cycle with speculative.interface.
- Inline the single TRT-LLM op into the compute_probs_from_logits() facade and
  drop the thin trtllm.py wrapper (no standalone provider contract yet).
- Update all import paths across pyexecutor / speculative / auto_deploy / tests.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
- BoundSamplingBackend: make it a frozen dataclass parameterised over the
  strategy-key type (Generic[_StrategyKeyT]) with precise Callable field types
  instead of Any, so the annotations are actually checked.
- Rename the generator-based flashinfer ops to *_generator_op
  (top_k_sampling_from_probs_generator_op / top_p_sampling_from_probs_generator_op)
  for naming consistency with the other generator-based ops.
- Update pyproject.toml mypy override to cover the whole sampler package
  (tensorrt_llm._torch.pyexecutor.sampler.*) after the package reorg, so the
  strict typing established in the base branch is not regressed.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…it, tidy sampler kernels

Follow-up on reviewer feedback:

- Revert to binding the grouped-sampler class as a unit (self._grouped_sampler_cls)
  instead of splitting the tightly-coupled grouping callables into separate
  fields; drop BoundSamplingBackend. resolve_sampling_backend now returns the
  chosen GroupedStrategySampler subclass and takes is_cuda: bool (redundant
  IS_FLASHINFER_AVAILABLE check removed at the call site).
- Rename _safely_apply_temperature -> _safely_apply_temperature_inplace (arg
  logits_inout) to make the in-place contract explicit.
- vanilla.compute_probs_from_logits_op: write greedy rows into probs in place,
  removing the full [batch, vocab] one-hot buffer and torch.where copy
  (numerically equivalent; kept dense to stay torch.compile-safe).
- Move flashinfer op imports to the top of sampling_utils.py (unconditional);
  fix sampling_batch_spec_dec_one_model return annotation (tuple -> Tensor).
- drafting_loops: unpack greedy() via tokens, _ = ...
- Update sampler unit tests for the class-based _grouped_sampler_cls dispatch.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…mpler package

The sampler refactor moved sampler.py, sampling_utils.py and
sampling_utils_flashinfer.py into the sampler/ package, so the old paths
in static-analysis-files no longer existed and mypy silently skipped the
new files. Point the list at the new module paths.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
Align the sampler subpackage with the existing codebase convention for
provider-specific compute implementations (cf. _torch/modules/fused_moe/ops),
where 'ops' denotes swappable backend implementations behind an interface,
reserving 'kernels' for actual CUDA/C++ kernel sources. No behavior change;
updates all imports, the lazy __getattr__ submodule guard, the mypy
static-analysis file list, and doc comments.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
…ing type-check

Enabling static analysis on the moved sampler files (previous commit
pointed static-analysis-files at the real module paths) surfaced
pre-existing [no-any-return] errors: functions declared to return Tensor
were returning the Any-typed results of untyped flashinfer / torch.ops
calls. Bind the results to annotated locals before returning, matching the
existing convention. No behavior change.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
@zhaoyangwang-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57973 [ run ] triggered by Bot. Commit: 5c0b3ec Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57973 [ run ] completed with state SUCCESS. Commit: 5c0b3ec
/LLM/main/L0_MergeRequest_PR pipeline #46647 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@xxi-nv

xxi-nv commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58118 [ run ] triggered by Bot. Commit: 5c0b3ec Link to invocation

Comment thread tensorrt_llm/_torch/pyexecutor/sampler/sampling_utils.py
Comment thread tensorrt_llm/_torch/pyexecutor/sampler/sampling_utils.py Outdated
Comment thread tensorrt_llm/_torch/pyexecutor/sampler/sampling_utils.py Outdated
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58118 [ run ] completed with state SUCCESS. Commit: 5c0b3ec
/LLM/main/L0_MergeRequest_PR pipeline #46778 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

… in spec sampling

Address review on the one-model speculative sampling helpers:
- sampling_batch_spec_dec_one_model: cast the greedy argmax tokens to the
  sampler's dtype before torch.where so the result stays int32 instead of
  being promoted to int64 (flashinfer returns int32).
- sampling_batch_spec_dec_one_model_for_rejection: restore the pre-refactor
  RuntimeError when flashinfer is missing instead of silently falling back to
  a global-RNG torch sample that ignores seed/offset, which would break
  determinism and cross-rank consistency.

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
@zhaoyangwang-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58136 [ run ] triggered by Bot. Commit: 4d882d3 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58136 [ run ] completed with state SUCCESS. Commit: 4d882d3
/LLM/main/L0_MergeRequest_PR pipeline #46793 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@xxi-nv

xxi-nv commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58167 [ run ] triggered by Bot. Commit: 4d882d3 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58167 [ run ] completed with state SUCCESS. Commit: 4d882d3
/LLM/main/L0_MergeRequest_PR pipeline #46818 completed with status: 'SUCCESS'

CI Report

Link to invocation

@zhaoyangwang-nvidia zhaoyangwang-nvidia merged commit 06df8da into NVIDIA:main Jul 8, 2026
7 checks passed
BrianLi23 pushed a commit to BrianLi23/TensorRT-LLM that referenced this pull request Jul 9, 2026
…to isolated modules (NVIDIA#15542)

Signed-off-by: ZhaoyangWang <zhaoyangw@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants