Skip to content

[Feature] Expose sampling mask via HTTP endpoints - #50520

Closed
aoshen02 wants to merge 38 commits into
vllm-project:mainfrom
aoshen02:worktree-sampling-mask-endpoint
Closed

aoshen02 wants to merge 38 commits into
vllm-project:mainfrom
aoshen02:worktree-sampling-mask-endpoint

Conversation

@aoshen02

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #49577 (mask replay). This PR:

  • Changes SamplingMask from CSR to list[list[int]] — the CSR format (flat token_ids + offsets) is efficient for internal GPU→CPU transfer but unnecessarily complex for the user-facing API. The internal pipeline (SamplingMaskTensorsSamplingMaskLists) still uses CSR; conversion to nested lists happens once at the output boundary via SamplingMaskLists.to_nested_list().

  • Exposes sampling_mask in HTTP endpoint responses — adds the field to chat completion, completion, and token-in-token-out (generate) endpoint protocols. The mask is null when enable_return_sampling_mask is off or the request was aborted.

Response format

{
  "choices": [{
    "sampling_mask": [
      [101, 55, 77, 88],
      [202, 33, 44],
      [303, 11, 22]
    ]
  }]
}

Each inner list contains the vocabulary token IDs that survived top-k/top-p/min-p filtering for the corresponding generated token.

Motivation

Without endpoint support, the sampling mask data stops at CompletionOutput and is only accessible via the offline LLM.generate() API. RL training frameworks (verl, slime/miles) that call vLLM over HTTP cannot consume it. This format (list[list[int]]) is also consistent with SGLang's output_token_sampling_mask.

Test plan

  • test_sampling_mask_lists_to_nested_list — verifies CSR → nested list conversion
  • All existing sampling mask tests pass (test_sampling_mask_tensors_tolist, test_sampling_mask_tensors_from_logits, test_sampling_mask_import)
  • E2E test with --enable-return-sampling-mask --logprobs-mode processed_logprobs (requires GPU, depends on [Feature] Mask Replay #49577)

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com

vx120 and others added 30 commits July 27, 2026 17:42
Signed-off-by: vx120 <893600387@qq.com>
Signed-off-by: vx120 <893600387@qq.com>
Signed-off-by: vx120 <893600387@qq.com>
Signed-off-by: vx120 <893600387@qq.com>
Signed-off-by: vx120 <893600387@qq.com>
Remove unnecessary blank line before the if statement.

Signed-off-by: vx120 <57470515+vx120@users.noreply.github.com>
Signed-off-by: vx120 <893600387@qq.com>
Clarify error message for top_k parameter in sampling distribution replay.

Signed-off-by: vx120 <57470515+vx120@users.noreply.github.com>
Signed-off-by: vx120 <893600387@qq.com>
Sampling masks are emitted only for FINAL_ONLY outputs, yet default
cumulative requests were silently accepted. Validate the supported output
mode when the request is admitted and keep the temperature check alongside it.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
Avoid accessing and slicing sampling masks in the scheduler
update-from-output path when the feature is disabled.

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
Validate sampling replay request output mode
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
…tput

Compact sampling mask before async output
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
…-mask-log

Remove FlashInfer sampling mask log
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
…g-mask

Disable FlashInfer sampling for sampling masks
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
Keep sampling mask tensors local to sampler
Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai>
vx120 and others added 2 commits July 31, 2026 11:56
- Change SamplingMask from CSR (flat token_ids + offsets) to
  list[list[int]] for a user-friendly API surface.
- Add SamplingMaskLists.to_nested_list() for internal CSR → nested
  list conversion at the output boundary.
- Expose sampling_mask in chat completion, completion, and
  token-in-token-out endpoint response protocols.
- Add unit test for the conversion path.

Depends on vllm-project#49577 (mask replay).

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Only the token-in-token-out /inference/v1/generate endpoint needs this;
the OpenAI /v1/completions and /v1/chat/completions endpoints should
not carry vLLM-specific RL training fields.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend mrv2 Model Runner V2 specific rust

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants