Prhub

#47265 [Rust Frontend] Split engine core DTOs into separate modules

原始 PR 作者 BugenZhao 合并时间 2026-07-01 22:28 文件变更 54 提交数 4 评论 1 代码增减 +806 / -789

执行摘要

拆分 engine core DTO 到独立模块

原 mod.rs 混合所有 DTO 定义,导致模块臃肿。拆分后更清晰,并有助于未来隔离北向接口的形状与某些类型的线表示。如 PR body 所述:"making the engine-core-client crate cleaner than mixing all definitions into mod.rs"。

建议阅读:该 PR 展示了如何随 DTO 集合增长进行模块拆分,对关注 Rust 前端架构演进者有价值。普通开发者只需了解新导入路径即可。

实现拆解

  1. 创建子模块文件:新增 request.rs、sampling.rs、output.rs(由原 classified_outputs.rs 重命名并扩充)、structured_outputs.rs,将对应类型定义从 mod.rs 迁移至各文件。
  2. 精简 mod.rs:大量删除被迁移的类型、导入、默认值函数和测试,仅保留 OpaqueValue、encode_msgpack、decode_msgpack 等基础设施及子模块声明。
  3. 更新导入路径:约 50 个文件的 use 语句改为完全限定路径(如 crate::protocol::request::EngineCoreRequest),消除 crate 根级 pub use 重新导出。
  4. 测试随迁:原 mod.rs 中的单元测试按主题分散到新模块文件中,无测试逻辑变更。
    无其他配置或部署配套变更。
文件 模块 状态 重要度
rust/src/engine-core-client/src/protocol/output.rs 输出模型 renamed 9.17
rust/src/engine-core-client/src/protocol/sampling.rs 采样参数 added 9.28
rust/src/engine-core-client/src/protocol/request.rs 请求模型 added 9.28
rust/src/engine-core-client/src/protocol/mod.rs 模块入口 modified 8.94
rust/src/engine-core-client/src/protocol/logprobs.rs 日志概率 modified 7.8
rust/src/engine-core-client/src/protocol/structured_outputs.rs 结构化输出 added 7.46

关键符号

finished resolve_in_place decode_engine_core_outputs from_frame to_frame validate default_top_p default_temperature default_repetition_penalty default_max_tokens for_test

关键源码片段

rust/src/engine-core-client/src/protocol/output.rs rename-or-move

核心输出 DTO 的定义文件,从 classified_outputs.rs 重命名并接收来自 mod.rs 的 EngineCoreOutput、EngineCoreFinishReason、StopReason 等类型,以及 resolve_in_place、finished 等方法。

/// Engine-core output for a single request.
///
/// Original Python definition:
/// <https://github.com/vllm-project/vllm/blob/d3af8c18317c0dc008d42e4367fbb9045cfb7bf6/vllm/v1/engine/__init__.py#L154-L184>
#[derive(Debug, Clone, PartialEq, Serialize_tuple, Deserialize_tuple, DefaultFromSerde)]
pub struct EngineCoreOutput {
    pub request_id: String,
    pub new_token_ids: Vec<u32>,
    #[serde(default)]
    pub new_logprobs: Option<MaybeWireLogprobs>,
    #[serde(default)]
    pub new_prompt_logprobs_tensors: Option<MaybeWireLogprobs>,
    #[serde(default)]
    pub pooling_output: Option<OpaqueValue>,
    #[serde(default)]
    pub finish_reason: Option<EngineCoreFinishReason>,
    #[serde(default)]
    pub stop_reason: Option<StopReason>,
    #[serde(default)]
    pub events: Option<Vec<EngineCoreEvent>>,
    #[serde(default)]
    pub kv_transfer_params: Option<serde_json::Value>,
    #[serde(default)]
    pub trace_headers: Option<OpaqueValue>,
    #[serde(default)]
    pub prefill_stats: Option<PrefillStats>,
    #[serde(default)]
    pub routed_experts: Option<OpaqueValue>,
    #[serde(default)]
    pub num_nans_in_logits: u32,
}
​
impl EngineCoreOutput {
    /// Returns whether this output is terminal for the request.
    pub fn finished(&self) -> bool {
        self.finish_reason.is_some()
    }
​
    /// Resolve all wire-format fields in-place by looking up aux frames and
    /// decoding raw-view payloads as needed.
    fn resolve_in_place<Frame>(&mut self, frames: &[Frame]) -> Result<()>
    where
        Frame: AsRef<[u8]>,
    {
        self.new_logprobs = (self.new_logprobs.take())
            .map(|value| value.resolve(frames, "new_logprobs"))
            .transpose()?;
        self.new_prompt_logprobs_tensors = (self.new_prompt_logprobs_tensors.take())
            .map(|value| value.resolve(frames, "new_prompt_logprobs_tensors"))
            .transpose()?;
        // 其他 wire 字段 (pooling_output, trace_headers) 以类似方式解析
        Ok(())
    }
}

评论区精华

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

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

风险与影响

纯代码移动和导入调整,无功能修改,风险极低。主要风险包括遗漏导入路径更新导致编译错误(但 CI 覆盖)或测试遗漏移动(已按模块分散)。无性能、安全或兼容性影响。

影响 Rust 前端 engine-core-client crate 内部组织及所有依赖它的上层模块(server、parser、llm、chat 等)。开发者需知晓类型现在分散在各模块文件中。涉及 54 个文件,均为 Rust 代码,无 Python/C++ 影响。

纯代码重构 无逻辑变更 导入路径调整范围广 CI 覆盖编译验证

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论