执行摘要
- 一句话:移除 SGL_EVAL_SPEC 空格,修复 AMD ROCm 7.2 stage-a 安装失败
- 推荐动作:建议快速浏览本 PR:改动只有一行,但讨论区有信息量。值得学习的点包括:用 stub 报告 argc 的方式可复现地证明拆词问题;在 review 要求下主动回退大规模重写、保留外科手术式最小修复;对遗留的 eval 隐患明确划界并拆分为后续 PR。可关注作者声明的 eval 修复后续提交,以及 stage-b 的 antlr4 冲突修复。
功能与动机
PR body 明确说明 stage-a-test-1-gpu-small-amd-rocm720 在每次通过 label 门禁的 PR Test ROCm 7.2(AMD)上必失败:pip install sgl-eval @ git+... 报 Invalid requirement: '@',3 次重试一致失败,镜像 fallback 无法解决(语法错误而非网络问题)。stage-a 门禁阻断所有下游 AMD leg,导致 AMD ROCm 7.2 的 CI 完全不可用,需要先解除这一阻塞。
实现拆解
实现过程分 4 步:
-
根因定位:对比各平台调用方式,CUDA($PIP_CMD install "$SGL_EVAL_SPEC")和 NPU(${UV_PIP_INSTALL} "$SGL_EVAL_SPEC")都带引号直接调用 pip,只有 AMD 的 install_with_retry 用 local cmd="$@" 拼接后执行 eval "$cmd",引号信息丢失,spec 被重新拆成 sgl-eval / @ / git+https://... 三段。这是语法错误,所以镜像 fallback 也无力回天。
-
初次方案与会话回退:作者最初在 scripts/ci/amd/amd_ci_install_dependency.sh 中重写 install_with_retry,改用 argv 数组规避 eval;review 建议保持外科手术式最小修复,作者将 helper 文件逐字节恢复上游,只保留 scripts/ci/utils/sgl_eval_ref.sh 的一行改动(+1/-1)。
-
最终修复:在 sgl_eval_ref.sh 中把 SGL_EVAL_SPEC 从 "sgl-eval @ git+https://...#{ref}" 改为 "sgl-eval@git+https://...#{ref}"。PEP 508 允许无空格 name@url 形式,packaging.requirements.Requirement 对两种写法解析结果完全一致,因此 CUDA/NPU/CPU 行为不变,同时使 spec 对任何不带引号的展开方式都健壮。
-
验证与配套:通过未修改的 eval 路径用 stub 验证 argv 从 6 个(拆词)变为 4 个(完整 spec);在 ROCm 7.2 CI 镜像(rocm/sgl-dev:v0.5.17-rocm720-mi35x-*,MI355X 节点)真实安装成功,import sgl_eval 与 sgl-eval --help 均正常。amd-bot 确认 stage-a-test-1-gpu-small-amd-rocm720 变为成功。无新增测试文件,依托真实 CI leg 验证;环境副作用是 sgl-eval 自身 pin 会把 datasets 5.0.1 -> 4.8.5(既有行为,非本 PR 引入)。
关键文件:
scripts/ci/utils/sgl_eval_ref.sh(模块 CI 脚本;类别 infra;类型 configuration): 唯一改动文件,一行移除 SGL_EVAL_SPEC 中的空格,消除 AMD eval 展开路径下的拆词问题,直接修复 ROCm 7.2 stage-a 门禁。
关键符号:未识别
关键源码片段
scripts/ci/utils/sgl_eval_ref.sh
唯一改动文件,一行移除 SGL_EVAL_SPEC 中的空格,消除 AMD eval 展开路径下的拆词问题,直接修复 ROCm 7.2 stage-a 门禁。
# scripts/ci/utils/sgl_eval_ref.sh 核心片段
# 固定 sgl-eval 依赖的 commit ref,供各平台 CI 安装脚本复用
SGL_EVAL_REF="6690895609dcbc5df1e7b00dd57c9502b868ec4d"
# 关键约束:SGL_EVAL_SPEC 不允许包含空格。
# AMD CI 的 install_with_retry 通过 eval 展开命令行,带空格的
# PEP 508 spec 例如 sgl-eval @ git+https://github.com/sgl-project/sgl-eval.git@...,
# 会被拆成 sgl-eval / @ / git+https://... 三段,pip 收到裸 @ 直接报
# Invalid requirement '@'。
# PEP 508 明确允许 name@url 的无空格形式,
# packaging.requirements.Requirement 对两种写法解析结果完全一致。
SGL_EVAL_SPEC="sgl-eval@git+https://github.com/sgl-project/sgl-eval.git@${SGL_EVAL_REF}"
评论区精华
核心讨论围绕 PR 描述准确性和修复范围展开:
- bingxche 复查后质疑“pip 从未被调用”的断言,kangwangamd 用 stderr stub 复验后承认错误并更正:
> 被当作重定向,pip 实际被调用,但 >=0.25.0 下限被剥离、输出落入垃圾文件 =0.25.0。描述改为“版本约束被静默丢弃且 pip 输出从 CI 日志消失”,并特别说明 --upgrade 安装最新版已满足下限,当前不算功能故障。
- review 要求保持最小修复,作者回退了
install_with_retry 的 argv 重写,只保留一行 spec 改动;同时指出 eval 仍是遗留隐患(未来任何带空格或重定向字符的参数都会被静默破坏),决定另开独立 PR 处理。
-
amd-bot 的 CI 状态确认 stage-a 已转绿,但 ROCm 7.2 整条流水线仍红:stage-b 出现与本次改动无关的 antlr4-python3-runtime 版本冲突(ImportError: Unsupported ANTLR version 4.7.2),需单独修复。
-
httpx 断言勘误:pip 是否被调用 (correctness): PR 描述改为“版本约束被静默丢弃且 pip 输出从 CI 日志消失”,并非 silent no-op;--upgrade 装最新版已满足下限,当前无功能故障。
- 是否重写 install_with_retry 为 argv 数组 (design): 接受最小修复方案;eval 遗留隐患(httpx 下限被吞、参数拆分)留作独立 PR。
- ROCm 7.2 CI 是否全绿 (testing): 本 PR 目标达成,但 ROCm 7.2 流水线仍需单独修复 antlr4 冲突才能全绿;NVIDIA base-b 失败与本 PR 无关。
风险与影响
- 解析一致性:无空格
name@url 形式的 PEP 508 解析等价性已在描述中用 packaging.requirements.Requirement 验证,CUDA/NPU/CPU 路径带引号调用不受影响,回归风险低。
- eval 遗留隐患:
scripts/ci/amd/amd_ci_install_dependency.sh 中的 eval 仍会吞掉 --upgrade 'httpx>=0.25.0' 的下限并重定向 pip 输出;本次修复相当于给 spec 打了补丁,但同一土地雷仍在,未来添加带空格或重定向字符的参数时可能再次触发静默故障。
- 环境副作用:sgl-eval 的依赖 pin 会把 CI 镜像中的
datasets 5.0.1 降级到 4.8.5,可能影响同一镜像上其他端到端评测用例的可复现性(作者标注为既有行为)。
- CI 未全绿:stage-b 的 antlr4 冲突意味着 ROCm 7.2 仍需后续修复才能作为可信门禁,本 PR 只解决了第一层阻塞。
- 影响:对最终用户和推理服务无影响,改动仅在 CI 脚本层。对团队的影响是直接解除 AMD ROCm 7.2 门禁阻塞:stage-a 是所有下游 AMD leg 的前置条件,修复后 AMD PR 的 ROCm 7.2 测试可以继续跑完并暴露后续问题(如 stage-b 的 antlr4 冲突)。对 CI 基础设施维护者而言,本 PR 提供了 eval 拆词问题的完整根因分析和可复现的最小修复范例,并明确划定了后续独立工作的边界(eval 重构、antlr4 修复)。
- 风险标记:CI helper 仍依赖 eval 展开(遗留隐患), 仅覆盖 AMD 路径验证, stage-b 存在无关的 antlr4 阻塞
关联脉络
- PR #34477 (上下文未提供标题): 该 PR 新增 scripts/ci/utils/sgl_eval_ref.sh,其中导出的带空格 PEP 508 spec 正是本 PR 所修复问题的根因来源。
参与讨论