Prhub

#56915 [Bugfix][Rust] Fix HF multi-turn dataset integration

原始 PR 作者 khluu 合并时间 2026-09-15 09:04 文件变更 2 提交数 1 评论 5 代码增减 +68 / -10

执行摘要

修复 Rust 多轮 bench 的 HF 数据集集成断裂

PR #51104 于 9 月 14 日通过精确 CI 后合入 main,但其最后一次 rebase 停留在 8 月 17 日;8 月 21 日 #51570 已将 download_hf_dataset 从四参数、返回路径的 API 改为六参数、返回反序列化行的 API。过期分支头在只编译自身 head 的精确 CI 上通过,掩盖了与当前 main 合成后的集成断裂,导致 #88956/#88957 等 main 构建在 CPU/CUDA/XPU/AMD 镜像与 CPU Rust 门禁上以 E0061/E0308 失败。PR body 明确选择「把新特性更新到当前 API,而非回退任一兼容特性」,并完成 duplicate-work 检查确认无其他 PR 修复该断裂。

值得精读。一是事故根因复盘:过期 head 在精确 CI 上通过后合入,暴露了「只验证 PR 头、不验证合成 merge」的流程盲区;二是「升级到新 API 而非回退特性」的修复决策;三是 load_sharegpt_multi_turn_from_rows 的抽取方式,把「数据来源(文件/行)」与「解析语义(过滤/洗牌/构建)」解耦,是低成本、可测试的架构改进。建议顺带确认双重 shuffle 语义是否符合预期,并考虑在 CI 中增加对合成 merge 的编译检查(与 #56169 配合)。

讨论亮点

核心讨论集中在合并门禁的证据纪律上。khluu 先以字面 head fa4403f 启动 #88961 声称是决定性机器门禁,随后自我更正:style lane 捕获了 rustfmt-only 差异,该构建已过期,仅剩诊断价值;应用 CI 格式化输出后推送字面 head 0ce0bec 并启动替代构建 #88963,并明确「只有 #88963 应作为 merge-gate 证据」。随后 #88964 独立复现同一 E0061/E0308 编译失败,确认断裂是确定性的、重试无意义,合并后首个自然 main 构建通过 Rust 门禁才算事故闭环。另外 PR body 明确披露 AI 辅助诊断与实现、刻意保持 draft 直至 khluu 能逐行 defend;claude[bot] 因 fork 自动审查被禁用,Codex 审查在 draft 转 ready 后完成且无 findings,esmeetu 批准。

实现拆解

  1. 调用点升级(rust/src/bench/src/multi_turn.rs):run_multi_turn_benchmark 中 DatasetName::Hf 分支原按四参数调用 download_hf_dataset 并拿回 downloaded_path 字符串路径;现改为六参数(新增 config.seed 与 config.disable_shuffle),返回值解构为 (rows, _config, _split),下游改调 load_sharegpt_multi_turn_from_rows。这正是 E0061「参数个数不匹配」与 E0308「路径 vs 行数组类型不匹配」两个编译错误的直接位置。
  2. 解析器抽取(rust/src/bench/src/datasets/multi_turn.rs):原 load_sharegpt_multi_turn 保留「读文件 → 解析 JSON 数组」的职责,拿到 entries 后委托给新函数 load_sharegpt_multi_turn_from_rows;「至少 4 条消息过滤、StdRng 固定种子洗牌、conversation 构建」等核心逻辑整体下移,文件输入与 HF 行输入从此共享同一套解析语义,避免双实现漂移。
  3. 离线回归测试:mod tests 新增 test_load_sharegpt_multi_turn_from_hf_rows,用 serde_json::json! 直接构造 4 条消息的 ShareGPT 行,断言 conversation_id == "hf-conv-0"、两轮 user_message 与 expected_output_len == 7,无网络依赖,可在纯 CPU Cargo 门禁运行。
  4. 验证配套:作者本机无 Cargo,先跑 pre-commit 与 git diff --check,再以字面 head 启动 Buildkite #88963(Cargo 1,798/1,798 通过、13 skipped;style+clippy 通过)。期间 #88961 暴露 rustfmt 差异,按 CI 格式化输出原样修正后重推 head 0ce0bec。未改动 rust/src/bench/src/config.rs,seed、disable_shuffle 复用既有配置字段,无配置或 schema 迁移。
文件 模块 状态 重要度
rust/src/bench/src/datasets/multi_turn.rs 基准工具 modified 7.24
rust/src/bench/src/multi_turn.rs 基准工具 modified 6.15

关键符号

load_sharegpt_multi_turn load_sharegpt_multi_turn_from_rows run_multi_turn_benchmark test_load_sharegpt_multi_turn_from_hf_rows

关键源码片段

rust/src/bench/src/multi_turn.rs core-logic

触发编译错误的直接调用点:`DatasetName::Hf` 分支从四参数路径返回调用升级为六参数行返回调用,是修复 E0061/E0308 的关键一环。

// rust/src/bench/src/multi_turn.rs(run_multi_turn_benchmark 内 DatasetName::Hf 分支)
DatasetName::Hf => {
    let tok = tokenizer
        .as_ref()
        .ok_or_else(|| BenchError::Config("HF dataset requires a tokenizer".into()))?;
    let dataset_id = config.dataset_path.as_deref().ok_or_else(|| {
        BenchError::Config("--dataset-path is required for --dataset-name hf".into())
    })?;
​
    // #51570 之后 download_hf_dataset 变为六参数、直接返回反序列化行;
    // 旧的四参数「返回文件路径」调用正是 E0061/E0308 编译失败的根源
    let (rows, _config, _split) = crate::datasets::hf_dataset::download_hf_dataset(
        dataset_id,
        config.hf_subset.as_deref(),
        config.hf_split.as_deref(),
        config.num_prompts,
        config.seed,
        config.disable_shuffle,
    )
    .await?;
​
    // 不再把 rows 当作文件系统路径,直接交给与文件输入共享的 ShareGPT 解析器
    crate::datasets::multi_turn::load_sharegpt_multi_turn_from_rows(
        tok,
        &rows,
        config.num_prompts,
        config.hf_output_len,
        config.sharegpt_multi_turn_max_turns,
        config.seed,
        &config.request_id_prefix,
    )?
}

评论区精华

精确 head 的 CI 门禁证据 测试

khluu 先以字面 head `fa4403f` 启动 #88961 声称是决定性机器门禁,随后自我更正:style lane 捕获了 rustfmt-only 差异,该构建已过期、仅剩诊断价值;按 CI 格式化输出修正后推送字面 head `0ce0bec` 并启动替代构建 #88963。

结论:仅 #88963 可作为合并门禁证据:Cargo 1,798/1,798 通过、style+clippy 通过、pre-commit 通过。 · 已解决

main 构建断裂的确定性确认 other

khluu 报告 #88964 独立复现同一 E0061/E0308 `vllm-bench` 编译断裂,覆盖 CUDA/CPU/AMD 镜像与 CPU language shards,结论是重试无意义。

结论:合并 PR 后首个自然 main 构建通过 Rust 门禁即为事故闭环;合并前无法仅靠重试恢复 main。 · 已解决

AI 辅助实现与人工逐行审查门槛 question

PR body 披露 AI 用于诊断与实现,并刻意保持 draft,要求 khluu 能 defend 每一行后才标记 ready;claude[bot] 因 fork 自动审查被禁用;Codex 审查在 draft 转 ready 后完成且无 findings;esmeetu 批准。

结论:draft 转 ready、人工审查完成并获得批准后合并。 · 已解决

风险与影响

契约耦合风险:修复硬依赖 download_hf_dataset 的六参数行返回签名,该 API 两周内已发生一次破坏性变更,若继续演进需同步此调用点;作者也把「合并后首个自然 main 构建通过 Rust 门禁」设为事故闭环条件。双重 shuffle 语义:download_hf_dataset 现在按 seed 内部洗牌(除非 disable_shuffle),而 load_sharegpt_multi_turn_from_rows 又用同一 seed 二次洗牌并截取 num_prompts 行;相同 seed 下结果确定可复现,但抽样子集与单轮 HF 路径可能不一致,且 disable_shuffle 只能关闭第一层洗牌。测试覆盖缺口:新增测试只覆盖行解析层,未覆盖 run_multi_turn_benchmark 的 HF 分支整体;既有 test_prefix_sharing_structure 为 #[ignore] 网络测试。影响面集中在 Rust 基准客户端,不触碰模型执行、调度与推理内核,但编译失败在合并前会让所有平台镜像构建全红。

用户侧:启用 --dataset-name hf --multi-turn 的 Rust 基准用户恢复可用,支持 ShareGPT 格式的 HF 数据集行(如 Inferact/codex_swebenchpro_traces)。系统侧:解除 main 全平台镜像构建与 CPU Rust 门禁上的确定性 E0061/E0308 失败,恢复 vllm-bench crate 可编译状态。团队侧:这是「过期头 + 精确 CI 通过」合并事故的修复样本,与 #56169 的分支新鲜度检查形成呼应,说明 CI 应补上「合成 merge 后编译验证」这一空白;同时展示了字面 head 门禁、独立事故复现(#88964)等可复用的验证纪律。

主分支全平台编译断裂 依赖 download_hf_dataset 契约 双重 shuffle 语义需确认 HF 分支缺端到端测试

关联 Issue

#51104 [Rust][Benchmark] Support HF ShareGPT datasets in multi-turn mode
#55937 [vllm-bench, feature] Added support for Mooncake-style, timed-traces replay.

完整报告

参与讨论