Prhub

#47166 [Rust Frontend] Coerce completion `max_tokens: null` to default

原始 PR 作者 blasrodri 合并时间 2026-07-01 14:41 文件变更 2 提交数 1 评论 2 代码增减 +34 / -1

执行摘要

修复 Rust 前端 max_tokens: null 时生成无限制

来自 PR #45491(Python 端修复)的 Rust 对应问题:OpenAI Python SDK 在客户端未设置 max_tokens 时会序列化为 null,而非省略字段。这导致请求处理时 max_tokens 变为 None,进而通过 resolve_max_tokens 使用剩余上下文窗口(max_model_len - prompt_len)作为生成长度,而不是文档中声明的默认 16。这会引发意外的长生成,增加延迟和成本。

值得立即合并,Rust 前端与 Python 前端的行为一致性修复。设计上利用已有的 Normalizable trait 和 ValidatedJson 提取器,无侵入性,值得效仿。

讨论亮点

PR 讨论较少:BugenZhao 直接批准(LGTM. Thanks for the alignment!),无实质争议。自动化代码审查工具 chatgpt-codex-connector 回复“没有发现重大问题”。

实现拆解

  1. types.rs 中实现 Normalizable trait

    • impl Normalizable for CompletionRequest {} 空实现替换为带 fn normalize(&mut self) 的实现。
    • normalize 内检查 self.max_tokens.is_none(),若为真则赋值为 default_completion_max_tokens() 的返回值(即 Some(16))。
    • normalizeValidatedJson 提取器在反序列化后自动调用,无需额外注册。
  2. convert.rs 中添加回归测试

    • 新增测试 normalize_coerces_null_max_tokens_to_default
    • 验证省略 max_tokens 的请求获得 Some(16)(Serde 字段默认)。
    • 验证显式 "max_tokens": null 的请求反序列化为 None,调用 normalize 后变为 Some(16)
    • 新增导入 Normalizable trait。
文件 模块 状态 重要度
rust/src/server/src/routes/openai/completions/types.rs 请求类型 modified 6.65
rust/src/server/src/routes/openai/completions/convert.rs 转换逻辑 modified 6.18

关键符号

normalize normalize_coerces_null_max_tokens_to_default

关键源码片段

rust/src/server/src/routes/openai/completions/types.rs entrypoint

核心修复:实现 `Normalizable` trait 的 `normalize` 方法,处理 `max_tokens: None` 回退到默认值。

impl Normalizable for CompletionRequest {
    /// Normalize the request by applying defaults.
    fn normalize(&mut self) {
        // An explicit `"max_tokens": null` deserializes to `None`, bypassing the
        // serde field default. Coerce it back to the default so it behaves like
        // an absent field, matching Python vLLM's `normalize_null_max_tokens`.
        if self.max_tokens.is_none() {
            self.max_tokens = default_completion_max_tokens();
        }
    }
}

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险极低:

  • 仅影响 CompletionRequestnormalize 流程,且逻辑与 Python 端一致,已在多环境中验证。
  • ChatCompletion 不受影响,其使用 max_completion_tokens 字段,默认行为不同。
  • 改动被单元测试覆盖,且 CI 测试通过。

影响范围:Rust 前端的 /v1/completions 端点。
影响程度:中等。修复了使用 OpenAI Python SDK 客户端时生成无限制的潜在问题,提升与 OpenAI API 的行为兼容性。
用户感知:使用 max_tokens: null 的请求现在会回退到默认 16,而非无限生成。

关联 Issue

#45491 Treat null completion max_tokens like the default

完整报告

参与讨论