Prhub

#44901 [Rust Frontend] Support Kimi K2 tool call IDs

原始 PR 作者 cinnamonica02 合并时间 2026-06-09 20:31 文件变更 5 提交数 1 评论 2 代码增减 +147 / -8

执行摘要

支持 Kimi K2 模型生成的 tool call ID

Kimi K2 模型在 tool call header 中定义了原始 ID(如 functions.{name}:{index}),Rust 前端此前总是使用 call_<uuid> 作为 ID,导致与 Python 端行为不一致,且 tool_call_mix roundtrip 测试无法通过。PR #44901 基于 output/mod.rs 中的 TODO 注释,实现了对模型生成 ID 的保留。

值得精读。设计上通过 trait 方法提供扩展点,替代硬编码 ID 生成,体现了开闭原则。review 中 BugenZhao 建议启用 roundtrip 测试,是验证变更正确性的好实践。对需要为其他模型定制 tool call ID 的开发者具有参考价值。

讨论亮点

BugenZhao 在评论中建议作者同时取消注释 roundtrip 测试中的 kimi_k25 用例,因为本 PR 已解除了阻塞;作者照做并重新提交。该讨论已解决,无未解决的争议。

实现拆解

  1. 扩展 ToolParser trait (lib.rs):添加默认返回 Nonetool_call_id(&self, tool_index: usize) -> Option<&str> 方法,为 parser 提供可选 hook。
  2. Kimi K2 parser 存储 ID (kimi_k2.rs):在结构体新增 call_ids: BTreeMap<usize, String> 字段;在 apply_event 处理 ToolCallHeader 时,从原始 header 中提取 tool_call_id 并存入映射;实现 tool_call_id() 方法查询映射;在 reset() 中清理映射。
  3. 输出流使用 parser ID (tool.rs):修改 process_tool_items 中生成 ToolCallStart 事件的逻辑:先调用 self.parser.tool_call_id(item.tool_index),若返回 Some 则使用该 ID,否则 fallback 到 generate_tool_call_id()
  4. 清理 TODO (mod.rs):移除 generate_tool_call_id 旁的 TODO: support other ID scheme like Kimi-K2's 注释。
  5. 启用 roundtrip 测试 (roundtrip.rs):取消 kimi_k25 => [tool_call_mix] 的注释,确保生成 ID 后该测试通过。
    测试方面:新增 tool_stream_preserves_parser_provided_tool_call_idtool_stream_generates_tool_call_id_when_parser_omits_one 两个异步测试,以及 kimi_k2_preserves_model_generated_tool_call_ids 单元测试。
文件 模块 状态 重要度
rust/src/chat/src/output/default/tool.rs 聊天处理 modified 8.54
rust/src/tool-parser/src/kimi_k2.rs 工具解析器 modified 7.47
rust/src/tool-parser/src/lib.rs 工具解析器 modified 5.97
rust/src/chat/src/output/mod.rs 聊天处理 modified 4.54
rust/src/chat/tests/roundtrip.rs 端到端测试 modified 3.86

关键符号

ToolParser::create ToolParser::tool_call_id ToolState::process_tool_items KimiK2ToolParser::tool_call_id KimiK2ToolParser::apply_event generate_tool_call_id

关键源码片段

rust/src/tool-parser/src/kimi_k2.rs core-logic

Kimi K2 parser 存储模型生成的 tool call ID,并通过 tool_call_id() 暴露给输出流。

// 存储模型生成的 tool call ID ( 例如 "functions.get_weather:0")
pub struct KimiK2ToolParser {
    buffer: String,
    mode: KimiK2Mode,
    active_tool_index: Option<usize>,
    call_ids: BTreeMap<usize, String>, // 新增字段
}impl ToolParser for KimiK2ToolParser {
    fn tool_call_id(&self, tool_index: usize) -> Option<&str> {
        self.call_ids.get(&tool_index).map(String::as_str)
    }
}// 在 apply_event 中处理 ToolCallHeader 时存储 ID
KimiK2Event::ToolCallHeader { tool_call_id, function_name, function_index } => {
    let tool_index = function_index;
    self.call_ids.insert(tool_index, tool_call_id); // 存储 ID
    output.calls.push(ToolCallDelta {
        tool_index,
        name: Some(function_name),
        arguments: String::new(),
    });
}

评论区精华

启用 Kimi K2 roundtrip 测试 测试

BugenZhao 建议取消注释 roundtrip.rs 中 kimi_k25 的 tool_call_mix 测试项(原因为之前不尊重模型生成的 tool call ID 而注释)。

结论:作者取消注释并提交,测试通过。 · 已解决

风险与影响

风险较低。改动仅限于 Rust 前端,且向后兼容:ToolParser::tool_call_id 默认返回 None,不影响其他 parser。Kimi K2 parser 修改局限在自身模块。新增测试覆盖了核心路径。主要风险为 tool_call_id 返回的字符串若包含非法字符可能导致下游解析异常,但 Kimi K2 的 ID 格式已知且已在 Python 端验证。

对用户:Kimi K2 模型输出中的 tool call ID 现在保留原始值,便于应用层关联调用。对其他模型无影响。对系统:新增 trait 方法不会影响现有 parser 的编译或运行。对团队:清理了 TODO,解锁了 roundtrip 测试,提升了 Rust 前端对 Kimi K2 的兼容性。影响程度中等(仅限 Kimi K2 模型且限于 Rust 前端)。

向后兼容 测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论