首页
/ BARTpho 越南语预训练序列到序列模型:架构原理、分词器设计与 Transformers 实战指南

BARTpho 越南语预训练序列到序列模型:架构原理、分词器设计与 Transformers 实战指南

2026-09-09 15:00:21作者:柏廷章Berta

BARTpho 是首个面向越南语的大规模单语预训练序列到序列(sequence-to-sequence)模型,基于 BART 的 large 架构与去噪预训练方案构建,特别适合文本摘要、掩码填充等生成式 NLP 任务。本文以本仓库的 BARTpho 官方文档为主体,结合 tokenization_bartpho.py 源码与 test_tokenization_bartpho.py 测试用例,带你完整掌握 BARTpho 的加载、推理、掩码填充与双词汇表分词器原理。

模型概述:BARTpho_word 与 BARTpho_syllable

BARTpho 由 Nguyen Luong Tran、Duong Minh Le 与 Dat Quoc Nguyen 在论文 BARTpho: Pre-trained Sequence-to-Sequence Models for Vietnam(2021)中提出,模型贡献者与原始代码作者为 dqnguyen。BARTpho 提供两个公开版本:

  • BARTpho_word:基于词(word)粒度切分的版本;
  • BARTpho_syllable:基于音节(syllable)粒度切分的版本。

两者都是越南语上首个公开的大规模单语预训练序列到序列模型,沿用 BART 的 large 架构与去噪预训练方案,因此在生成类任务上具有天然优势。原论文实验表明,在越南语文本摘要下游任务上,无论自动评估还是人工评估,BARTpho 均优于强基线 mBART,并刷新了当时的最先进水平(SOTA)。需要说明的是,上述对比结论源自论文原文表述,仓库内并不包含相应基准测试代码。

在本仓库中,BARTpho 在 models/bartpho/ 目录下以 tokenizer 模块形式实现(models/bartpho/init.py 仅导出 BartphoTokenizer),并在 models/auto/tokenization_auto.py 中注册了 ("bartpho", "BartphoTokenizer") 映射,因此可通过 AutoTokenizer 直接加载。

快速上手:加载模型与提取特征

BARTpho 可以直接通过 AutoModel / AutoTokenizer 加载官方预训练权重(如 vinai/bartpho-syllable),与 Transformers 生态无缝集成。以下示例完整继承自官方文档,并补充了必要的导入说明:

import torch
from transformers import AutoModel, AutoTokenizer

# 加载模型与分词器(首次运行会自动从 Hub 下载权重)
bartpho = AutoModel.from_pretrained("vinai/bartpho-syllable")
tokenizer = AutoTokenizer.from_pretrained("vinai/bartpho-syllable")

# 一段越南语示例文本
line = "Chúng tôi là những nghiên cứu viên."

# 分词并构造模型输入(返回 PyTorch 张量)
input_ids = tokenizer(line, return_tensors="pt")

with torch.no_grad():
    # 注意:模型的输出现在是元组(tuple)形式
    features = bartpho(**input_ids)

若你使用 TensorFlow 2.0+,可通过 TFAutoModel 获得等价体验:

from transformers import TFAutoModel

bartpho = TFAutoModel.from_pretrained("vinai/bartpho-syllable")
input_ids = tokenizer(line, return_tensors="tf")
features = bartpho(**input_ids)

从源码看,BartphoTokenizermodel_input_names["input_ids", "attention_mask"](见 tokenization_bartpho.py),即分词器只产出 input_idsattention_mask 两类输入,不产出 token type ids——因为 BARTpho 不使用 segment 区分(对应源码中 create_token_type_ids_from_sequences 恒返回全零列表)。

使用技巧:以 mBART 类替代 BART 类完成掩码填充

BARTpho 沿用了 mBART 的实践:使用 BART 的 large 架构,并在编码器与解码器之上各额外叠加一层 Layer Normalization。因此,直接使用 BART 专属类会与权重结构不匹配,应遵循官方文档的建议——将 BART 专属类替换为对应的 mBART 专属类。例如用 MBartForConditionalGeneration 替代 BartForConditionalGeneration

下面是官方文档给出的掩码填充(masked language modeling)完整示例,演示如何预测 <mask> 位置的候选词:

from transformers import MBartForConditionalGeneration

bartpho = MBartForConditionalGeneration.from_pretrained("vinai/bartpho-syllable")
tokenizer = AutoTokenizer.from_pretrained("vinai/bartpho-syllable")

TXT = "Chúng tôi là <mask> nghiên cứu viên."
input_ids = tokenizer([TXT], return_tensors="pt")["input_ids"]

# 前向传播得到 logits
logits = bartpho(input_ids).logits

# 定位 <mask> 对应的索引
masked_index = (input_ids[0] == tokenizer.mask_token_id).nonzero().item()

# 取出该位置的分布并取 top-5 候选
probs = logits[0, masked_index].softmax(dim=0)
values, predictions = probs.topk(5)

print(tokenizer.decode(predictions).split())

需要说明的是:MBartForConditionalGeneration 类定义于本仓库的 models/mbart/ 模块中,它承载了 BARTpho 实际使用的模型权重结构。该提示的核心逻辑是——BARTpho 的"大架构 + 额外层归一化"与 mBART 一脉相承,因此凡是需要实例化模型的地方,都应优先使用 mBART 系类(如 MBartForConditionalGenerationMBartModel)。

文本摘要实战示例

官方英文文档还提供了一个基于 AutoTokenizer + BartForConditionalGeneration 的越南语文本摘要示例(模型使用 vinai/bartpho-word)。这里结合文档说明,完整给出可复现的摘要流程:

from transformers import AutoTokenizer, BartForConditionalGeneration

tokenizer = AutoTokenizer.from_pretrained("vinai/bartpho-word")
model = BartForConditionalGeneration.from_pretrained("vinai/bartpho-word", device_map="auto")

text = """
Quang tổng hợp hay gọi tắt là quang hợp là quá trình thu nhận và chuyển hóa năng lượng ánh sáng Mặt trời của thực vật,
tảo và một số vi khuẩn để tạo ra hợp chất hữu cơ phục vụ bản thân cũng như làm nguồn thức ăn cho hầu hết các sinh vật
trên Trái Đất. Quang hợp trong thực vật thường liên quan đến chất tố diệp lục màu xanh lá cây và tạo ra oxy như một sản phẩm phụ
"""
inputs = tokenizer(text, return_tensors="pt").to(model.device)

# beam search 解码生成摘要
outputs = model.generate(inputs["input_ids"], num_beams=2, min_length=0, max_length=20)
tokenizer.batch_decode(outputs, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]

其中 device_map="auto" 用于自动分配设备(多卡/CPU 场景),num_beams=2 表示束搜索宽度,max_length=20 限制摘要长度。从源码结构看,生成所需的 generate 方法继承自 PreTrainedModel 的通用生成接口,其参数体系(beam search、长度惩罚等)与仓库其他条件生成模型完全一致,详见 generation/ 目录。

分词器原理:双词汇表设计

BARTpho 的分词是理解其设计的关键。官方文档明确指出:该实现仅通过 monolingual_vocab_file 处理分词,其结构如下(见 tokenization_bartpho.py):

VOCAB_FILES_NAMES = {"vocab_file": "sentencepiece.bpe.model", "monolingual_vocab_file": "dict.txt"}

即 BARTpho 需要两个词汇文件:

文件 默认文件名 作用
vocab_file sentencepiece.bpe.model 预训练 SentencePiece 模型,来自多语言 XLM-RoBERTa(mBART 同样使用),包含约 25 万(250K)种 token 类型,负责子词切分
monolingual_vocab_file dict.txt 单语词汇表,从上述 250K 多语言词汇中抽取的越南语专属 token 子集,负责 token 到 ID 的映射

这种双词汇表设计带来一个重要能力:如果其他语言也希望复用该 SentencePiece 子词切分机制,只需将 monolingual_vocab_file 替换为针对目标语言定制的单语词汇表,即可继续复用 BartphoTokenizer。文档中明确记载了这一扩展用法,这也是本分词器最具移植性的特性。

BartphoTokenizer 参数详解

BartphoTokenizer 继承自 XLMRobertaTokenizer 的适配实现,底层基于 SentencePiece,同时继承自 tokenization_utils_sentencepiece.py 中的 SentencePieceBackend(其本身继承 PreTrainedTokenizer)。其构造参数如下(依据 tokenization_bartpho.py 与类 docstring):

参数 默认值 说明
vocab_file 必填 预训练 SentencePiece 模型路径,即多语言 XLM-RoBERTa / mBART 使用的 250K 词汇表
monolingual_vocab_file 必填 单语词汇表路径,为越南语从 250K 词汇中抽取出的专用子集
bos_token "<s>" 序列开始 token;构建带特殊 token 的序列时实际使用 cls_token
eos_token "</s>" 序列结束 token;构建带特殊 token 的序列时实际使用 sep_token
sep_token "</s>" 分隔 token,用于拼接多段序列(如问答的 question/context)
cls_token "<s>" 分类 token,用于序列分类场景,是带特殊 token 序列的首个 token
unk_token "<unk>" 未知 token,词汇表外的 token 会被映射为该 token 的 ID
pad_token "<pad>" 填充 token,用于 batch 内不同长度序列对齐
mask_token "<mask>" 掩码 token,用于掩码语言建模;构造时会被包装为 AddedToken(mask_token, lstrip=True, rstrip=False),即掩码前保留空格、按普通词处理
sp_model_kwargs None 透传给 SentencePieceProcessor.__init__() 的关键字参数

其中 sp_model_kwargs 支持三类核心用法(来自类 docstring):

  • enable_sampling:启用子词正则化(subword regularization);
  • nbest_size:unigram 采样参数(对 BPE-Dropout 无效)。nbest_size = {0, 1} 不采样;> 1 从 nbest 结果中采样;< 0 视为无限,使用 forward-filtering-and-backward-sampling 从全假设格(lattice)中采样;
  • alpha:unigram 采样的平滑参数,对 BPE-dropout 而言是合并操作的丢弃概率。

源码级实现:fairseq 词汇表与特殊 token 对齐

阅读 tokenization_bartpho.py 的初始化逻辑,可以发现其内部维护了一套独立的 fairseq 风格词汇表,与 SentencePiece 原生词表并存:

  1. 构建 fairseq 词表(第 127-140 行):先将 bos/pad/eos/unk/sep/cls 六个特殊 token 依次编号(0 起始),再逐行读取 monolingual_vocab_file(每行取第一个字段作为 token)追加编号,最后补上 mask_token,生成 fairseq_tokens_to_ids 与其反向映射 fairseq_ids_to_tokens
  2. 重写 ID 转换(第 253-271 行):_convert_token_to_id 优先查 fairseq 词表,未命中返回 unk_token_id_convert_id_to_token 直接查 fairseq 反向映射;vocab_sizeget_vocab 均以 fairseq 词表为准。
  3. 对齐 added tokens(第 273-289 行,_align_added_tokens_with_fairseq_vocab):父类 SentencePieceBackend 会用 SentencePiece 的 ID 填充 _added_tokens_*,该方法将其重新映射到缩减后的 fairseq 词典 ID 上,确保所有 token 在任何转换路径下 ID 一致,避免"两个词汇表"导致的不一致问题。
  4. 特殊 token 序列格式(第 160-184 行):单序列格式为 <s> X </s>,序列对格式为 <s> A </s></s> B </s>get_special_tokens_maskcreate_token_type_ids_from_sequences 与之严格对应。
  5. 词汇保存(第 291-320 行):save_vocabulary 会同时输出 sentencepiece.bpe.modeldict.txt 两个文件;当 SentencePiece 模型无法以文件形式访问时,会通过 sp_model.serialized_model_proto() 序列化写出。

此外,该类带有 @requires(backends=("sentencepiece",)) 装饰器(第 31 行),SentencePieceBackend.__init__ 中也会执行 requires_backends(self, "sentencepiece"),因此使用前需确保环境已安装 sentencepiece 依赖。

测试验证:分词行为的一致性保障

仓库在 test_tokenization_bartpho.py 中提供了针对该分词器的完整测试,可作为你验证环境的参考:

  • from_pretrained_id = "vinai/bartpho-syllable":以官方 syllable 权重作为 from_pretrained 的集成验证目标;
  • test_rust_tokenizer = False:BARTpho 仅有慢速(slow)分词器,无 Rust 快速版本;
  • test_sentencepiece = True:启用 SentencePiece 相关通用测试;
  • test_full_tokenizer:用测试夹具(fixture)验证 "This is a là test" 被切分为 ▁This ▁is ▁a ▁l à ▁t est,且 ID 序列与预期完全一致(第 60-78 行);
  • get_input_output_texts 验证越南语字符 不在单语词汇表时会回退为 <unk><unk>,印证了 _convert_token_to_id 的未命中回退逻辑。

测试中使用的 SentencePiece 夹具位于 tests/fixtures/test_sentencepiece_bpe.model,测试会动态构造临时 dict.txt 单语词汇文件(见 get_tokenizer 方法),完整覆盖了双词汇表加载路径。

小结

BARTpho 通过"BART large 架构 + 额外层归一化 + mBART 类适配 + 双词汇表 SentencePiece 分词器"的组合,为越南语生成式 NLP 提供了开箱即用的预训练方案。上手时只需记住三条核心准则:模型加载用 AutoModel/AutoTokenizer(或 TensorFlow 的 TFAutoModel)指向 vinai/bartpho-{word,syllable} 检查点;模型实例化用 mBART 系类替代 BART 系类;如需迁移到其他语言,替换 monolingual_vocab_file 即可复用分词器。结合本仓库 tokenization_bartpho.pytest_tokenization_bartpho.py 的源码与测试,你可以在越南语摘要、掩码填充等任务上快速落地,并深入理解其与 XLM-RoBERTa/mBART 词汇体系的渊源。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525