| name | generate-model-pytest-cases |
| description | 为 imodelzoo 中指定模型生成 `tests/models_tests` 风格的 pytest 测例,包括模型配置 JSON、pytest 入口、marker 注册、`imodelExampleConfig.yaml` 聚合配置。适用于新增模型测例、补齐 get_model/quant/compile/demo/perf/eval/compare 流程。 |
为指定模型生成 pytest 测例
存放规则
SKILL.md 必须放在 .github 目录下,推荐路径为 .github/skills/<skill-name>/SKILL.md。
- 不要把
SKILL.md 放在仓库根目录。
- 如果历史上已经在仓库根目录创建过
SKILL.md,迁移到 .github/skills/ 后应删除旧文件,避免出现多个版本。
- 与技能相关的模板、参考材料和辅助脚本,也优先放在
.github/skills/<skill-name>/ 子目录中统一管理。
目标
为指定模型接入 tests/models_tests 统一测试框架,并保证:
- 模型有独立配置文件
model_cfg_<model>.json。
- 对应 flow 在
test_*.py 中有 pytest 入口。
- 模型名已注册到
model_names.txt。
config/imodelExampleConfig.yaml 中使用 models_tests 风格,而不是直接跑 test.sh。
- 不要修改这些文件:
tests/conftest.py
tests/models_tests/conftest.py
tests/models_tests/test_models_utils.py
tests/models_tests/update_test_py.py
tests/tests_utils/tests_common_utils.py
tests/tests_utils/tests_pyvenv_utils.py
先读这些文件
tests/models_tests/README.md
tests/models_tests/test_models_utils.py
tests/models_tests/update_test_py.py
config/imodelExampleConfig.yaml
- 目标模型目录下的
README.md、get_model.py、ptq.py、build.py、demo.py、perf.py、test.sh
必须修改的文件
按需修改以下文件:
tests/models_tests/model_configs/model_cfg_<model>.json
tests/models_tests/model_names.txt
tests/models_tests/test_get_models.py
tests/models_tests/test_quant_models.py (仅当支持 quant)
tests/models_tests/test_compile_models.py
tests/models_tests/test_demo_models.py
tests/models_tests/test_perf_models.py(仅当支持 perf)
tests/models_tests/test_eval_models.py(仅当支持 eval)
tests/models_tests/test_compare_models.py(仅当支持 compare)
config/imodelExampleConfig.yaml
执行顺序(强制)
- 先阅读目标模型目录,确认实际支持的 flow 和脚本参数。
- 再创建/修改
model_cfg_<model>.json。
- 把模型 marker 写入
model_names.txt。
- 在对应
test_*.py 中补 pytest 函数。
- 若
imodelExampleConfig.yaml 里已有该模型但走的是脚本直跑,改成 models_tests 风格。
- 最后跑
pytest --collect-only 做最小验证。
第一步:识别模型能力
需要从模型目录判断以下信息:
1. 基础信息
- 模型目录:如
models/tts/cosyvoice3
- 模型类型:
cv 或 llm
- 支持 backend:如
xh2
- 支持平台:通常从 README 和脚本中的
HOUMO_TARGET / 平台断言判断
- 设备依赖:如
ndevice=1、dev_mem=12g
2. 支持 flow
结合脚本是否存在来判断:
get_model.py -> get_model
ptq.py -> quant
build.py -> compile
demo.py -> demo
demo_multibatch.py -> 在 support_flow 中额外加入 demo_multibatch,并补 demo_multibatch_params;它作为 demo flow 的附加执行步骤,不新增独立 test_*.py
demo.py 中带 perf 输出,且测试框架可解析 perf 输出日志 -> perf
hmatc compare/eval 配置 -> compare / eval
3. 参数名
重点核对脚本参数是否和框架默认假设一致:
ptq.py 常见参数:--out-dir 或 --output_dir
ptq.py 模型路径参数:--model 或 --model_dir
build.py 常见参数:--model_dir、--output_dir、--context_length
demo.py 常见参数:hmm 路径、embedding 路径、tokenizer 路径
- 若模型 demo 入口不是
demo.py,优先在 demo_params / demo_multibatch_params 中增加 script 字段指定脚本名,而不是为单个模型在共享逻辑里写特判
优先规则:
model_cfg_<model>.json 中的参数名,应优先与模型脚本的真实对外接口保持一致。
- 如果
ptq.py 对外接口是 --output_dir,则 quant_params 中就写 output_dir;不要为了迁就历史习惯,强行把模型脚本改成 --out-dir。
- 只有在现有统一框架无法通过配置表达、且最小兼容修改可以明确降低维护成本时,才考虑改模型脚本或框架。
第二步:编写 model_cfg_<model>.json
1. 命名规则
文件命名必须为:
tests/models_tests/model_configs/model_cfg_<模型名>.json
例如:
tests/models_tests/model_configs/model_cfg_cosyvoice3.json
2. 最小字段集合
{
"obsolete": false,
"model_dir": "models/tts/cosyvoice3",
"model_type": "llm",
"dependencies": {
"ndevice": [1],
"dev_mem": ["12g"]
},
"support_platform": ["x86_64"],
"support_backend": ["xh2"],
"support_core_num": {
"xh2": [2]
},
"support_flow": {
"xh2": ["get_model", "compile", "demo"]
},
"support_hmatc": null,
"get_model_params": {},
"compile_params": {},
"demo_params": {}
}
3. context_length 规则(非常重要)
如果模型的量化/编译依赖固定上下文长度,配置文件中必须显式写出来,并反映到缓存目录名中。
例如:
ptq.py 默认 context_length=2048
- 则目录命名不应写成
hmquant_xh2
- 应显式写成
hmquant_xh2_2k
推荐映射:
2048 -> 2k
8192 -> 8k
16384 -> 16k
32768 -> 32k
补充规则:
get_model_params 中 hmm 下载项的 context_length,必须与 get_model.py 的默认值或该测试项实际传入值一致。
get_model_params.extract_dir 的目录后缀,也必须与该 context_length 一致,例如 8k 应写成 cached_models/hmm_xh2_8k。
compile_params.context_length 应优先与 get_model_params 中对应 hmm 产物的上下文长度保持一致。
compile_params.model_dir 指向的量化输入目录,可以与 compile_params.output_dir 的上下文后缀不同;也就是说,允许“输入 hmquant_xh2_2k,输出 hmm_xh2_8k”。
- 一旦
compile_params.output_dir 的上下文后缀发生变化,demo_params、perf 读取路径中引用的 hmm/embedding 路径也要同步更新,避免仍指向旧目录。
以 cosyvoice3 为例:
"get_model_params": {
"xh2": {
"type": ["raw", "raw", "hmm"],
"download_dir": ["cached_models", "cached_models", "cached_models"],
"extract_dir": [null, null, "cached_models/hmm_xh2_2k"],
"source_type": [null, "modelscope", null],
"context_length": [null, null, "2k"]
}
},
"quant_params": {
"xh2": {
"output_dir": ["cached_results/hmquant_xh2_2k"],
"context_length": ["2048"]
}
},
"compile_params": {
"xh2": {
"model_dir": ["cached_results/hmquant_xh2_2k"],
"context_length": ["2048"],
"output_dir": ["cached_results/hmm_xh2_2k"]
}
}
如果是类似 glm-ocr 这种“下载的预编译 hmm 默认是 8k,但量化输入目录仍是 2k”的场景,可以写成:
"get_model_params": {
"xh2": {
"type": ["raw", "hmm"],
"download_dir": ["cached_models", "cached_models"],
"extract_dir": [null, "cached_models/hmm_xh2_8k"],
"context_length": [null, "8k"]
}
},
"quant_params": {
"xh2": {
"output_dir": ["cached_results/hmquant_xh2_2k"],
"max_sequence_length": ["2048"]
}
},
"compile_params": {
"xh2": {
"model_dir": ["cached_results/hmquant_xh2_2k"],
"context_length": ["8192"],
"output_dir": ["cached_results/hmm_xh2_8k"]
}
},
"demo_params": {
"xh2": {
"embedding_path": ["cached_results/hmm_xh2_8k/hmquant/quant_embedding.pt"],
"prefill_path": ["cached_results/hmm_xh2_8k/<model>_prefill.hmm"],
"decode_path": ["cached_results/hmm_xh2_8k/<model>_decode.hmm"]
}
}
4. LLM 模型的经验规则
model_type 通常写 llm。
quant / compile 很可能依赖 GPU,框架会在 execute_quant_flow() / execute_compile_flow() 中按 llm 分支处理。
compare / eval 不要盲目加,先确认模型确实有这两类脚本或 hmatc 配置。
- 如果模型目录下存在
demo_multibatch.py,默认应在配置里加入 demo_multibatch 与 demo_multibatch_params。若 multibatch 依赖单独的 batch 编译产物,应在 compile_params 中额外增加一组 batch / output_dir,并让 demo_multibatch_params 指向对应目录。
5. perf 配置规则
如果支持 perf:
support_flow 要包含 perf
- 必须加
perf_metrics
- 如果 perf 走
demo.py 输出性能日志,则写:
"perf_params": "demo"
如果 demo 走的不是默认脚本名,可在 demo_params 中补充:
"demo_params": {
"xh2": {
"script": ["demo_asr.py"]
}
}
perf_params: "demo" 时,perf 默认复用 demo_params 中的 script。demo_multibatch.py 也支持通过 demo_multibatch_params 中的 script 覆盖脚本名。
第三步:注册 marker
把模型 marker 追加到:
tests/models_tests/model_names.txt
规则:
例如:
qwen2.5 -> qwen2dot5
deepseek-r1-qwen3-8b -> deepseek_r1_qwen3_8b
cosyvoice3 -> cosyvoice3
第四步:补 pytest 入口
1. get_model
在 tests/models_tests/test_get_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
@pytest.mark.get_model
@pytest.mark.dependency(name="test_tts_cosyvoice3_get_model")
def test_tts_cosyvoice3_get_model(setup_logging) -> None:
"""test_tts_cosyvoice3_get_model"""
model_name = "cosyvoice3"
_get_model_func(model_name, setup_logging)
2. quant
在 tests/models_tests/test_quant_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.quant
@pytest.mark.dependency(
name="test_tts_cosyvoice3_quant",
depends_on=["test_get_models.py::test_tts_cosyvoice3_get_model"],
)
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
def test_tts_cosyvoice3_quant(setup_logging) -> None:
"""test_tts_cosyvoice3_quant"""
model_name = "cosyvoice3"
_quant_func(model_name, setup_logging)
3. compile
在 tests/models_tests/test_compile_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.compile
@pytest.mark.dependency(
name="test_tts_cosyvoice3_compile",
depends_on=["test_quant_models.py::test_tts_cosyvoice3_quant"],
)
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
def test_tts_cosyvoice3_compile(setup_logging) -> None:
"""test_tts_cosyvoice3_compile"""
model_name = "cosyvoice3"
_compile_func(model_name, setup_logging)
4. demo
在 tests/models_tests/test_demo_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
@pytest.mark.demo
def test_tts_cosyvoice3_demo(setup_logging) -> None:
"""test_tts_cosyvoice3_demo"""
model_name = "cosyvoice3"
_demo_func(model_name, setup_logging)
5. perf
如果支持 perf,在 tests/models_tests/test_perf_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
@pytest.mark.perf
def test_tts_cosyvoice3_perf(setup_logging) -> None:
"""test_tts_cosyvoice3_perf"""
model_name = "cosyvoice3"
_perf_func(model_name, setup_logging)
6. eval
如果支持 eval,在 tests/models_tests/test_eval_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
@pytest.mark.eval
def test_tts_cosyvoice3_eval(setup_logging) -> None:
"""test_tts_cosyvoice3_eval"""
model_name = "cosyvoice3"
_eval_func(model_name, setup_logging)
7. compare
如果支持 compare,在 tests/models_tests/test_compare_models.py 中增加目标模型测试用例,参考如下:
@pytest.mark.cosyvoice3
@pytest.mark.ndevice_1
@pytest.mark.dev_mem_12g
@pytest.mark.compare
def test_tts_cosyvoice3_compare(setup_logging) -> None:
"""test_tts_cosyvoice3_compare"""
model_name = "cosyvoice3"
_compare_func(model_name, setup_logging)
第五步:修改 imodelExampleConfig.yaml
如果该模型在 config/imodelExampleConfig.yaml 中原来直接执行 test.sh,应改为与现有 models_tests 一致的风格。
如果该模型不在 config/imodelExampleConfig.yaml 中,应为模型新增测试配置,保持与现有 models_tests 一致的风格。
不推荐
tts_cosyvoice3:
example_case:
- tts_cosyvoice3_test:
script: ../models/tts/cosyvoice3/test.sh
推荐
tts_cosyvoice3:
include:
- models/tts/cosyvoice3
exclude:
- models/tts/cosyvoice3/README.MD
example_case:
- tts_cosyvoice3_test:
test_type: models_tests
script: cosyvoice3
args: all
test:
- tts_cosyvoice3_test
最低交付物
新增一个模型 pytest 测例时,最低要交付:
model_cfg_<model>.json
model_names.txt 中的 marker
- 至少
get_model / compile / demo 的 pytest 入口
- 如果模型支持,则补
quant / perf / eval / compare
config/imodelExampleConfig.yaml 中对应 models_tests 风格配置
- 一次
pytest --collect-only 验证结果
推荐验证命令
1. 收集指定模型用例
pytest tests/models_tests/test_get_models.py \
tests/models_tests/test_quant_models.py \
tests/models_tests/test_compile_models.py \
tests/models_tests/test_demo_models.py \
-k <model_name> --collect-only -q
例如:
pytest tests/models_tests/test_get_models.py \
tests/models_tests/test_quant_models.py \
tests/models_tests/test_compile_models.py \
tests/models_tests/test_demo_models.py \
-k cosyvoice3 --collect-only -q
生成新模型测例时的检查清单
不要这样做
- 不要只写
model_cfg_<model>.json,却不补 test_*.py。
- 不要忘记更新
model_names.txt。
- 不要在
imodelExampleConfig.yaml 里继续用 test.sh 替代 models_tests,除非该模型明确不接入统一框架。
- 不要把
hmquant_xh2、hmm_xh2 这种不含上下文长度的信息用于有固定 context 的 LLM 模型。
- 不要因为历史经验里常见
--out-dir,就把实际只支持 --output_dir 的模型脚本强行改接口。
- 不要只改
compile_params.output_dir 的上下文后缀,却忘了同步 demo_params / perf 对应路径。
- 不要修改
apis/common/ 或 tools/common/ 下的 vendored 内容。
cosyvoice3 经验总结
本次接入 cosyvoice3 时,实际落地经验如下:
- 该模型应走
models_tests 统一框架,而不是在 imodelExampleConfig.yaml 中直接跑 test.sh。
ptq.py 默认 context_length=2048,因此量化/编译/下载的目录需要统一命名为 *_2k。
ptq.py 使用的是 model_dir / output_dir 参数名,不是典型的 model / out-dir,框架侧需要兼容。
demo.py 的 perf 日志字段与通用 LLM 略有差异,必要时需要补 perf 解析兼容。
- 对 TTS/多组件模型,
demo_params 往往比普通 LLM 更长,必须逐个核对 hmm 和 embedding 路径。
glm-ocr 经验补充
本次接入 glm-ocr 时,额外确认了以下规则:
get_model.py 的 --context_length 默认值是 8k,因此 get_model_params 中的 hmm 下载项必须写成 8k,并对应 cached_models/hmm_xh2_8k。
ptq.py 的真实对外接口是 --output_dir,因此 quant_params 应写 output_dir,不应为了适配历史习惯强制改脚本为 --out-dir。
compile_params.context_length 最好与 get_model_params 中目标 hmm 的上下文保持一致;对 glm-ocr,应使用 8192。
compile_params.model_dir 可以继续指向 hmquant_xh2_2k,而 compile_params.output_dir 使用 hmm_xh2_8k,这是允许的。
- 当
compile_params.output_dir 改为 hmm_xh2_8k 后,demo_params 中的 embedding_path、vit_path、prefill_path、decode_path 也必须同步改到 hmm_xh2_8k。