Prhub

#46137 [Rust Frontend] Support thinking_token_budget for chat and completions

原始 PR 作者 ricky-chaoju 合并时间 2026-06-22 16:00 文件变更 13 提交数 3 评论 6 代码增减 +178 / -7

执行摘要

Rust 前端支持 thinking_token_budget 参数,实现与 Python 前端对等

PR body 明确指出:“Add support for the thinking_token_budget request parameter in the Rust frontend, for both /v1/chat/completions and /v1/completions, reaching parity with the Python frontend (tracked in #44280, "Request compatibility and validation")”。此前 V1 引擎已支持该参数,Python 前端已对外暴露,但 Rust 前端存在功能缺口。此变更消除了这个差距。

建议

  • 该 PR 值得精读,特别是 normalize_thinking_token_budget 函数的设计(与 Python 逻辑紧密对齐)以及三个转换层统一透传模式。它展示了 Rust 前端如何通过降层(lowering)集中处理参数验证,保持代码整洁。
  • 关注后续跟着的推理解析器传递配套 PR,以完全解决 managed-engine 模式下的功能限制。
  • 代码审查中应关注字段解构顺序的脆弱性,但当前设计合理。
讨论亮点

review 讨论要点

  • P2 议题:Codex 机器人评论指出,当 thinking_token_budgetSome 时,如果 Rust managed-engine 模式没有传递 --reasoning-parser,引擎端可能拒绝请求返回 500。但作者回应确认,引擎端 ThinkingBudgetStateHolderreasoning_configNone 时静默忽略预算,不会报错,因此不会 500。这是一个已知限制,而非回归。
  • 后续跟进:BugenZhao 指出,Rust 前端默认自动解析推理解析器,但 ManagedEngine 未将推理解析器选择传递到 Python 引擎,可能导致 thinking_token_budget 在 managed-engine 模式下被静默忽略。他计划在后续 PR 中一并修复推理解析器传递问题。作者致谢。
  • 共识:PR 本身正确实现了前端透传与规范化,限制在后续迭代中解决,因此批准合并。

实现拆解

实现步骤

  1. 添加协议定义:在 rust/src/engine-core-client/src/protocol/mod.rsEngineCoreSamplingParams 结构体中新增 thinking_token_budget: Option<u64> 字段,用于引擎核心消费。该字段表示推理预算,None 为无限制。

  2. 核心规范化函数:在 rust/src/text/src/lower.rs 中新增 normalize_thinking_token_budget 函数,将用户侧 Option<i64> 转换为引擎侧 Option<u64>,规则与 Python validate_thinking_token_budget 一致:None-1 映射为 None(无限制),非负整数直接通过,其他负值拒绝并返回 InvalidThinkingTokenBudget 错误。在 lower_sampling_params 函数内解构 SamplingParams 时提取 thinking_token_budget,调用规范化函数后赋值给 EngineCoreSamplingParams

  3. 三个请求入口透传

    • Chat completions (rust/src/server/src/routes/openai/chat_completions/convert.rs):在 prepare_chat_request 中将 request.thinking_token_budget 直接传递给 SamplingParams
    • Completions (rust/src/server/src/routes/openai/completions/convert.rs):在 prepare_completion_request 中同样直接透传。
    • Inference generate (rust/src/server/src/routes/inference/generate/convert.rs):在 prepare_generate_request 中从 sampling_params.thinking_token_budget 读取并传递。

注意:转换层仅透传原始值(包括 -1 哨兵),不做任何验证,验证延迟到降层统一进行。

  1. 错误映射:在 rust/src/server/src/error.rs 中将 vllm_text::Error::InvalidThinkingTokenBudget 加入请求验证错误集合,确保无效值返回 400 Bad Requestinvalid_request_error 类型。

  2. 移除旧拒绝逻辑:在 rust/src/server/src/routes/openai/chat_completions/validate.rs 中删除了之前显式拒绝 thinking_token_budget 的代码(该代码返回“thinking_token_budget is not supported”错误)。

  3. 测试覆盖:每个转换层新增一个测试用例验证字段正确透传;lower.rs 新增 lower_sampling_params_normalizes_thinking_token_budget 测试覆盖归一化规则;error.rs 新增 invalid_thinking_token_budget_maps_to_invalid_request 测试验证错误映射。同时在多个现有测试中补全了 thinking_token_budget: None 默认值以保持编译。

文件 模块 状态 重要度
rust/src/text/src/lower.rs 文本处理 modified 7.86
rust/src/server/src/routes/openai/chat_completions/convert.rs 服务端 modified 6.74
rust/src/server/src/routes/openai/completions/convert.rs 服务端 modified 6.77
rust/src/server/src/routes/inference/generate/convert.rs 服务端 modified 6.75
rust/src/server/src/error.rs 服务端 modified 6.22
rust/src/engine-core-client/src/protocol/mod.rs 引擎协议 modified 5.44

关键符号

normalize_thinking_token_budget lower_sampling_params prepare_chat_request prepare_completion_request prepare_generate_request

关键源码片段

rust/src/text/src/lower.rs core-logic

核心降层逻辑,新增 normalize_thinking_token_budget 函数,在 lower_sampling_params 中进行参数规范化,是 PR 的枢纽模块。

/// 将用户侧的 thinking_token_budget(Option<i64>)规范化为引擎侧 Option<u64>。
/// 与 Python validate_thinking_token_budget 语义一致:
/// - None 或 -1 → None(无限制)
/// - 非负值 → Some(value)(直接传递)
/// - 其他负值 → 错误 InvalidThinkingTokenBudget
fn normalize_thinking_token_budget(value: Option<i64>) -> Result<Option<u64>> {
    match value {
        None | Some(-1) => Ok(None), // 视作无限制
        Some(budget) if budget >= 0 => Ok(Some(budget as u64)), // 有效预算
        Some(_) => Err(Error::InvalidThinkingTokenBudget), // 非法负值
    }
}// 在 lower_sampling_params 中使用:
let thinking_token_budget = normalize_thinking_token_budget(thinking_token_budget)?;
// 然后赋值给 EngineCoreSamplingParams 的对应字段

评论区精华

Managed-engine 模式下 reasoning parser 未同步导致 budget 被静默忽略 设计

Codex 机器人初评提醒可能引擎端拒绝请求,但作者澄清不会。之后 BugenZhao 指出 Rust 前端 auto-resolve 推理 parser 但未传递给 managed engine Python 进程,导致 budget 被静默忽略,计划在后续 PR 中统一修复。

结论:这是一个已知限制,需在后续 PR 中传递推理 parser 配置。当前 PR 已正确实现基础功能,可合并。 · resolved_with_follow_up

风险与影响

风险分析

  • 兼容性风险:Rust 前端新增字段,但未变更已有接口格式,向后兼容。但对依赖 Rust 前端的非标准 client 可能观察到新字段被忽略(如果未传递到引擎)。无破坏性。
  • 功能正确性风险:在 Rust managed-engine 模式下若 reasoning_parser 未同步,thinking_token_budget 会被静默忽略,用户以为预算生效但实际未生效。讨论已确认这是已知限制,但 PR 本身未解决,可能引起困惑。
  • 安全风险:无上界验证,用户可设置极大值(如 i64::MAX),但引擎端有算力限制,不视为安全漏洞。
  • 回归风险:新增字段测试覆盖较好,且为简单透传,回归概率低。但依赖 SamplingParams 解构顺序——如果未来添加新字段,需注意字段顺序。改进建议:考虑在 managed-engine 模式下添加推理解析器传递的警告或自动同步机制。

影响分析

  • 用户可见影响:Rust 前端的 chat/completions 端点现在接受并处理 thinking_token_budget,返回值符合预期。之前明确出错或未定义的行为变为正常工作(取决于引擎配置)。
  • 系统层面:仅 Rust 前端内部变更,不影响 Python 前端或 V1 引擎核心。传输协议新增 DTO 字段,但前向兼容。
  • 团队协作:与 #44280 追踪项关联,完成 Rust 前端请求兼容性对等工作。后续 PR 需修复推理解析器传递问题以完全生效。
  • 影响程度:中等。对使用 Rust 前端进行推理预算控制的用户有直接影响。
managed-engine 模式 budget 可能静默无效 无上界验证可能被滥用

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论