执行摘要
- 一句话:同步 Rust 与 Python 的 EngineCoreReadyResponse 字段定义
- 推荐动作:建议团队在涉及跨语言协议定义时,借鉴本 PR 中 Python→Rust 双向键集合断言的测试方法,防止字段版本漂移。值得精读
python_compat.rs 的测试夹具设计。
功能与动机
PR 描述中指出:“The Rust EngineCoreReadyResponse had fallen three fields behind the Python dataclass: block_size (required) plus the optional kv_cache_size_tokens and kv_cache_max_concurrency. Registration is a field-keyed map, so a Rust engine encoding the response omits block_size and the Python frontend rejects it on decode.” 该问题导致 vllm-mock-engine 无法与 Python 前端完成注册。
实现拆解
- Rust 结构体补全:在
rust/src/engine-core-client/src/protocol/handshake.rs 的 EngineCoreReadyResponse 结构体中增加 block_size: u64(必需)、kv_cache_size_tokens: Option<u64> 和 kv_cache_max_concurrency: Option<f64>(可选),并更新文档注释中的 Python 源码链接。
- Mock 引擎默认值:在
rust/src/engine-core-client/src/mock_engine.rs 中添加常量 DEFAULT_MOCK_BLOCK_SIZE = 16,并在 default_ready_response() 函数中为新字段赋默认值(可选字段赋 None)。
- Python 测试夹具:新建
rust/src/engine-core-client/src/tests/python_compat.py,用 msgspec 定义与 Python 生产逻辑一致的 EngineCoreReadyResponse dataclass,编码并打印十六进制输出。
- Rust 集成测试增强:在
rust/src/engine-core-client/src/tests/client.rs 的 python_msgpack_fixtures_match_rust_encoding 测试中新增一步:解码 Python 输出的 ready_response 键集合,与 Rust default_ready_response() 编码后的键集合做全等断言,若双方字段不匹配则测试失败。
关键文件:
rust/src/engine-core-client/src/protocol/handshake.rs(模块 协议层;类别 source;类型 core-logic;符号 EngineCoreReadyResponse): 核心修复文件,在 EngineCoreReadyResponse 结构体中新增三个字段,确保 Rust 序列化格式与 Python 一致。
rust/src/engine-core-client/src/mock_engine.rs(模块 模拟引擎;类别 source;类型 core-logic;符号 default_ready_response, DEFAULT_MOCK_BLOCK_SIZE): 更新 default_ready_response() 为所有新字段提供默认值,保证 mock 引擎能生成合法的 ready 响应。
rust/src/engine-core-client/src/tests/python_compat.py(模块 兼容测试;类别 test;类型 test-coverage;符号 EngineCoreReadyResponse): 新增的 Python 测试夹具,定义 EngineCoreReadyResponse dataclass 并输出其 msgpack 十六进制,供 Rust 测试提取键集合进行双向兼容性断言。
rust/src/engine-core-client/src/tests/client.rs(模块 客户端测试;类别 test;类型 test-coverage;符号 python_msgpack_fixtures_match_rust_encoding): 增强现有 python_msgpack_fixtures_match_rust_encoding 测试,新增 Python 端 ready_response 键集合与 Rust 默认响应的键集合断言,防止未来字段漂移。
关键符号:EngineCoreReadyResponse::new (struct definition), default_ready_response, python_msgpack_fixtures_match_rust_encoding
关键源码片段
rust/src/engine-core-client/src/protocol/handshake.rs
核心修复文件,在 EngineCoreReadyResponse 结构体中新增三个字段,确保 Rust 序列化格式与 Python 一致。
/// Post-initialization configuration sent from each engine on the input socket
/// registration message, after the handshake completes.
///
/// Contains values that may differ from the original config (e.g.
/// `max_model_len` after KV cache auto-fitting, `num_gpu_blocks` after
/// profiling).
///
/// Original Python definition:
/// <https://github.com/vllm-project/vllm/blob/c9340e6f35/vllm/v1/engine/__init__.py#L68-L80>
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EngineCoreReadyResponse {
/// Engine-reported maximum model context length (auto-fitted after
/// KV cache profiling and may differ from the original config value).
pub max_model_len: u64,
/// Number of GPU blocks available for KV cache on this engine.
pub num_gpu_blocks: u64,
/// KV cache block size (tokens per block). 此前 Rust 遗漏该必需字段,
/// 导致 Python 前端解码时抛出 `ValidationError`。
pub block_size: u64,
/// DP coordinator stats publish address, if applicable.
pub dp_stats_address: Option<String>,
/// Effective model dtype after Python vLLM resolves `--dtype`.
pub dtype: ModelDtype,
/// Python vLLM version reported by the engine process.
pub vllm_version: String,
/// Total KV cache capacity in tokens, if reported. 新增可选字段,用于
/// 调度器感知缓存容量。
pub kv_cache_size_tokens: Option<u64>,
/// Maximum achievable request concurrency given the KV cache, if reported.
/// 新增可选字段,用于前端判断并发度。
pub kv_cache_max_concurrency: Option<f64>,
}
rust/src/engine-core-client/src/tests/python_compat.py
新增的 Python 测试夹具,定义 EngineCoreReadyResponse dataclass 并输出其 msgpack 十六进制,供 Rust 测试提取键集合进行双向兼容性断言。
from dataclasses import dataclass
# 其余导入略 ...
@dataclass
class EngineCoreReadyResponse:
max_model_len: int
num_gpu_blocks: int
block_size: int # 必需字段,Rust 侧之前遗漏导致崩溃
dp_stats_address: str | None
dtype: str
vllm_version: str
kv_cache_size_tokens: int | None = None # 可选字段,同步添加
kv_cache_max_concurrency: float | None = None
# 构造一个典型实例,用于与 Rust 编码结果对比
ready_response = EngineCoreReadyResponse(
max_model_len=32768,
num_gpu_blocks=1000,
block_size=16,
dp_stats_address=None,
dtype="float32",
vllm_version="0.0.0",
)
# 输出 hex 供 Rust 测试解析
print(msgspec.msgpack.encode(ready_response).hex())
评论区精华
PR 仅有一条 Mergify 自动评论提醒 pre-commit 格式化失败,随后 BugenZhao 提交了格式化修正 commit 并批准。此外无其他技术讨论。
风险与影响
- 风险:此修改针对远程 Rust 引擎注册场景,对纯 Python 前端无影响。风险较低,但仍需关注:
- 若 Python 侧再次新增字段而未同步到 Rust,新增的测试会立即失败,这正是期望的防御效果。
- 新增两个
Option 字段对下游消费者无破坏性,但若消费者期望这些字段存在而收到 None 可能需调整逻辑。
- 影响:影响范围:主要影响使用 Rust 引擎客户端(如
vllm-mock-engine)与 Python 前端通过 Data Parallel 协议通信的场景。修复后远程引擎可成功注册,API 服务器能正常启动。影响程度:中等,属于阻塞性 bug 修复。
- 风险标记:跨语言序列化一致性, 协议漂移(已防御)
关联脉络
参与讨论