Skip to content

[Rust Frontend] Support logprob_token_ids on OpenAI endpoints - #59549

Merged
BugenZhao merged 2 commits into
vllm-project:mainfrom
zupengwang:rust-openai-selected-logprobs
Oct 12, 2026
Merged

BugenZhao merged 2 commits into
vllm-project:mainfrom
zupengwang:rust-openai-selected-logprobs

Conversation

@zupengwang

@zupengwang zupengwang commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Add logprob_token_ids support to the Rust /v1/chat/completions and /v1/completions endpoints. Related to the selected-token item in #44280; scope claim.

Claims

  • Forward non-empty token selections through the existing text/engine sampling path instead of silently dropping the field; preserve the Python frontend's empty-list fallback.
  • Return the selected candidates and sampled token in streaming and non-streaming responses without applying the natural top-k cut again.
  • Enforce the logprobs prerequisite and completion prompt-only echo restriction, reusing existing token-count and vocabulary validation.

Validation

Check Baseline With change
Conversion regressions 2 failures: selection is None Passed
cargo test -p vllm-server -p vllm-text --locked (Rust 1.95) — 543 passed, 1 upstream-ignored slow tokenizer test
cargo nextest run --workspace --all-features --locked --no-fail-fast (Rust 1.95, Python 3.12) — 1923 passed, 13 upstream-ignored tests, 0 failures
Qwen2.5-0.5B-Instruct / RTX 4090, selected probabilities Selected IDs omitted at all 15 observed generated positions Python/Rust comparison across 45 positions: max absolute difference 4.87e-7
Ordinary requests without a selection Original Rust binary Same tokens, candidate maps and duplicate counts at all 15 positions

The Python/changed-Rust evaluation made 62 requests covering both endpoints, streaming/non-streaming, empty selections, sampled-token selections, invalid IDs/counts, missing logprobs, beam search, and prompt-only echo. Invalid requests returned 400, and each server remained healthy. One baseline run reproduced the omission and checked unchanged ordinary behavior. This is functional validation, not a throughput or accuracy benchmark.

The full Buildkite Rust style-clippy entrypoint passes, including fmt, Cargo ordering, dependency bans and workspace/all-targets/all-features Clippy with warnings denied. The frontend build and six applicable pre-commit hooks also pass.

The test bootstrap encountered external download failures. After installing nextest from locked source and preparing the CI Python environment, the identical full-workspace nextest command passed in one run. Initial missing tokenizer caches and first-run dependency timeouts were resolved without changing tests or adding skips. This reports local execution of the CI checks, not hosted CI status.

Reproduction commands:

cargo test --manifest-path rust/Cargo.toml -p vllm-server -p vllm-text --locked
bash .buildkite/scripts/run-rust-frontend-cargo-ci.sh style-clippy
cargo nextest run --manifest-path rust/Cargo.toml --workspace --all-features --locked --no-fail-fast

Example chat request used in validation:

{"model":"selected-logprobs-eval","messages":[{"role":"user","content":"The capital of France is"}],"temperature":0,"max_tokens":4,"logprobs":true,"top_logprobs":1,"logprob_token_ids":[0,1,2]}

Details

The shared sampling types already support selected-token logprobs, but the two OpenAI request types omit the field and conversion hard-codes it to None. The change clears natural top-k sampling for a non-empty selection and uses the existing all-candidates response option for chat. No sampler, engine protocol, GPU code or dependency changes are included.

Non-duplication: merged #56406 fixes gRPC conversion; #46427 adds /generative_scoring, #45569 addresses broader validation, and #57394/#49320 concern Python empty-list validation. None exposes selected IDs on these two Rust OpenAI routes. #59518 and #58711 also touch shared Rust chat candidate deduplication. This PR now dedupes chat top_logprobs by token ID before the top_logprobs cut, so a sampled token that is also selected (or the top-1 token) appears once, matching Python.

Evaluation used the exact Rust patch and Python source at cff08b461e08 with the same model snapshot, while reusing torch 2.13.0+cu132 and precompiled native extensions from the existing runtime. It was not a complete native rebuild. Rust 1.98 locally raises a newer lint in unchanged multimodal tensor code; pinned Rust 1.95 Clippy passes.

AI assistance was used for investigation, implementation and validation. The human submitter reviewed the patch and authorized this submission.


Pull Request Checklist
  • I used vLLM's /pr-checklist skill. (Mandatory for agents, optional for humans).
  • AI assistance was used during the creation of this PR.
  • Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
  • Testing and Validation: Validation completed as reported above; human review confirmed before submission.
  • Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
  • Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.

@mergify mergify Bot added the rust label Oct 1, 2026
@zupengwang
zupengwang marked this pull request as ready for review October 1, 2026 05:24

@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.

@BugenZhao

Copy link
Copy Markdown
Member

[AUTOMATED] @codex review

zupengwang and others added 2 commits October 12, 2026 09:52
Expose selected-token logprobs on both Rust OpenAI endpoints using the
existing sampling and response paths, with request validation and
streaming/non-streaming regression coverage.

Related to vllm-project#44280.

Co-authored-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
The engine row is the sampled token followed by the top-k or requested
tokens, so the sampled token can repeat in chat `top_logprobs`. Keep
each token's first entry before applying the `top_logprobs` cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>

@BugenZhao BugenZhao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @zupengwang for filling this gap. I'll rebase the PR for you

@BugenZhao
BugenZhao force-pushed the rust-openai-selected-logprobs branch from 49984c4 to 82985c9 Compare October 12, 2026 09:55
@BugenZhao

Copy link
Copy Markdown
Member

/ci run

@github-actions

Copy link
Copy Markdown

✅ Triggered Buildkite CI #94173 for commit 82985c9a8cb1.

@BugenZhao
BugenZhao merged commit 2144580 into vllm-project:main Oct 12, 2026
32 checks passed
michael-gpu pushed a commit to practical-inference/vllm-ampere-extended that referenced this pull request Oct 20, 2026
…roject#59549)

Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Bugen Zhao <i@bugenzhao.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants