拉取请求检查
当您打开一个拉取请求时,Hugging Face CI 会运行多项检查,这些检查必须通过,您的 PR 才能被合并。
修复 CI
在大多数情况下,make style 足以通过代码质量检查,而代码质量检查是最常见的失败原因。
make style
如果仓库一致性、副本或自动生成的文件出现问题,请运行 make fix-repo。它可以在一次操作中修复代码风格、副本、文档字符串以及自动生成的文件。
make fix-repo
对于较大的更改,以下三条命令序列涵盖了所有检查。虽然开销更大,但能在推送前捕获所有问题。
make fix-repo # auto-fix everything that can be auto-fixed
make typing # check types and model structure, fix any errors manually
make check-repo # verify all checks pass, fix anything that remainsmake typing 会捕获类型错误和模型结构违规,这些需要您手动修复。make check-repo 会执行一次最终的只读检查,以便您确认一切就绪。
CI 偶尔会出现不稳定的情况。如果某个检查因与您的更改无关的原因而失败,请通知维护者重新运行该检查。
代码质量
代码质量检查涵盖格式、导入、类型检查以及模型结构规则。它对应于 make fix-repo 和 make typing。
make style(包含在 make fix-repo 中)会自动修复 Ruff 的 linting 和格式化问题、__init__.py 中的 import 排序,以及 auto-mapping 的一致性。
make typing 使用 ty 执行类型检查,并验证 TRansFormers (TRF) 规则,这些规则涵盖配置类的命名约定以及 forward() 的签名。类型错误和 TRF 违规会报告具体的规则编号,必须手动修复。这些规则位于 mlinter 仓库中。运行 python -m utils.mlinter --list-rules 可以查看所有 TRF 规则,或运行 python -m utils.mlinter --rule TRFXXX 查看特定规则的完整文档。
如果 TRF 规则需要例外,请选择以下选项之一(有关更多详细信息,请参阅抑制违规)。
- 在
utils/mlinter/rules.toml中,将您的模型名称添加到相应规则的allowlist_models列表中。当整个模型文件需要例外处理时,请使用此方法。 - 在标记的构造所在的同一行,或紧邻其上方的行中添加
# trf-ignore: TRFXXX。当仅有一个标记的构造需要例外处理时,请使用此方法。
仓库一致性
仓库一致性检查与 make check-repo 类似,但它在遇到第一个失败时就会停止。它确保仓库在以下类别中保持内部一致:公共对象保持可导入,复制的代码与其源保持同步,自动生成的文件(dummies、doctests、元数据)反映代码的当前状态。对于新模型,它还会验证每个新的模型类是否已注册到自动映射中。
| 类别 | 它验证的内容 | 已自动修复? |
|---|---|---|
| 初始化文件 | src/transformers/models/ 中的 __init__.py 文件已是最新 | make fix-repo |
| 副本与模块化 | # Copied from 块与其源文件匹配,且模块化生成的文件是最新的 | make fix-repo |
| 文档字符串和文档 | 参数文档字符串与函数签名及文档目录一致 | make fix-repo |
| 自动生成的文件 | Dummies、pipeline 类型、doctest 列表、元数据、依赖项表 | make fix-repo |
| 配置验证 | Config 类的 docstring 中包含有效的检查点,且 config 属性与 modeling 文件相匹配 | 手动 |
| 评审人分配 | 每个模型目录以及审核员文件中的每条规则,最终都会分配给一位审核员 | 手动 |
评审人分配
当 Pull Request 被标记为可审查时,Assign PR Reviewers 工作流会请求最多两名审查者,并根据该 Pull Request 在其负责的文件中所修改的行数进行排序。草稿状态的 Pull Request 在退出草稿状态之前不会分配审查者。该工作流本身位于 huggingface/transformers-ci 中,本仓库会调用它;保留在此处的是它所读取的所有权数据。
所有权按文件解析,最具体的优先。
| 在哪里 | 看起来 | 用于 |
|---|---|---|
| 模型文件 | # Reviewers: @login 位于 modular_<model>.py 或 modeling_<model>.py 的开头注释块中 | 一个需要由模态所有者以外的其他人来处理的模型。模块化转换器会将头部信息复制到生成的建模文件中,因此该标签在重新生成后依然会保留 |
| 路径规则 | /src/transformers/<area>/ @login 位于 .github/scripts/codeowners_for_review_action 中 | 任何非模型 |
| 模态表 | @@modality/vision @login,位于同一文件中 | docs/source/en/_toctree.yml 中该部分下的所有模型 |
| 万能 | * @Rocketknight1 @ArthurZucker | 其他任何内容 |
新模型无需在任何地方添加条目:只需将其文档页面添加到 _toctree.yml(文档目录检查已要求这样做),即可将其归入某个模态,而模态表格会自动涵盖该模型。
只能向仓库协作者请求审查。该工作流会在单独的调用中向每位审查者发起请求,并跳过无法请求的人员。因此,如果某条记录指向一位已离开的成员,只会损失一位审查者,而不是全部审查者,并且每次跳过都会作为警告报告到工作流运行中。
Pull request 无法重新路由其自身的审查。.github/scripts/codeowners_for_review_action 是从 base 分支读取的,绝不会从 pull request 的 head 读取,并且 PR CI 安全门会阻止非协作者(collaborator)的 pull request 修改 src/、tests/、docs/ 和 utils/ 之外的任何内容——这就是该文件位于当前位置的原因。# Reviewers: 标签是从 head 读取的,因为新模型会随其一同到达,因此其中列出的每个登录名在请求任何人之前,仍会经过协作者检查。
make check-repository-consistency 会运行 utils/check_reviewers.py。当某个模型仅匹配到兜底规则、某条规则不再匹配任何文件,或模态表与目录不一致时,该脚本会报错。它与分配工作流共用同一个解析器,因此两者不会出现不一致的情况。该解析器并非 transformers 的依赖项,而是列在 utils/checkers-requirements.txt 中,检查器运行器会在环境中首次运行时安装它。如果无法完成安装(例如处于离线状态),检查会报告该情况并直接通过,而不会阻塞流程。
位于 src/transformers/models 之外且没有负责人的路径会以备注形式报告;可通过以下命令列出:
python utils/check_reviewers.py --strict
测试
CI 会根据你的 PR 所修改的内容运行一组有针对性的测试子集。CI 使用 pytest-random-order 以略微随机化的顺序运行测试,以捕获相互耦合的测试。运行开始时会在日志中打印随机种子,因此你可以使用 --random-order-seed=<seed> 来复现相同的测试顺序。
如果测试在本地 GPU 上通过但在 CI 中失败,请设置 TRANSFORMERS_TEST_DEVICE="cpu",以检查是否能在 CPU 上复现该失败。
TRANSFORMERS_TEST_DEVICE="cpu" pytest tests/models/my_model/ -v以下各部分将解释测试选择机制、哪些任务会运行,以及如何应对耗时较长的测试。
测试选择
CI 不会在每个 PR 上运行完整的测试套件。CI 会在每个 PR 上跳过带有 @slow 装饰器的测试,并在 PR 进入审查阶段后由维护者在 GPU 上触发这些测试。
utils/tests_fetcher.py 会追踪您修改的文件中的导入依赖,以识别受影响的测试,并仅运行这些测试。当您修改共享工具时,它还能捕获其他模型中的回归问题。该工具会打印出哪些文件发生了变更以及哪些测试受到影响,然后将列表写入 tests_torch_test_list.txt。
使用 fetcher 来完全复现 CI 运行的内容。
python utils/tests_fetcher.py
python -m pytest -n 8 --dist=loadfile -rA -s $(cat test_preparation/tests_torch_test_list.txt)修改
modeling_utils.py或generation/utils.py等核心文件会触发所有模型测试,而不仅仅是受影响的子集。
您也可以无条件地运行模型的所有测试。直接运行是一种更快的本地健全性检查,但它无法捕获因您修改的共享代码而在其他模型中引发的回归问题。
pytest tests/models/my_model/ -v
测试任务类别
测试被拆分到并行的 CI 作业中,每个作业根据路径模式选取文件。与模型 PR 相关的作业如下:
tests_torch:建模测试(tests/models/*/test_modeling_*.py)tests_tokenization:分词器测试(tests/models/*/test_tokenization_*.py)tests_processors:处理器和特征提取器测试(tests/models/*/test_(processing|image_processing|feature_extractor)_*.py)tests_generate:生成测试pipelines_torch:流水线测试tests_training_ci:训练循环测试tests_tensor_parallel_ci:张量并行测试tests_fsdp_ci:FSDP 测试
慢速测试
常规 CI 运行会跳过带有 @slow 装饰器的测试。这些测试需要下载真实的检查点或消耗大量计算资源,因此会在 GPU 实例上运行,维护者会在你的 PR 进入评审阶段后触发它们。
慢速测试在 NVIDIA A10 上运行,数值结果在 CI 硬件与本地机器之间可能存在轻微差异。维护者在添加新模型时,通常会根据需要调整测试中的这些值。
使用以下命令在本地运行慢速测试。
RUN_SLOW=1 python -m pytest tests/models/my_model/ -v
文档构建
build_pr_documentation 任务会构建并生成文档的预览。机器人会在你的 PR 中发布预览链接,且该检查必须通过才能合并。大多数失败原因是 toctree 中缺少条目。如需在本地构建文档,请参阅 docs 文件夹中的 README.md。
# 从语法复制
对于新模型,请始终优先使用模块化工作流(
modular_*.py),而非# Copied from。请尽量避免使用# Copied from。
# Copied from 机制可确保复制的代码与其源保持同步。当运行 make fix-repo 时,它会检查每个 # Copied from 代码块,并将其更新为与原始代码一致,因此对 # Copied from 代码块内部的任何修改都会被覆盖。请改为编辑源文件,然后让 make fix-repo 自动传播该更改。
# Copied from 的基本形式包括以下几种。
# Copied from transformers.models.bert.modeling_bert.BertSelfOutput
# Copied from transformers.models.bert.modeling_bert.BertAttention with Bert->Roberta
# Copied from transformers.models.bert.modeling_bert.BertForSequenceClassification with Bert->MobileBert all-casingwith model->newModel 语法在复制后应用字符串替换。多个替换项之间用逗号分隔,并按从左到右的顺序依次应用。all-casing 选项会一次性替换所有大小写变体(Bert、bert、BERT 分别变为 MobileBert、mobilebert、MOBILEBERT)。