Transformers 文档
Pull Request 检查
并获得增强的文档体验
开始
Pull Request 检查
当你在 🤗 Transformers 上打开一个 pull request 时,会运行相当多的检查,以确保你添加的补丁不会破坏任何已有的东西。这些检查分为四种类型
- 常规测试
- 文档构建
- 代码和文档风格
- 一般仓库一致性
在本文档中,我们将尝试解释这些不同的检查是什么以及它们背后的原因,以及如果其中一个检查在你的 PR 上失败时如何在本地调试它们。
请注意,理想情况下,它们需要你进行开发安装
pip install transformers[dev]
或者用于可编辑安装
pip install -e .[dev]
在 Transformers 仓库中。由于 Transformers 的可选依赖项数量已大幅增长,你可能无法全部安装它们。如果开发安装失败,请确保安装你正在使用的深度学习框架(PyTorch、TensorFlow 和/或 Flax),然后执行
pip install transformers[quality]
或者用于可编辑安装
pip install -e .[quality]
测试
所有以 ci/circleci: run_tests_
开头的任务都运行 Transformers 测试套件的一部分。这些任务中的每一个都专注于库的某个部分在特定环境中的测试:例如 ci/circleci: run_tests_pipelines_tf
在仅安装 TensorFlow 的环境中运行 pipelines 测试。
请注意,为了避免在被测模块没有实际更改时运行测试,每次只运行测试套件的一部分:运行一个实用程序来确定 PR 前后库中的差异(GitHub 在“文件更改”选项卡中显示的内容),并选择受该差异影响的测试。该实用程序可以使用以下命令在本地运行
python utils/tests_fetcher.py
从 Transformers 仓库的根目录。它将
- 检查 diff 中的每个文件,看更改是在代码中还是仅在注释或文档字符串中。仅保留具有实际代码更改的文件。
- 构建一个内部映射,该映射为库源代码的每个文件提供它递归影响的所有文件。如果模块 B 导入模块 A,则称模块 A 影响模块 B。对于递归影响,我们需要一个从模块 A 到模块 B 的模块链,其中每个模块都导入前一个模块。
- 将此映射应用于步骤 1 中收集的文件,这将为我们提供受 PR 影响的模型文件列表。
- 将这些文件中的每一个映射到其对应的测试文件,并获取要运行的测试列表。
当在本地执行脚本时,你应该获得步骤 1、3 和 4 的结果打印输出,从而知道运行了哪些测试。该脚本还将创建一个名为 test_list.txt
的文件,其中包含要运行的测试列表,你可以使用以下命令在本地运行它们
python -m pytest -n 8 --dist=loadfile -rA -s $(cat test_list.txt)
为了防止任何疏漏,完整的测试套件也会每天运行。
文档构建
build_pr_documentation
任务构建并生成文档预览,以确保你的 PR 合并后一切看起来正常。一个机器人将在你的 PR 中添加一个链接以预览文档。你对 PR 所做的任何更改都会在预览中自动更新。如果文档构建失败,请单击失败任务旁边的“Details”以查看哪里出错了。通常,错误就像 toctree 中缺少文件一样简单。
如果你有兴趣在本地构建或预览文档,请查看 docs 文件夹中的 README.md
。
代码和文档风格
代码格式化应用于所有源文件、示例和测试,使用 black
和 ruff
。我们还有一个自定义工具,用于处理文档字符串和 rst
文件的格式化 (utils/style_doc.py
),以及在 Transformers __init__.py
文件中执行的延迟导入的顺序 (utils/custom_init_isort.py
)。所有这些都可以通过执行以下命令启动
make style
CI 检查这些是否已在 ci/circleci: check_code_quality
检查中应用。它还运行 ruff
,它将基本查看你的代码,如果发现未定义的变量或未使用的变量,则会发出警告。要在本地运行该检查,请使用
make quality
这可能需要很长时间,因此要在当前分支中仅对你修改的文件运行相同的操作,请运行
make fixup
最后一个命令还将运行所有用于仓库一致性的附加检查。让我们看看它们。
仓库一致性
这重新组合了所有测试,以确保你的 PR 使仓库保持良好状态,并由 ci/circleci: check_repository_consistency
检查执行。你可以通过执行以下命令在本地运行该检查
make repo-consistency
这检查了
- 添加到 init 的所有对象都已文档化(由
utils/check_repo.py
执行) - 所有
__init__.py
文件在其两个部分中都具有相同的内容(由utils/check_inits.py
执行) - 所有标识为从另一个模块复制的代码都与原始代码一致(由
utils/check_copies.py
执行) - 所有配置类在其文档字符串中都至少提到了一个有效的检查点(由
utils/check_config_docstrings.py
执行) - 所有配置类仅包含在相应的建模文件中使用的属性(由
utils/check_config_attributes.py
执行) - README 的翻译和文档索引与主 README 具有相同的模型列表(由
utils/check_copies.py
执行) - 文档中的自动生成表格是最新的(由
utils/check_table.py
执行) - 即使未安装所有可选依赖项,库也拥有所有可用对象(由
utils/check_dummies.py
执行) - 所有文档字符串都正确记录了对象签名中的参数(由
utils/check_docstrings.py
执行)
如果此检查失败,前两项需要手动修复,后四项可以通过运行以下命令为你自动修复
make fix-copies
附加检查涉及添加新模型的 PR,主要是
- 添加的所有模型都在 Auto-mapping 中(由
utils/check_repo.py
执行) - 所有模型都经过适当的测试(由
utils/check_repo.py
执行)
检查副本
由于 Transformers 库在模型代码方面非常有主见,并且每个模型都应完全在一个文件中实现,而不依赖于其他模型,因此我们添加了一种机制,用于检查给定模型层的代码副本是否与原始代码保持一致。这样,当出现 bug 修复时,我们可以看到所有其他受影响的模型,并选择向下传递修改或中断副本。
如果文件是另一个文件的完整副本,则应将其注册在 utils/check_copies.py
的常量 FULL_COPIES
中。
此机制依赖于 # Copied from xxx
形式的注释。xxx
应包含正在复制的类或函数的完整路径。例如,RobertaSelfOutput
是 BertSelfOutput
类的直接副本,因此你可以在此处看到它有一个注释
# Copied from transformers.models.bert.modeling_bert.BertSelfOutput
请注意,你可以将其应用于从其复制的相关方法,而不是将其应用于整个类。例如,在这里你可以看到 RobertaPreTrainedModel._init_weights
如何从 BertPreTrainedModel
中的相同方法复制而来,并带有注释
# Copied from transformers.models.bert.modeling_bert.BertPreTrainedModel._init_weights
有时,副本除了名称外完全相同:例如在 RobertaAttention
中,我们使用 RobertaSelfAttention
而不是 BertSelfAttention
,但除此之外,代码完全相同。这就是为什么 # Copied from
支持使用以下语法进行简单的字符串替换:Copied from xxx with foo->bar
。这意味着代码被复制,所有 foo
实例都被 bar
替换。你可以在 RobertaAttention
中看到它是如何使用的,并带有注释
# Copied from transformers.models.bert.modeling_bert.BertAttention with Bert->Roberta
请注意,箭头周围不应有任何空格(除非该空格是要替换的模式的一部分)。
你可以添加多个以逗号分隔的模式。例如,CamemberForMaskedLM
是 RobertaForMaskedLM
的直接副本,其中有两个替换:Roberta
替换为 Camembert
,ROBERTA
替换为 CAMEMBERT
。你可以在此处看到这是如何完成的,并带有注释
# Copied from transformers.models.roberta.modeling_roberta.RobertaForMaskedLM with Roberta->Camembert, ROBERTA->CAMEMBERT
如果顺序很重要(因为其中一个替换可能与之前的替换冲突),则替换从左到右执行。
如果替换更改了格式(例如,如果你用一个很长的名称替换一个短名称),则在应用自动格式化程序后检查副本。
当模式只是同一替换的不同大小写(带有大写和小写变体)时,另一种方法是添加选项 all-casing
。这是 MobileBertForSequenceClassification
中的一个示例,带有注释
# Copied from transformers.models.bert.modeling_bert.BertForSequenceClassification with Bert->MobileBert all-casing
在这种情况下,代码是从 BertForSequenceClassification
复制而来,通过替换
Bert
替换为MobileBert
(例如,在 init 中使用MobileBertModel
时)bert
替换为mobilebert
(例如,在定义self.mobilebert
时)BERT
替换为MOBILEBERT
(在常量MOBILEBERT_INPUTS_DOCSTRING
中)