Prhub

#24237 fix: accept 0-indexed safetensors shard names in CI weight validator

原始 PR 作者 alisonshao 合并时间 2026-05-02 15:58 文件变更 1 提交数 2 评论 1 代码增减 +4 / -1

执行摘要

修复 CI 权重校验器对 0 索引分片的误报

python/sglang/srt/model_loader/ci_weight_validation.py 中,_validate_sharded_model 函数硬编码期望分片范围从 1 开始,导致对 0 索引模型(如 inclusionAI/Ring-2.5-1T)误报缺少第 160 个实际不存在的分片。@alisonshao 在 PR body 中说明该误报虽然由于缓存完整不会真正触发下载,但会误导调试,且在冷缓存场景下会导致实际失败的重新下载尝试。

该 PR 修复明确且改动量极小,值得快速合并。但 reviewer 建议的更稳健启发式(检查是否存在分片 0 而非取最小值)可以进一步降低边缘 case 风险,建议作为后续改进项跟踪。

讨论亮点

reviewer gemini-code-assist[bot] 指出当前使用 min(found_shards) 作为起始索引的启发式方法在缺少前几个分片时仍然脆弱——缺失的分片会导致 min 偏移,进而产生更混乱的错误信息。建议改用更稳健的启发式:检测分片 0 是否存在,若存在则假设 0 索引,否则默认 1 索引。此外建议作者在代码库其他位置检查是否有类似逻辑需要同步更新。

此建议未被接受或讨论即被 merged_by Kangyan-Zhou 批准合并(最终版本仍使用 min(found_shards))。这意味着当前方案在缺失分片 0 或前几个分片时仍可能产生误导性错误,但考虑到该函数仅用于 CI 配置校验,且完整缓存是常见场景,风险被认为可接受。

实现拆解

  1. 定位问题:在 _validate_sharded_model 函数中,expected_shards = set(range(1, total_shards + 1)) 硬编码了起始索引为 1。
  2. 修改逻辑:将硬编码的起始索引改为从实际找到的分片集合中动态计算最小 ID:min_idx = min(found_shards) if found_shards else 1,然后构造 set(range(min_idx, min_idx + total_shards))。这样无论分片从 0 还是 1 开始,期望集合均能正确匹配。
  3. 行为验证:PR body 中提供了 4 种典型用例的验证矩阵,确认修改后对 1 索引全量、0 索引全量、1 索引缺片、0 索引缺片均能正确判定。
  4. 清理提交:第二个提交移除了首个提交中增加但不会在 CI 中运行的 test/manual/ 单元测试,保持只包含源码变更。
文件 模块 状态 重要度
python/sglang/srt/model_loader/ci_weight_validation.py 模型加载器 modified 5.91

关键源码片段

python/sglang/srt/model_loader/ci_weight_validation.py data-contract

唯一变更文件,修改 CI 权重校验器的分片编号验证逻辑,直接影响所有分片模型的 CI 行为。

# 在 _validate_sharded_model 函数中,修改前:
# expected_shards = set(range(1, total_shards + 1))
# 修改后:
min_idx = min(found_shards) if found_shards else 1 # 从实际找到的分片推算起始 ID
expected_shards = set(range(min_idx, min_idx + total_shards))
# 后续逻辑不变:
missing_shards = expected_shards - found_shards
if missing_shards:
    return (
        False,
        f"Missing shards in {group_key}: {sorted(missing_shards)}",
        [],
    )

评论区精华

min(found_shards) 启发式的稳健性 正确性

gemini-code-assist[bot] 指出当缓存中前几个分片缺失时,使用 `min(found_shards)` 会导致期望范围偏移,产生更误导的错误信息。建议改用 ' 检查分片 0 是否存在 ' 作为 0 索引判断依据。

结论:未采纳建议;当前 PR 使用 `min(found_shards)` 的版本被批准合并。 · unresolved

风险与影响

  • 回归风险(低):1 索引模型(DeepSeek-V3、Qwen 等)的行为不变,因为 min(found_shards) 在 1 索引全量时仍为 1。
  • 边缘 case 脆弱性(中):如果缓存中前几个分片缺失(例如只有分片 5-9),min(found_shards) 会得到 5,期望范围变为 5-14,与实际总数 10 不匹配,导致错误信息仍不准确。但该场景在 CI 全量缓存中罕见。
  • 性能影响(无):仅增加了 O(1) 的 min() 计算,与 I/O 和文件校验相比微不足道。
  • 安全风险(无):仅涉及本地文件路径比较和集合运算,不涉及网络或用户输入。
  • 用户影响:CI 权重校验不再对 0 索引模型(如 inclusionAI/Ring-2.5-1T)产生误报,避免误导性调试信息和潜在的不必要重下载。
  • 系统影响:限于 CI 流水线中的权重验证步骤,不涉及运行时推理路径。
  • 团队影响:降低维护者排查 CI 失败时的认知负担,提高对异构模型分片命名的容错性。
边缘 case 脆弱性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论