为指定模型生成 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.pytests/models_tests/conftest.pytests/models_tests/test_models_utils.pytests/models_tests/update_test_py.pytests/tests_utils/tests_common_utils.pytests/tests_utils/tests_pyvenv_utils.py
先读这些文件
tests/models_tests/README.mdtests/models_tests/test_models_utils.pytests/models_tests/update_test_py.pyconfig/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>.jsontests/models_tests/model_names.txttests/models_tests/test_get_models.pytests/models_tests/test_quant_models.py(仅当支持 quant)tests/models_tests/test_compile_models.pytests/models_tests/test_demo_models.pytests/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_modelptq.py->quantbuild.py->compiledemo.py->demodemo_multibatch.py-> 在support_flow中额外加入demo_multibatch,并补demo_multibatch_params;它作为demoflow 的附加执行步骤,不新增独立test_*.pydemo.py中带 perf 输出,且测试框架可解析 perf 输出日志 ->perfhmatccompare/eval 配置 ->compare/eval
3. 参数名
重点核对脚本参数是否和框架默认假设一致:
ptq.py常见参数:--out-dir或--output_dirptq.py模型路径参数:--model或--model_dirbuild.py常见参数:--model_dir、--output_dir、--context_lengthdemo.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->2k8192->8k16384->16k32768->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
规则:
-->_.->dot
例如:
qwen2.5->qwen2dot5deepseek-r1-qwen3-8b->deepseek_r1_qwen3_8bcosyvoice3->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>.jsonmodel_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
生成新模型测例时的检查清单
- 已阅读目标模型目录中的脚本和 README
- 已确定模型类型是
cv还是llm - 已确认实际支持哪些 flow
-
quant_params/compile_params的参数名与脚本真实接口一致(如output_dirvsout-dir) -
context_length已显式写入配置 -
get_model_params的hmm默认context_length与get_model.py默认值一致 - 缓存目录名已反映
2k/8k/16k等信息 -
compile_params.context_length与目标 hmm 上下文一致 -
demo_params/perf读取路径已跟随compile_params.output_dir同步 -
model_names.txt已追加 marker - 对应
test_*.py已补 pytest 入口 -
imodelExampleConfig.yaml已改为models_tests风格 - 如有必要,
test_models_utils.py已做最小兼容改动 -
pytest --collect-only已通过
不要这样做
- 不要只写
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。
Source: houmo-ai/houmo-examples — distributed by TomeVault.