Prhub

#44938 [Rust Frontend] Support prompt-only completions

原始 PR 作者 reidliu41 合并时间 2026-06-17 14:38 文件变更 3 提交数 3 评论 12 代码增减 +550 / -27

执行摘要

Rust 前端支持 prompt-only completions 路径

该 PR 是 Rust 前端功能对等路线图(#44280)的一部分。Python vLLM 已支持 echo=true 时 max_tokens=0 的 prompt-only completions,Rust 前端需实现相同能力以消除功能差距,提升 API 兼容性。

此 PR 展示了如何在前端执行请求降级和响应后处理来实现特殊功能,值得负责 Rust 前端或 API 路由实现的开发者精读。设计决策与 Python 行为对齐,保证了兼容性。代码结构清晰,包含充分的测试覆盖。

讨论亮点
  • Reviewer tahsintunan 指出非流式 prompt-only 响应的 completion_tokens 初始为 0,而 Python 计数为 1(内部 decode token)。作者随后更新以匹配 Python,将 completion_tokens 调整为 1。
  • tahsintunan 建议简化不可达的 else 分支,并共享流式与非流式的 logprobs 处理逻辑。作者重构了代码,引入了共享辅助函数。
  • BugenZhao 要求为流式 prompt-only 分支添加注释,作者已补充。
  • chatgpt-codex-connector 建议在 prompt-only 时将 completion_tokens 和 token_ids 置零。作者决定保持与 Python 行为一致(completion_tokens 为 1,token_ids 隐藏)。

实现拆解

  1. 验证层修改validate.rs):原逻辑直接拒绝 max_tokens=0,改为仅当 echo=false 时拒绝,接受 echo=true 的 prompt-only 组合。
  2. 请求转换层修改convert.rs):在 prepare_completion_request 中检测 echo=true && max_tokens==0 条件,设置 prompt_only 标志;为保证引擎能运行,将 max_tokens 强制设为 1;同时调整 prompt_logprobs 的默认启用逻辑,使流式 prompt-only 请求也能得到 prompt_logprobs。
  3. 主路由层修改completions.rs):在 collect_completioncompletion_chunk_stream 中根据 prompt_only 标志调整响应——text 仅回显 prompt,token_ids 为空,logprobs 通过新函数 prompt_only_logprobs_to_openai 构造,并隐藏内部 token 的 usage 计数。流式响应中,连续 usage 和最终 usage 均将内部 token 计数消除。
  4. 测试配套:在 validate.rsconvert.rs 中添加单元测试,覆盖合法和非法 prompt-only 请求的转换与验证。
文件 模块 状态 重要度
rust/src/server/src/routes/openai/completions.rs 请求路由 modified 8.84
rust/src/server/src/routes/openai/completions/convert.rs 请求路由 modified 7.49
rust/src/server/src/routes/openai/completions/validate.rs 请求路由 modified 6.93

关键符号

collect_completion completion_chunk_stream prepare_completion_request validate_request_compat prompt_only_logprobs_to_openai prompt_logprobs_to_maps

关键源码片段

rust/src/server/src/routes/openai/completions/convert.rs core-logic

请求转换层,检测 prompt_only 条件并设置标志,将 max_tokens 替换为 1 以驱动引擎。

// detect prompt-only condition: echo=true and max_tokens=0
let prompt_only = request.echo && request.max_tokens == Some(0);// override max_tokens to 1 so the engine can run
let max_tokens = if prompt_only { Some(1) } else { request.max_tokens };// enable prompt_logprobs for streaming prompt-only case
let prompt_logprobs = request.prompt_logprobs.or(if request.echo && (!request.stream || prompt_only) {
    logprobs
} else {
    None
});

评论区精华

completion_tokens 计数与 Python 不一致 正确性

Reviewer tahsintunan 指出 Rust 返回 completion_tokens=0 而 Python 返回 1。

结论:作者更新为匹配 Python,将 completion_tokens 调整为 1。 · 已解决

代码简化建议(不可达分支) style

tahsintunan 建议简化 else 分支,因为仅当 prompt_logprobs 为 None 时才会触发错误,且逻辑与 streaming 分支重复。

结论:作者重构了代码,共享了 logprobs 处理逻辑。 · 已解决

隐藏内部 token 的 usage 设计

chatgpt-codex-connector 建议将 completion_tokens 和 token_ids 在 prompt-only 响应中置零。

结论:作者决定与 Python 行为对齐,当前已隐藏 token_ids 但 usage 仍计数内部 token(1)。 · 已解决

风险与影响

  • 与 Python 行为对齐的兼容性风险:completion_tokens 计数为 1(内部 token)而非 0,可能引起部分用户困惑,但与 Python 前端行为一致,风险可控。
  • 日志暴露内部 token:当开启 enable_log_requests 时,info! 日志会输出内部 token 计数,可能暴露实现细节。
  • 回归风险:验证层逻辑修改可能影响正常请求,但已有单元测试覆盖,且原有 max_tokens=0 拒绝逻辑仍然保留于 echo=false 场景。

影响范围限定在 Rust 前端 /v1/completions 路由。用户现在可以使用 echo=true, max_tokens=0 进行 prompt-only 请求,行为与 Python 前端一致。支持非流式、流式以及 logprobs 响应。无 Breaking Changes,现有请求行为不变。

兼容性风险 计数一致性 日志暴露内部 token

关联 Issue

#44280 [Roadmap] Rust Frontend Feature Parity

完整报告

参与讨论