执行摘要
- 一句话:简化扩散测试用例组织结构,合并列表并重命名文件
- 推荐动作:该PR属于常规维护重构,不涉及功能变更。建议阅读
gpu_cases.py和diffusion_case_parser.py的变更,了解测试组织方式的新约定。"1-gpu-b200"测试套件的文件引用已更新,注意保持同步。
功能与动机
简化扩散CI的测试用例组织方式,减少碎片化列表,使开发者更容易添加和查找测试用例。
实现拆解
- 合并测试用例列表(
python/sglang/multimodal_gen/test/server/gpu_cases.py):将ONE_GPU_CASES_A、ONE_GPU_CASES_B、ONE_GPU_CASES_C合并为ONE_GPU_CASES,并在文件末尾使用+=将ModelOpt用例追加到ONE_GPU_CASES中;同理,将TWO_GPU_CASES_A和TWO_GPU_CASES_B合并为TWO_GPU_CASES,并移除原有的拼接语句。
- 重命名ModelOpt列表(
gpu_cases.py):将ONE_GPU_CASES_C改为ONE_GPU_MODELOPT_CASES,更清晰地表明它包含ModelOpt(量化)测试用例。
- 重命名测试文件(
test_server_c.py → test_server_b200.py):将B200专用的测试文件更名,并更新其导入语句使用新的列表名ONE_GPU_MODELOPT_CASES。
- 更新配套配置(
testcase_configs.py、run_suite.py):修改文档注释中的列表引用,以及run_suite.py中FILE_SUITES的条目,将test_server_c.py替换为test_server_b200.py。
- 增强用例解析器(
scripts/ci/utils/diffusion/diffusion_case_parser.py):新增visit_AugAssign方法以处理+=赋值,新增_extract_case_ids方法支持变量引用和二进制加法操作,并在_extract_case_ids_from_list中处理ast.Starred解包,最后添加去重逻辑以保持列表顺序。
关键文件:
python/sglang/multimodal_gen/test/server/gpu_cases.py(模块 测试用例;类别 test;类型 test-coverage): 核心变更文件,合并了所有扩散测试用例列表并重命名了ModelOpt列表
scripts/ci/utils/diffusion/diffusion_case_parser.py(模块 CI脚本;类别 infra;类型 infrastructure;符号 visit_AugAssign, _extract_case_ids_from_list, _process_aug_assignment, _extract_case_ids): 增强解析器以支持+=赋值和变量引用,确保新结构能被正确解析
python/sglang/multimodal_gen/test/server/test_server_b200.py(模块 测试脚本;类别 test;类型 rename-or-move): 文件重命名并更新导入,与gpu_cases.py的新列表名对齐
python/sglang/multimodal_gen/test/server/testcase_configs.py(模块 测试配置;类别 test;类型 test-coverage): 更新文档注释中的列表名称引用
python/sglang/multimodal_gen/test/run_suite.py(模块 运行脚本;类别 test;类型 test-coverage): 更新文件引用以匹配重命名后的测试文件
关键符号:visit_AugAssign, _process_aug_assignment, _extract_case_ids, _extract_case_ids_from_list
关键源码片段
python/sglang/multimodal_gen/test/server/gpu_cases.py
核心变更文件,合并了所有扩散测试用例列表并重命名了ModelOpt列表
# python/sglang/multimodal_gen/test/server/gpu_cases.py
# 合并前:ONE_GPU_CASES_A, ONE_GPU_CASES_B, ONE_GPU_CASES_C 三个独立列表
# 合并后:统一为 ONE_GPU_CASES,并在末尾追加 ModelOpt 用例
ONE_GPU_CASES: list[DiffusionTestCase] = [
# === Text to Image (T2I) ===
DiffusionTestCase("qwen_image_t2i", ...),
DiffusionTestCase("qwen_image_t2i_cache_dit_enabled", ...),
# ... 原有 A 和 B 的所有用例 ...
DiffusionTestCase("flux_2_image_t2i_upscaling_4x", ...),
# === Text to Video (T2V) ===(原来在 B 中)
DiffusionTestCase("wan2_1_t2v_1.3b", ...),
# ...
]
# 平台条件追加(原来分别追加到 A/B)
if not current_platform.is_hip():
ONE_GPU_CASES.append(DiffusionTestCase("hunyuan3d_shape_gen", ...))
ONE_GPU_CASES.append(DiffusionTestCase("turbo_wan2_1_t2v_1.3b", ...))
if current_platform.is_hip():
ONE_GPU_MODELOPT_CASES = []
else:
ONE_GPU_MODELOPT_CASES = [
_make_modelopt_ci_case("flux1_modelopt_fp8_t2i", ...),
# ...
]
# 使用 += 合并(简化前是通过 [*A, *B, *C] 拼接)
ONE_GPU_CASES += ONE_GPU_MODELOPT_CASES
# 2-GPU 同理合并
TWO_GPU_CASES = [
DiffusionTestCase("wan2_2_i2v_a14b_2gpu", ...),
# ... 原来 A 和 B 的所有用例 ...
DiffusionTestCase("flux_2_ti2i_multi_image_cache_dit", ...),
]
TWO_GPU_CASES = _with_default_num_gpus(TWO_GPU_CASES, 2)
scripts/ci/utils/diffusion/diffusion_case_parser.py
增强解析器以支持+=赋值和变量引用,确保新结构能被正确解析
# scripts/ci/utils/diffusion/diffusion_case_parser.py
class CaseCollector(ast.NodeVisitor):
# ...
def visit_AugAssign(self, node: ast.AugAssign):
"""处理 += 这类赋值,用于合并列表"""
self._process_aug_assignment(node.target, node.op, node.value)
self.generic_visit(node)
def _process_aug_assignment(self, target, op, value):
"""执行 += 的语义:将右侧case ID追加到左侧列表"""
if not isinstance(target, ast.Name) or not isinstance(op, ast.Add):
return
rhs_case_ids = self._extract_case_ids(value)
if rhs_case_ids is None:
return
lhs_case_ids = self.cases.get(target.id, [])
# 合并并保留顺序
self.cases[target.id] = [*lhs_case_ids, *rhs_case_ids]
def _extract_case_ids(self, node):
"""通用提取:支持列表字面量、变量引用、列表加法"""
if isinstance(node, ast.List):
return self._extract_case_ids_from_list(node)
if isinstance(node, ast.Name):
return list(self.cases.get(node.id, [])) # 引用之前解析过的变量
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
left_ids = self._extract_case_ids(node.left)
right_ids = self._extract_case_ids(node.right)
if left_ids is None or right_ids is None:
return None
return [*left_ids, *right_ids]
return None
def _extract_case_ids_from_list(self, node: ast.List):
"""从列表字面量中提取case ID"""
case_ids = []
for elt in node.elts:
if isinstance(elt, ast.Starred):
# 处理 *list 展开
starred = self._extract_case_ids(elt.value)
if starred:
case_ids.extend(starred)
continue
case_id = self._extract_case_id_from_call(elt)
if case_id:
case_ids.append(case_id)
return case_ids
# 后续还添加了去重逻辑:保留首次出现顺序
评论区精华
只收到一个来自gemini-code-assist[bot]的评论,建议将ONE_GPU_CASES += ONE_GPU_MODELOPT_CASES改为显式列表连接ONE_GPU_CASES = ONE_GPU_CASES + ONE_GPU_MODELOPT_CASES,以避免就地修改可能带来的副作用。该建议未被采纳,PR已合入当前实现。
- 使用+= vs 显式列表连接 (design): PR合入时未采纳建议,保留了+=写法。
风险与影响
关联脉络
参与讨论