server: return prompt-token logprobs when echo=true (#27174) - #27537
server: return prompt-token logprobs when echo=true (#27174)#27537safiullah3915 wants to merge 1 commit into
Conversation
This fixes an issue where the server ignored the echo setting and returned an empty list for prompt-token logprobs. This broke downstream evaluation frameworks like lm-eval, which rely on adding these prompt scores together to grade specific sentences.
|
Hi @simongonzalezdc Let me know if it works as expected on your end. |
|
Hi @safiullah3915, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
Validation report (gfx1151 / Strix Halo, asked in-thread)Environment: AMD Ryzen AI Max+ 395 (Radeon 8060S, gfx1151), ROCm 7.2.4 HIP build, commit 43e3005 vs current main (2100e59) as control, identical server flags (Qwen3.8-27B UD-Q4_K_XL, q4_0 KV, 8k ctx, temp 0). 1) Control (main) — bug confirmed, and worse than reported. 2) PR build — hard abort on the feature request. The first Minimal repro: Likely mechanism: the prompt-logprob pass piggybacks on prompt decode, but the outputs buffer isn't sized for the extra prompt positions ( Normal-path generation on the PR build was not reachable in our sequence (the feature request aborts first); happy to re-run the full paired matrix (including byte-identical generation anchors and the lm-eval arc_easy end-to-end) once a fix lands — the motivation here is strong and we want this upstream. |
|
Correction + refinement to my earlier report (my crash claim was config-dependent — precise trigger below; the feature itself works). At the default context size, the PR works correctly: The crash I reported is deterministic and context-size dependent: with any Repro: launch with Thanks for the ping to retest — flagging my own overreach in the first report: the 'first request kills the server' framing was true only for non-default context sizes. |
@simongonzalezdc Thanks for detailed testing! I ran into the exact same n_outputs_max assertion error during my local tests. I temporarily bypassed it by starting the server with the --embedding flag, which forces it to allocate enough capacity. |
|
Great that you reproduced the same assert — and your Where the mismatch comes from (traced through your diff): the prompt-logprob path marks prompt tokens as batch outputs during the main prompt decode ( Two concrete fix options: A. Reserve at startup — in result.total = std::max<int32_t>(result.total, params.n_batch);This is exactly what the embedding branch already returns, so it's precedent-consistent. Cost to be aware of: the logits buffer scales as B. Chunk within existing capacity (no reservation, no memory cost): don't mark all prompt positions as outputs in the main batch. Instead, after prompt processing, feed the echo positions back through decode in chunks bounded by the already-reserved capacity (query If it's useful context from our repro: default context (4096) survived 5/5 requests while Happy to run either patch through the same paired harness (gfx1151, 262k production config) — the setup is standing by. |
Overview
Fixes #27174.
This PR enables support for
echo=true+logprobs=Nin the/v1/completionsendpoint. Previously, the server ignored theechosetting for logprobs, returning an empty list for prompt tokens and breaking downstream evaluation frameworks likelm-eval.Additional information
Motivation
Evaluation frameworks like
lm-evalgrade a model by feeding it a specific correct answer as a prompt and adding up the logprobs for those prompt tokens to calculate a total score. Because prompt scores were missing,lm-evalreceived blanks and assumed the model was randomly guessing.Changes
token_logprobsandtop_logprobsfor the echoed prompt tokens.nullfor its logprob data.Requirements
Co-author: @simongonzalezdc