Transformers 文档

拉取请求的检查

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

拉取请求检查

当你在 🤗 Transformers 上打开一个拉取请求时,会运行大量的检查,以确保你添加的补丁不会破坏任何现有功能。这些检查分为四种类型:

  • 常规测试
  • 文档构建
  • 代码和文档风格
  • 通用仓库一致性

本文档将尝试解释这些各种检查是什么以及它们背后的原因,以及如果其中一个检查在你的 PR 上失败,如何在本地调试它们。

请注意,理想情况下,它们要求你在 Transformers 仓库中进行开发安装

pip install transformers[dev]

或可编辑安装

pip install -e .[dev]

由于 Transformers 的可选依赖项数量已大幅增加,你可能无法全部获取。如果开发安装失败,请务必安装你正在使用的深度学习框架(PyTorch、TensorFlow 和/或 Flax),然后执行:

pip install transformers[quality]

或可编辑安装

pip install -e .[quality]

测试

所有以 `ci/circleci: run_tests_` 开头的作业都运行 Transformers 测试套件的一部分。每个作业都在特定环境中专注于库的一部分:例如,`ci/circleci: run_tests_pipelines_tf` 在仅安装 TensorFlow 的环境中运行管道测试。

请注意,为了避免在模块没有实际更改时运行测试,每次只运行测试套件的一部分:会运行一个实用程序来确定 PR 前后库中的差异(GitHub 在“文件更改”选项卡中显示的内容),并选择受该差异影响的测试。该实用程序可以在本地从 Transformers 仓库的根目录运行,使用

python utils/tests_fetcher.py

该实用程序将

  1. 检查差异中的每个文件,判断更改是在代码中还是仅在注释或文档字符串中。只保留有实际代码更改的文件。
  2. 构建一个内部映射,为库源代码的每个文件提供其递归影响的所有文件。如果模块 B 导入模块 A,则称模块 A 影响模块 B。对于递归影响,我们需要一个从模块 A 到模块 B 的模块链,其中每个模块都导入前一个模块。
  3. 将此映射应用于步骤 1 中收集的文件,从而获得受 PR 影响的模型文件列表。
  4. 将每个文件映射到其对应的测试文件,并获取要运行的测试列表。

在本地执行脚本时,您应该会看到步骤 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,主要包括:

  • 所有添加的模型都在自动映射中(由 `utils/check_repo.py` 执行)
  • 所有模型都经过了适当的测试(由 `utils/check_repo.py` 执行)

检查副本

由于 Transformers 库在模型代码方面非常注重,每个模型都应该完全在一个文件中实现,而不依赖于其他模型,因此我们添加了一种机制,可以检查给定模型的层代码副本是否与原始代码保持一致。这样,当出现 bug 修复时,我们可以查看所有其他受影响的模型,并选择是向下传递修改还是中断副本。

如果一个文件是另一个文件的完整副本,您应该将其注册到 `utils/check_copies.py` 的常量 `FULL_COPIES` 中。

此机制依赖于 `注释` 形式的注释。`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` 中)
< > 在 GitHub 上更新