☰
使用 Cookiecutter 为 Hugging Face Transformers 新增 Tokenization 测试模板(FlexGen 仓库内置 transformers 开发工具链)
2026/9/26 6:36:04 网站建设 项目流程
  • 推理引擎
  • 大模型

【免费下载链接】FlexGen

Running large language models on a single GPU for throughput-oriented scenarios.

项目地址:https://gitcode.com/gh_mirrors/fl/FlexGen
点击查看免费下载

导读

本指南以仓库benchmark/third_party/transformers/templates/adding_a_missing_tokenization_test/目录下的官方模板为绝对核心,系统讲解如何通过 Cookiecutter 为一个尚缺分词测试的新模型一键生成test_tokenization_Xxx.py测试骨架。你将掌握模板的交互式变量配置(模型命名、慢/快分词器组合、SentencePiece 依赖)、生成后测试文件的结构与关键实现点,以及如何把生成文件安置到对应模型的测试子目录并接入TokenizerTesterMixin公共测试体系,最终用pytest驱动验证。文中全部证据来自仓库内模板、cookiecutter.json配置与tests/test_tokenization_common.py、tests/models/bert/test_tokenization_bert.py等源码。

一、模板是什么:为“缺失的分词测试”补课

在 Hugging Face Transformers 中,每个模型(BERT、RoBERTa、DeBERTa 等)在tests/models/<model>/下都应有一份test_tokenization_*.py,用来回归验证该模型分词器的行为。当社区提交一个新模型或发现某模型缺少分词测试时,最规范的做法不是手写重复的样板代码,而是使用本目录提供的 Cookiecutter 模板生成标准骨架。

仓库中该模板由三个部分组成(相对仓库根目录):

  • 模板说明文档:即本指南依据的主文档,交代 fork、clone、安装与调用方式;
  • cookiecutter.json:定义模板的全部交互变量及默认值;
  • Jinja 模板源文件:用{{cookiecutter.xxx}}占位符生成最终测试文件。

从源码结构看,这是 transformers 官方templates/目录被完整随仓库收录的开发者工具,属于“给库本身做贡献”的流程组件,与 FlexGen 的推理基准脚本无直接耦合,可以独立使用。

二、环境准备:fork、clone 与 dev 依赖安装

模板说明文档给出的第一步是准备开发环境。注意:本仓库为只读镜像,以下命令面向你在 GitHub 上的 fork 副本执行,不修改当前仓库:

git clone https://github.com/YOUR-USERNAME/transformers cd transformers pip install -e ".[dev]"

要点说明:

  • pip install -e ".[dev]"以可编辑模式安装 transformers 及其全部开发依赖。cookiecutter 属于 dev 依赖之一,因此文档强调“使用 cookiecutter 需要先装齐所有 dev 依赖”;
  • 若你的环境是 Conda,官方文档一般建议先创建独立环境再执行上述安装,避免污染系统 Python;
  • 安装完成后可用cookiecutter --version验证工具可用。

三、生成模板:一条命令 + 一轮问答

安装就绪后,在 transformers 仓库根目录下运行:

cookiecutter path-to-the folder/adding_a_missing_tokenization_test/

即指向本目录的路径(在本仓库中为benchmark/third_party/transformers/templates/adding_a_missing_tokenization_test/)。运行后:

  1. Cookiecutter 会在当前工作目录新建一个以{{cookiecutter.modelname}}命名的文件夹(例如BrandNewBERT/);
  2. 依次弹出变量问答(见下一节变量表);
  3. 模板引擎把 Jinja 占位符替换成你回答的值,最终在新建文件夹内生成唯一一个文件:test_tokenization_{{cookiecutter.lowercase_modelname}}.py。

文档特别提醒:模板生成位置是当前工作目录下的新文件夹,生成完成后需要手动把它移动到tests/models/<对应模型名>/子目录。

四、交互变量详解:一份 cookiecutter.json 的完整拆解

模板变量配置 定义了 8 个变量,下面逐个给出含义、默认值与影响:

变量默认值可选值作用与注意事项
modelnameBrandNewBERT任意字符串模型显示名,按纯文本大小写书写,如BERT、RoBERTa、DeBERTa。文档明确要求按模型原文大小写填写,它同时决定新建文件夹名
uppercase_modelnameBRAND_NEW_BERT任意全大写蛇形名,用于在注释、常量等场景引用模型
lowercase_modelnamebrand_new_bert任意全小写蛇形名,直接决定生成文件名test_tokenization_brand_new_bert.py
camelcase_modelnameBrandNewBert任意驼峰名,用于生成测试类名BrandNewBertTokenizationTest及导入BrandNewBertTokenizer/BrandNewBertTokenizerFast
has_slow_classTrueTrue/False模型是否提供 Python 慢分词器。为True时测试类绑定tokenizer_class并开启test_slow_tokenizer
has_fast_classTrueTrue/False模型是否提供基于 🤗 Tokenizers 的快分词器。为True时绑定rust_tokenizer_class并开启test_rust_tokenizer
slow_tokenizer_use_sentencepieceTrueTrue/False慢分词器是否基于 SentencePiece。为True时测试类追加test_sentencepiece = True,并自动加上@require_sentencepiece装饰器
authorsThe HuggingFace Team任意写入生成文件版权头的作者名

变量之间的组合关系(由 Jinja 模板源文件 的{% if %}逻辑决定):

  • 导入语句:仅慢类时导入XxxTokenizer;仅快类时导入XxxTokenizerFast;两者都有时同时导入;
  • 装饰器:慢类用 SentencePiece → 加@require_sentencepiece;含快类 → 加@require_tokenizers;两者都有且用 SentencePiece → 两个装饰器都加;都不用 → 无装饰器。

这两个装饰器定义在 transformers/testing_utils.py:require_sentencepiece在 SentencePiece 未安装时跳过测试,require_tokenizers在 🤗 Tokenizers 未安装时跳过测试。也就是说,生成文件的“可运行性”由你的环境决定——只有安装对应依赖才能跑这些用例。

五、生成的测试文件长什么样

以默认值(BrandNewBERT、双类、用 SentencePiece)生成后,文件核心结构如下:

""" Testing suite for the BrandNewBERT tokenizer. """ import unittest from transformers import BrandNewBertTokenizer, BrandNewBertTokenizerFast from transformers.testing_utils import require_sentencepiece, require_tokenizers from ...test_tokenization_common import TokenizerTesterMixin @require_sentencepiece @require_tokenizers class BrandNewBertTokenizationTest(TokenizerTesterMixin, unittest.TestCase): tokenizer_class = BrandNewBertTokenizer test_slow_tokenizer = True rust_tokenizer_class = BrandNewBertTokenizerFast test_rust_tokenizer = True test_sentencepiece = True # TODO: Check in `TokenizerTesterMixin` if other attributes need to be changed def setUp(self): super().setUp() raise NotImplementedError( "Here you have to implement the saving of a toy tokenizer in " "`self.tmpdirname`." ) # TODO: add tests with hard-coded target values

5.1 类级属性:声明被测对象

  • tokenizer_class/rust_tokenizer_class:指定被测的慢、快分词器类,供 mixin 的get_tokenizer()/get_rust_tokenizer()加载(见 公共测试基类);
  • test_slow_tokenizer/test_rust_tokenizer:开关对应慢/快分词器的公共用例;
  • test_sentencepiece:开关 SentencePiece 专属用例;
  • setUp中的self.tmpdirname由 mixin 的setUp创建(tempfile.mkdtemp(),见 test_tokenization_common.py),测试结束由tearDown清理。

5.2 模板留白:两个 TODO 是“必答题”

模板刻意留下两处raise NotImplementedError/ TODO,这是新增测试的核心工作量所在:

  1. setUp必须被重写:你要在self.tmpdirname中保存一个“玩具分词器”(toy tokenizer),例如写一份 vocab 文件。参考 BERT 的真实实现——test_tokenization_bert.py 在setUp里构造了含[UNK]、[CLS]、[SEP]、[PAD]、[MASK]及若干子词(want、##want、##ed、wa、un、runn、##ing等)的词表并写入self.vocab_file,还实现了get_input_output_texts返回一对文本/期望输出;
  2. 补充硬编码目标值的用例:模板的# TODO: add tests with hard-coded target values提示你仿照test_full_tokenizer(见 test_tokenization_bert.py)写出确定性的 token→id 断言,而不是只依赖 mixin 的通用检查。

5.3 mixin 带来的“免费”测试集

TokenizerTesterMixin是约 4000 行的公共测试基类(tests/test_tokenization_common.py),子类仅需配置少量属性即可自动继承大量用例,主要包括:

  • 基础行为:test_tokenize_special_tokens(L338)、test_sentencepiece_tokenize_and_convert_tokens_to_string(L365)、test_rust_and_python_full_tokenizers(L494)验证 Python/Rust 分词结果一致性;
  • 编解码:test_save_and_load_tokenizer(L610)、test_pickle_tokenizer(L700)、test_internal_consistency(L868)、test_conversion_reversible(L1915);
  • 特殊 token:test_add_tokens_tokenizer(L795)、test_add_special_tokens(L846)、test_special_tokens_mask(L1415);
  • 长度/填充/截断:test_maximum_encoding_length_single_input(L993)、test_right_and_left_padding(L1535)、test_padding_to_max_length(L1655);
  • 批处理与模型输入:test_batch_encode_plus_tensors(L2244)、test_torch_encode_plus_sent_to_model(L2339)、test_offsets_mapping(L2883);
  • 对齐与保存:test_tokenization_python_rust_equals(L2768)、test_save_pretrained(L3390)。

另有从tests/fixtures/sample_text.txt读取样本文本驱动慢/快一致性检查的逻辑(L171-L172)。

六、把生成文件归位并运行测试

生成完成后按文档说明执行归位与验证:

# 1. 将新生成的文件夹移动到对应模型的测试子目录 # 例如 tests/models/brand_new_bert/test_tokenization_brand_new_bert.py # 2. 运行该测试文件 pytest tests/models/brand_new_bert/test_tokenization_brand_new_bert.py

若在仓库内查看现成范例,可对照 tests/models/bert/test_tokenization_bert.py(BERT)、tests/models/albert/test_tokenization_albert.py(ALBERT)等十余个模型的分词测试,它们都是从同一 mixin 体系派生并各自补齐setUp与硬编码断言的成熟样例。注意在仓库中运行此类测试前,需确认已安装sentencepiece(@require_sentencepiece依赖)与tokenizers(@require_tokenizers依赖),否则相关用例会被unittest.skipUnless跳过而不是失败(装饰器语义见 testing_utils.py)。

七、最佳实践清单

  1. 命名三件套保持一致:modelname(原样大小写)、camelcase_modelname(类名/导入名)、lowercase_modelname(文件名)三者必须对应同一模型,避免类名与文件名错位;
  2. 如实申报类与依赖:has_slow_class/has_fast_class/slow_tokenizer_use_sentencepiece必须与模型实际实现一致,否则生成的 import 或装饰器会让测试误跳过或误失败;
  3. 必改setUp:不实现玩具分词器的保存,get_tokenizer()/get_rust_tokenizer()会因from_pretrained(self.tmpdirname)找不到文件而失败(加载逻辑见 test_tokenization_common.py);
  4. 补硬编码断言:mixin 只保证通用契约,模型特有的分词边界(如 BERT 的##子词切分)必须靠自定义测试固定下来;
  5. 提交前跑通全套:先单跑生成文件,再跑tests/test_tokenization_common.py中与test_slow_tokenizer/test_rust_tokenizer开关相关的公共用例,确保与既有模型测试风格一致。

八、关联文件索引

  • 模板说明:README.md
  • 变量配置:cookiecutter.json
  • 生成骨架:test_tokenization_{{cookiecutter.lowercase_modelname}}.py
  • 公共测试基类:tests/test_tokenization_common.py
  • 成熟范例:tests/models/bert/test_tokenization_bert.py
  • 依赖装饰器:src/transformers/testing_utils.py
  • 推理引擎
  • 大模型

【免费下载链接】FlexGen

Running large language models on a single GPU for throughput-oriented scenarios.

项目地址:https://gitcode.com/gh_mirrors/fl/FlexGen
点击查看免费下载

相关推荐

上一篇:Lightweight Charts终极代码分割策略:基于Rollup的chunk优化完全指南
下一篇:cann/asc-devkit矩阵计算空间API

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询