Prhub

#46583 [Rust Frontend] Introduce unified parser interface & combined parser

原始 PR 作者 BugenZhao 合并时间 2026-06-25 11:17 文件变更 74 提交数 5 评论 7 代码增减 +1204 / -1745

执行摘要

统一解析器接口,整合 tool/reasoning parser

现有架构中 reasoning 和 tool 解析分为两个独立阶段,导致处理混合输出时很笨拙,例如 <channel_thinking>...<end> <channel_tool>...</end> 这类块式输出难以自然处理。PR body 提到:“This refactoring unblocks implementing a real unified parser in the future that can handle block-style output more naturally”。统一解析器接口允许未来更自然的块式输出处理。

值得精读。本 PR 展示了如何通过统一的 trait 接口和组合模式重构一个分离的解析流水线,使其易于扩展。重点关注 UnifiedParser trait 的设计、CombinedParser 的编排策略以及 error recovery 的折衷。对于想深入了解 vLLM Rust 前端架构的开发者是极好的参考。

讨论亮点

核心讨论包括:

  • njhillcombined.rs 评论:"Does it matter that we'll lose partial output here on errors?" 作者 BugenZhao 回复:"Good catch! We should defer throwing the error after calling output.append_tool_output." 此问题已在后续 commit handle partial failure in combined parser 中修复。
  • chatgpt-codex-connectormod.rs 提出:append_tool_output 总是先将 normal_text 放入事件流,可能破坏 tool-call 事件顺序(P1)。BugenZhao 回应:"Will be covered in #46584",表明已知并将在下游 PR 修复。

实现拆解

  1. 定义 UnifiedParser trait:在 rust/src/parser/src/unified/mod.rs 中定义 UnifiedParser trait 及其相关类型(UnifiedParserOutputUnifiedParserEvent),统一定义解析事件(Text、Reasoning、ToolCall)。
  2. 实现 CombinedParser:在 rust/src/parser/src/unified/combined.rs 中实现 CombinedParser,同时持有可选的 ReasoningParserToolParserparse_into 方法先使用 reasoning parser 拆分解码文本,再将非 reasoning 部分传给 tool parser。
  3. 更新 chat 层:在 rust/src/chat/src/output/default/unified.rs 新增 UnifiedParserState,替代原来的两阶段状态机(ReasoningStateToolState),直接驱动 UnifiedParser 并将事件转换为 AssistantEvent
  4. 删除旧模块:移除 reasoning.rstool.rs 文件,删除两阶段流式处理。
  5. 文件重组:将 rust/src/tool-parser/ 重名命并移动到 rust/src/parser/src/tool/,统一 parser crate 结构,保持 Python 绑定兼容。
  6. 测试适配:添加 combined.rs 单元测试(使用 FakeTokenizer),更新 chat output 测试以使用统一流式处理。
文件 模块 状态 重要度
rust/src/parser/src/unified/mod.rs 解析接口 added 8.81
rust/src/parser/src/unified/combined.rs 组合解析器 added 9.18
rust/src/chat/src/output/default/unified.rs 状态机 added 9.18

关键符号

CombinedParser::new CombinedParser::parse_into CombinedParser::parse_tool CombinedParser::flush_tool UnifiedParserState::process_delta UnifiedParserState::initialize UnifiedParserState::finish UnifiedParserOutput::append_tool_output UnifiedParserOutput::push_text UnifiedParserOutput::push_reasoning

关键源码片段

rust/src/parser/src/unified/combined.rs core-logic

CombinedParser 实现 UnifiedParser,合并两个现有解析器,是核心适配器。

//! 组合解析器适配器,包装 reasoning 和 tool 解析器。/// 新建组合解析器,可指定 reasoning 和 tool 解析器(均为可选)。
pub fn new(
    reasoning: Option<Box<dyn ReasoningParser>>,
    tool: Option<Box<dyn ToolParser>>,
) -> Self {
    Self { reasoning, tool }
}/// 将一段解码后的文本增量送入组合解析器。
///
/// 先经 reasoning 解析器拆分,再将非 reasoning 部分送入 tool 解析器。
fn parse_into(&mut self, delta: &str, output: &mut UnifiedParserOutput) -> Result<()> {
    // 如果没有配置 reasoning 解析器,直接走 tool 解析器
    let Some(reasoning) = self.reasoning.as_mut() else {
        return self.parse_tool(delta, output);
    };    // reasoning 解析器将 delta 分为 reasoning 和 content 两部分
    let reasoning_delta = reasoning.push(delta)?;
    if let Some(reasoning) = reasoning_delta.reasoning {
        output.push_reasoning(reasoning);
    }
    if let Some(content) = reasoning_delta.content {
        // tool 解析器只处理非 reasoning 文本
        self.parse_tool(&content, output)?;
    }
    Ok(())
}

评论区精华

错误处理中部分输出丢失 正确性

njhill 在 combined.rs 评论询问:在错误时是否会丢失部分输出?

结论:BugenZhao 同意,并修改为在抛出错误前先调用 output.append_tool_output 保存部分结果。已在后续 commit 中修复。 · 已解决

tool-call 事件顺序 正确性

chatgpt-codex-connector 指出 UnifiedParserOutput::append_tool_output 总是先将 normal_text 推入事件流,可能导致 tool-call 事件顺序错误。

结论:BugenZhao 回应将在 #46584 中处理该问题,当前 PR 暂不修复。 · pending

风险与影响

主要风险:

  1. 事件顺序UnifiedParserOutput::append_tool_output 的默认实现可能导致 tool-call 和 text 事件相对顺序错误(已识别,待后续修复)。
  2. 错误处理:当 reasoning 或 tool 解析器失败时,可能丢失部分已解析输出。已在 parse_toolparse_into 中通过先保存 partial 结果再返回错误来缓解。
  3. 文件搬迁:Cargo.toml 和导入路径必须正确,否则编译失败。已通过实验确认通过。
  4. 行为一致:重构应保持原有行为,但不同边界情况(如两个 parser 同时抛出错误)可能引入回归。

对用户和外层 API 无影响。对系统:Rust 解析流水线架构更清晰,消除两阶段分离,为后续支持混合内容(如同时包含 reasoning 和 tool call)提供了统一的扩展点。对开发团队:降低维护成本,新解析策略只需实现 UnifiedParser 即可。测试覆盖主要流程但缺少端到端模糊测试。

核心解析流水线重构 事件顺序依赖 错误恢复逻辑变更

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论