Skip to content

[Bugfix][V1/V2] Fix prompt_logprobs to respect logprobs_mode#47680

Open
aoshen02 wants to merge 3 commits into
vllm-project:mainfrom
aoshen02:optimized-36539
Open

[Bugfix][V1/V2] Fix prompt_logprobs to respect logprobs_mode#47680
aoshen02 wants to merge 3 commits into
vllm-project:mainfrom
aoshen02:optimized-36539

Conversation

@aoshen02

@aoshen02 aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fix prompt_logprobs to respect the logprobs_mode configuration setting across both V1 and V2 GPU model runners.

Previously, prompt_logprobs always returned log_softmax results regardless of logprobs_mode. When a user set logprobs_mode="raw_logits", output logprobs correctly returned raw logits, but prompt logprobs silently ignored the mode and returned logprobs instead.

Changes

  • V1 runner (gpu_model_runner.py): inline mode branch — *_logits returns logits.float32(), *_logprobs calls compute_logprobs()
  • V2 runner (prompt_logprob.py): thread logprobs_mode through PromptLogprobsWorkercompute_prompt_logprobs_with_chunking(), dispatch to compute_topk_logits or compute_topk_logprobs
  • Shared utility (logprob.py): add compute_topk_logits() — sibling of compute_topk_logprobs() that gathers raw logits instead of applying log_softmax via Triton kernel
  • Config (vllm.py): remove the V2 runner unsupported-feature gate for raw_logits/processed_logits, since V2 now handles them correctly
  • Tests: e2e test in test_sampling_params_e2e.py, unit test in test_prompt_logprobs_mode.py

Acknowledgements

This PR consolidates and extends the work from two prior PRs that independently identified and fixed this bug:

This PR takes the best of both: V1+V2 coverage, compute_topk_logits as a reusable sibling in logprob.py (not a private helper), config gate removal to unblock V2, and tests.

Fixes: #35832

Test plan

  • pytest tests/v1/sample/test_prompt_logprobs_mode.py -v — unit test for mode branch logic
  • pytest tests/v1/sample/test_sampling_params_e2e.py::test_prompt_logprobs_respects_logprobs_mode -v — e2e: raw_logits vs raw_logprobs return different values
  • Verify V2 runner no longer rejects logprobs_mode=raw_logits

AI-assisted: Claude was used for code generation and review. All changes reviewed and understood by the submitter.

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

@mergify mergify Bot added v1 bug Something isn't working labels Jul 6, 2026
@aoshen02 aoshen02 force-pushed the optimized-36539 branch 2 times, most recently from 3615999 to bc02352 Compare July 6, 2026 03:11

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

Thanks @aoshen02 for consolidating this — V2 coverage plus the shared compute_topk_logits utility makes this strictly better than either of the prior PRs, and I'm happy to be listed as co-author. Reviewed the full diff; one blocking concern and two smaller ones.

1. Removing the config gate regresses V2 + raw_logits from "works via V1 fallback" to "crash at model load".

The gate entry in _get_v2_model_runner_unsupported_features is what makes default-V2 models silently fall back to the V1 runner for logits modes (use_v2_model_runner warns and returns Falsevllm/config/vllm.py, ~L545). With the entry removed, those configs now stay on V2 — but the V2 sampler still hard-rejects logits modes at construction:

# vllm/v1/worker/gpu/sample/sampler.py
if logprobs_mode not in ("processed_logprobs", "raw_logprobs"):
    raise NotImplementedError(f"Unsupported logprobs_mode: {logprobs_mode}")

and Sampler is constructed unconditionally for generate models in gpu/model_runner.py::load_model, so logprobs_mode="raw_logits" now dies during engine startup with NotImplementedError in the worker instead of transparently running on V1. It also means sampled-token logprobs still don't respect logits modes on V2 — this PR threads the mode through the prompt path only.

Two clean ways out:

  • Keep the gate entry and scope this PR to prompt logprobs (the V2 threading becomes groundwork that activates once the V2 sampler learns logits modes), or
  • Extend the V2 Sampler to support raw_logits/processed_logits for sampled tokens in this PR — then removing the gate is correct and the whole feature works end-to-end on V2.

I'd lean to the first for reviewability; either works.

2. Pre-commit will likely fail on prompt_logprob.py — there's trailing whitespace in the compute_fn(...) call args, and the compute_fn = (...) ternary line exceeds the 88-char limit. pre-commit run --all-files should catch both.

3. Possible GPU OOM flake in the new e2e test. test_sampling_params_e2e.py uses a module-scoped llm fixture, so its engine (default gpu_memory_utilization=0.9) can still be alive when this test constructs two more engines. Suggest moving the test to its own file, or calling cleanup_dist_env_and_memory() between engines and passing a lower gpu_memory_utilization.

Everything else LGTM: compute_topk_logits rank semantics match the existing _ranks_kernel convention ((logits >= target).sum()), log_softmax→logits is rank-preserving so ranks stay consistent across modes, and the inline V1 branch is equivalent to what #36539 did.

cc @WoosukKwon @njhill @22quinn @houseroad — this consolidates #35885 + #36539 (fixes #35832); maintainer review would be appreciated once the gate question above is settled.

@fede-kamel

Copy link
Copy Markdown

One more thought on sequencing, following up on my review above.

Since the gate question means the V2 half needs another iteration either way (keep the gate, or extend gpu/sample/sampler.py to logits modes), I'd propose not holding the V1 fix hostage to that: merge #36539 first. It's scoped exactly to the V1 runner — the only runner that can currently serve raw_logits/processed_logits end-to-end — it's rebased on current main with unit + e2e regression tests, and the approach was already agreed in review there.

This PR would then become the V2 completion on top of it: compute_topk_logits and the PromptLogprobsWorker threading here are exactly the right building blocks, and once the V2 sampler supports the logits modes for sampled tokens, removing the gate lands safely with the whole feature working end-to-end on V2.

@aoshen02 does that sequencing work for you? Happy to review the V2 follow-up promptly. If a maintainer agrees, #36539 just needs the ready label to get full CI.

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks @aoshen02 for consolidating this — V2 coverage plus the shared compute_topk_logits utility makes this strictly better than either of the prior PRs, and I'm happy to be listed as co-author. Reviewed the full diff; one blocking concern and two smaller ones.

1. Removing the config gate regresses V2 + raw_logits from "works via V1 fallback" to "crash at model load".

The gate entry in _get_v2_model_runner_unsupported_features is what makes default-V2 models silently fall back to the V1 runner for logits modes (use_v2_model_runner warns and returns Falsevllm/config/vllm.py, ~L545). With the entry removed, those configs now stay on V2 — but the V2 sampler still hard-rejects logits modes at construction:

# vllm/v1/worker/gpu/sample/sampler.py
if logprobs_mode not in ("processed_logprobs", "raw_logprobs"):
    raise NotImplementedError(f"Unsupported logprobs_mode: {logprobs_mode}")

and Sampler is constructed unconditionally for generate models in gpu/model_runner.py::load_model, so logprobs_mode="raw_logits" now dies during engine startup with NotImplementedError in the worker instead of transparently running on V1. It also means sampled-token logprobs still don't respect logits modes on V2 — this PR threads the mode through the prompt path only.

Two clean ways out:

  • Keep the gate entry and scope this PR to prompt logprobs (the V2 threading becomes groundwork that activates once the V2 sampler learns logits modes), or
  • Extend the V2 Sampler to support raw_logits/processed_logits for sampled tokens in this PR — then removing the gate is correct and the whole feature works end-to-end on V2.

I'd lean to the first for reviewability; either works.

2. Pre-commit will likely fail on prompt_logprob.py — there's trailing whitespace in the compute_fn(...) call args, and the compute_fn = (...) ternary line exceeds the 88-char limit. pre-commit run --all-files should catch both.

3. Possible GPU OOM flake in the new e2e test. test_sampling_params_e2e.py uses a module-scoped llm fixture, so its engine (default gpu_memory_utilization=0.9) can still be alive when this test constructs two more engines. Suggest moving the test to its own file, or calling cleanup_dist_env_and_memory() between engines and passing a lower gpu_memory_utilization.

Everything else LGTM: compute_topk_logits rank semantics match the existing _ranks_kernel convention ((logits >= target).sum()), log_softmax→logits is rank-preserving so ranks stay consistent across modes, and the inline V1 branch is equivalent to what #36539 did.

cc @WoosukKwon @njhill @22quinn @houseroad — this consolidates #35885 + #36539 (fixes #35832); maintainer review would be appreciated once the gate question above is settled.

done

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

One more thought on sequencing, following up on my review above.

Since the gate question means the V2 half needs another iteration either way (keep the gate, or extend gpu/sample/sampler.py to logits modes), I'd propose not holding the V1 fix hostage to that: merge #36539 first. It's scoped exactly to the V1 runner — the only runner that can currently serve raw_logits/processed_logits end-to-end — it's rebased on current main with unit + e2e regression tests, and the approach was already agreed in review there.

This PR would then become the V2 completion on top of it: compute_topk_logits and the PromptLogprobsWorker threading here are exactly the right building blocks, and once the V2 sampler supports the logits modes for sampled tokens, removing the gate lands safely with the whole feature working end-to-end on V2.

@aoshen02 does that sequencing work for you? Happy to review the V2 follow-up promptly. If a maintainer agrees, #36539 just needs the ready label to get full CI.

I don't have any problems.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa0ba744bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vllm/v1/worker/gpu/sample/sampler.py Outdated
Comment on lines +110 to +113
logprobs_tensors = compute_topk_logits(
logits,
num_logprobs,
sampled,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor explicit token IDs in logits mode

When a request uses SamplingParams(logprob_token_ids=[...]) with raw_logits or processed_logits, this branch ignores the max_per_req_token_ids/logprob_token_ids_state computed above. If logprobs is unset, num_logprobs becomes 0 and the response contains only the sampled token; if both are set, it returns top-k logits instead of the explicitly requested token IDs. The logprobs branch below passes the custom-token state, so the newly enabled logits modes regress the generative-scoring/logprob_token_ids path.

Useful? React with 👍 / 👎.

Comment on lines +97 to +98
if self.sampler.logprobs_mode.endswith("logits"):
return compute_topk_logits(logits, max_num_logprobs, flat_sampled)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pass offsets through logits spec decode

In V2 speculative decoding with raw_logits or processed_logits and logprobs enabled, this early return drops the input_batch.cu_num_logits_np offsets that the logprobs branch passes below. The resulting LogprobsTensors has cu_num_generated_tokens=None, so LogprobsLists.slice_request treats the request index as the row offset; when any earlier request has multiple speculative logits, later requests get logprobs sliced from the wrong rows.

Useful? React with 👍 / 👎.

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f0a95c8bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1346 to 1349
self._pending_logprobs[slot.item()] = compute_topk_scores(
flat_logits[start : start + k_i],
max_num_logprobs,
argmax_tokens[local_idx][:k_i],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor logits mode in DiffusionGemma logprobs

When DiffusionGemma runs with logprobs_mode="raw_logits" or "processed_logits" and the request asks for logprobs, this custom sampler now calls compute_topk_scores without the new logits_mode flag, so it defaults to False and takes the log-softmax path. Since this commit also removes the V2/worker guard for logits modes, those requests no longer fail fast but return log probabilities in the logprob field instead of logits. Store/pass the sampler's logprobs_mode.endswith("logits") here before stashing _pending_logprobs.

Useful? React with 👍 / 👎.

@aoshen02 aoshen02 requested a review from bigPYJ1151 as a code owner July 6, 2026 06:52
@mergify mergify Bot added the cpu Related to CPU backends label Jul 6, 2026
@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c4dc291a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +232 to +236
result = compute_topk_scores(
prompt_logits,
requested_num_prompt_logprobs,
prompt_token_ids[start_idx:end_idx],
requested_num,
chunk_tgt,
logits_mode=logits_mode,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Apply processors for processed prompt logprobs

When logprobs_mode is processed_logits or processed_logprobs, this path still feeds the unprocessed prompt_logits directly into compute_topk_scores; the new flag only switches between returning logits and log_softmax. Since ModelConfig.logprobs_mode documents processed modes for prompt_logprobs as after processors such as logit bias, bad words, temperature, and top_k/top_p, V2 requests with prompt_logprobs plus any such sampling processor will now be accepted but return the same raw prompt scores as the raw modes.

Useful? React with 👍 / 👎.

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review, processed logprobs is not apply to prompt logprobs, prompt will not process by sampler

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c4dc291a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +232 to +236
result = compute_topk_scores(
prompt_logits,
requested_num_prompt_logprobs,
prompt_token_ids[start_idx:end_idx],
requested_num,
chunk_tgt,
logits_mode=logits_mode,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don’t treat processed prompt scores as raw scores

When a request uses logprobs_mode='processed_logits' or 'processed_logprobs' with prompt_logprobs, this path only switches between gathering logits vs log-softmax from the unmodified prompt_logits; it never applies the sampler processors that define the processed modes, such as temperature/top_k/top_p, logit bias, bad words, or penalties. Since this commit also unblocks processed_logits for the V2 runner, those requests now succeed but return raw prompt scores while generated-token logprobs are processed. Please either run prompt logits through the same processing path or keep processed modes unsupported for prompt logprobs.

Useful? React with 👍 / 👎.

@njhill njhill 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 @aoshen02 @wojciech-wais this looks generally good to me.

@WoosukKwon might have some opinion on renaming logprobs to scores... though they might now technically not be logprobs that naming might still be clearer.

We could even consider logprobs_or_logits. Or maybe scores is best afer all. I'm really not sure about this just thinking aloud.

else num_prompt_logprobs
)
prompt_logprobs = compute_topk_logprobs(
chunk_tgt = prompt_token_ids[start_idx:end_idx]

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.

Why separate var for this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fix

Comment thread vllm/v1/worker/gpu/sample/sampler.py Outdated

if return_logprobs:
if self.logprobs_mode == "processed_logprobs":
if self.logprobs_mode.startswith("processed"):

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.

It feels nasty to use string operations for these checks. Though I know it kind of predates this PR.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 617d132c6e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread vllm/v1/worker/gpu/sample/logprob.py Outdated
logprob_token_ids = torch.cat((logprob_token_ids, topk_indices), dim=1)
logprobs = compute_token_logprobs(logits, logprob_token_ids)
if logits_mode:
scores = logits.to(torch.float32).gather(-1, logprob_token_ids)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gather raw logits before casting to float32

In raw_logits/processed_logits modes this casts the entire [batch, vocab] logits tensor to FP32 before gathering the few requested columns. On common bf16/fp16 models with large vocabs or prompt-logprob chunks, that adds a full extra logits-sized allocation and can OOM requests; the logprob path avoids materializing a full score matrix. Gather from logits first and cast the small gathered result instead; the same pattern appears in the custom-token branch below.

Useful? React with 👍 / 👎.

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.

I think this makes sense!

logprobs = []
scores = []
ranks = []
logits_mode = logprobs_mode.endswith("logits")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep processed logits from using raw prompt scores

Now that the V2 unsupported-feature guard for processed_logits is removed, that mode reaches this path, but this suffix check treats raw_logits and processed_logits identically and scores the unprocessed prompt_logits. For requests that use logit processors or sampling transforms, prompt_logprobs in processed_logits mode are therefore the same as raw logits instead of processed scores as the model config promises. Either apply the per-request processing before scoring prompt logits or keep processed_logits gated for this path.

Useful? React with 👍 / 👎.

@aoshen02 aoshen02 requested a review from 22quinn as a code owner July 6, 2026 13:13

class PromptLogprobsWorker:
def __init__(self, max_num_reqs: int):
def __init__(self, max_num_reqs: int, logprobs_mode: str = "raw_logprobs"):

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.

Both PromptLogprobsWorker.init and compute_prompt_logprobs_with_chunking declare logprobs_mode: str.
Every other caller in the diff uses LogprobsMode.
With str, a typo like "raw_logrobs" silently falls through to the log-softmax path because "raw_logrobs".endswith("logits") is False - no error, wrong behavior.



def test_prompt_logprobs_respects_logprobs_mode():
"""raw_logits must return positive logits, raw_logprobs must return

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.

The assertion only checks values["raw_logprobs"] <= 0 and values["raw_logits"] != values["raw_logprobs"].
There is no assertion for the following condition
raw_logits > 0
and there shouldn't be, because raw logits can be negative for any token.
The docstring is technically false and would mislead anyone reading the test to understand the sense of it.

assert out_1[0].outputs[0].text != out_3[0].outputs[0].text


def test_prompt_logprobs_respects_logprobs_mode():

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.

The e2e test only iterates over ("raw_logits", "raw_logprobs").
Those two processed_* modes have no test coverage at all. IMO this is missing unit test.

logprobs = self.sampler.compute_logprobs(logits)
# Compute prompt scores respecting logprobs_mode.
if self.model_config.logprobs_mode.endswith("logits"):
scores = logits.to(torch.float32)

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.

Since both runners return raw unprocessed logits for processed_logits maybe worth to flag it somehow in the code/docstring or in the comments.

prompt_logprobs ignored the logprobs_mode config — all modes returned
log_softmax results. This fix threads the mode through both V1 and V2
GPU model runners so that *_logits modes return raw logits and
*_logprobs modes return log_softmax values.

V1 runner (gpu_model_runner.py): inline mode branch before gather.
V2 runner: add logits_mode flag to compute_topk_scores, thread
logprobs_mode through Sampler, PromptLogprobsWorker, and
RejectionSampler.
Config (vllm.py): remove V2 runner unsupported-feature gate for
raw_logits/processed_logits now that V2 handles them.

Fixes: vllm-project#35832

Co-authored-by: Federico Kamelhar <209537060+fede-kamel@users.noreply.github.com>
Co-authored-by: Allen Shen <aoshen@inferact.ai>
Signed-off-by: Wojciech Wais <wojciech.wais@gmail.com>
Signed-off-by: Federico Kamelhar <209537060+fede-kamel@users.noreply.github.com>
Signed-off-by: Allen Shen <aoshen@inferact.ai>
@fede-kamel

Copy link
Copy Markdown

Re-reviewed at the current head — the blocker from my earlier review is resolved: the V2 sampler no longer rejects logits modes at construction, and the mode is threaded through the sampled-token, spec-decode, and DiffusionGemma paths, so dropping the config gate is safe now. The four-mode e2e test and the LogprobsMode typing cover the rest of what I'd flagged. LGTM from my side — this supersedes #36539, and I'll close that one once this merges. Thanks for carrying the co-author trailers through; please keep them in the squash message.

@aoshen02

aoshen02 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

Re-reviewed at the current head — the blocker from my earlier review is resolved: the V2 sampler no longer rejects logits modes at construction, and the mode is threaded through the sampled-token, spec-decode, and DiffusionGemma paths, so dropping the config gate is safe now. The four-mode e2e test and the LogprobsMode typing cover the rest of what I'd flagged. LGTM from my side — this supersedes #36539, and I'll close that one once this merges. Thanks for carrying the co-author trailers through; please keep them in the squash message.

Thank you!

@fede-kamel

Copy link
Copy Markdown

@njhill on the naming question: scores seems right to me — the tensor holds either logits or logprobs depending on mode, and logprobs_or_logits bakes today's two options into the name. The LogprobsTensors.logprobs field has the same ambiguity, but renaming that touches a much wider surface, so probably better as a follow-up if at all.

@fede-kamel

Copy link
Copy Markdown

Heads-up from #36539's CI run (build 76426): test_prompt_logprobs_respects_logprobs_mode here will likely hit the same OOM once full CI runs — the four LLMs are created with the default gpu_memory_utilization while the module-scoped llm fixture in test_sampling_params_e2e.py still holds its memory, and on the 16 GiB CI GPU engine init then fails with ~0.7 GiB free (my variant of this test failed exactly that way on both the NVIDIA and AMD runners). The cleanup_dist_env_and_memory() between iterations helps but doesn't release the fixture's engine. What fixed it for me: pass gpu_memory_utilization=0.05 to the test's LLMs, same idiom as test_logprobs.py.

@fede-kamel

Copy link
Copy Markdown

Correcting my earlier suggestion: CI on #36539 (build 76618) showed that even gpu_memory_utilization=0.05 doesn't fit next to the module-scoped llm fixture — only 0.72 GiB stays free on the 16 GiB runner, below even that reduced request. What worked is moving the test into its own module (test_prompt_logprobs_mode_e2e.py), collected before the fixture module so the engines never coexist. Worth doing the same for the four-mode test here.

@aoshen02 aoshen02 added the ready ONLY add when PR is ready to merge/full CI is needed label Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cpu Related to CPU backends ready ONLY add when PR is ready to merge/full CI is needed v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: prompt_logprobs ignores logprobs_mode

4 participants