Transformers 多语言模型推理指南:XLM 语言嵌入、M2M100 与 MBart 多语翻译实战
本文基于 Transformers 仓库官方的多语言模型文档(docs/source/ar/multilingual.md),系统讲解在 Transformers 中如何正确调用 XLM、BERT、XLM-RoBERTa、M2M100、MBart 五类多语言模型进行推理:哪些模型可以直接按单语模型方式使用,哪些模型必须显式传入语言嵌入或源语言参数,并结合仓库源码剖析 langs 张量、lang2id、forced_bos_token_id 等关键机制的底层实现,帮助你在跨语言 NLP 任务中避开"忘记指定语言"这一类隐蔽的推理错误。
多语言模型:哪些可以直接用,哪些需要特殊处理
Transformers 中包含大量多语言模型,但它们的推理用法并不统一。文档明确指出:并不是所有多语言模型的用法都不同。部分模型(如 google-bert/bert-base-multilingual-uncased)的调用方式与单语模型完全一致;而另一些模型(如需要语言嵌入的 XLM、需要指定源语言的多语翻译模型)则必须遵循额外的调用约定。本指南聚焦后者。
按调用方式,可以把多语言模型分为三类:
- 无需任何语言信息的模型:BERT 多语版本、XLM-RoBERTa、不要求语言嵌入的 XLM MLM 大模型;
- 需要显式传入语言嵌入(language embeddings)的模型:多数 XLM 因果/掩码语言模型;
- 需要指定源语言、并在生成时强制目标语言 BOS 的翻译模型:M2M100、MBart。
XLM 系列模型总览
XLM 共有十种预训练副本,其中仅一种是单语模型。其余九种可划分为两大类:
- 使用语言嵌入的副本:推理时必须传入与输入形状相同的
langs张量; - 不使用语言嵌入的副本:
FacebookAI/xlm-mlm-17-1280(17 语言 MLM)与FacebookAI/xlm-mlm-100-1280(100 语言 MLM),用于通用的句子表示,不需要语言信息。
XLM 使用语言嵌入的模型列表
以下 XLM 副本在推理时要求显式提供语言嵌入:
| 模型 | 任务类型 | 语言范围 |
|---|---|---|
FacebookAI/xlm-mlm-ende-1024 |
掩码语言建模 | 英-德 |
FacebookAI/xlm-mlm-enfr-1024 |
掩码语言建模 | 英-法 |
FacebookAI/xlm-mlm-enro-1024 |
掩码语言建模 | 英-罗马尼亚 |
FacebookAI/xlm-mlm-xnli15-1024 |
掩码语言建模 | XNLI 语言集合 |
FacebookAI/xlm-mlm-tlm-xnli15-1024 |
掩码语言建模 + 翻译 | XNLI 语言集合 |
FacebookAI/xlm-clm-enfr-1024 |
因果语言建模 | 英-法 |
FacebookAI/xlm-clm-ende-1024 |
因果语言建模 | 英-德 |
语言嵌入的底层实现:langs 张量与 lang_embeddings
语言嵌入被表示为一个与 input_ids 形状完全相同的张量,其取值由语言决定,并通过分词器的 lang2id 与 id2lang 两个映射字典确定。这两个属性在 XLMTokenizer 实现 中作为可选构造参数传入,并在加载预训练词表时自动设置;若传入的 lang 参数不在 lang2id 映射中,分词器会直接抛出错误,提示检查语言是否受支持(参见 tokenization_xlm.py)。
模型侧的实现可以在 modeling_xlm.py 中确认:当配置满足 n_langs > 1 and use_lang_emb 时,XLMModel 会创建 self.lang_embeddings = nn.Embedding(self.n_langs, self.dim)。在前向传播中(modeling_xlm.py):
langs张量的形状必须断言为(batch_size, sequence_length),否则触发assert失败;- 若启用了增量缓存(
past_key_values),只取langs的最后_slen列; - 最终执行
tensor = tensor + self.lang_embeddings(langs),即将语言嵌入逐元素加到词嵌入上——这就是为什么langs中每个位置都填充同一语言 ID 也能生效,因为语言信息是叠加在每个 token 嵌入上的。
完整示例:加载 xlm-clm-enfr-1024 并传入语言嵌入
以因果语言建模副本 FacebookAI/xlm-clm-enfr-1024(英-法)为例:
>>> import torch
>>> from transformers import XLMTokenizer, XLMWithLMHeadModel
>>> tokenizer = XLMTokenizer.from_pretrained("FacebookAI/xlm-clm-enfr-1024")
>>> model = XLMWithLMHeadModel.from_pretrained("FacebookAI/xlm-clm-enfr-1024")
通过 lang2id 查看该模型支持的语言及其编号:
>>> print(tokenizer.lang2id)
{'en': 0, 'fr': 1}
创建输入序列(batch size 为 1):
>>> input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")]) # batch size of 1
将语言 ID 取为 "en" 对应的编号(0),构造与 input_ids 同形状、全部填充该值的 langs 张量:
>>> language_id = tokenizer.lang2id["en"] # 0
>>> langs = torch.tensor([language_id] * input_ids.shape[1]) # torch.tensor([0, 0, 0, ..., 0])
>>> # 重塑为 (batch_size, sequence_length)
>>> langs = langs.view(1, -1) # 形状变为 [1, sequence_length](batch size 为 1)
将 input_ids 与语言嵌入一起传入模型:
>>> outputs = model(input_ids, langs=langs)
要点回顾:langs 的形状必须严格等于 input_ids 的形状,这是源码中 assert langs.size() == (bs, slen) 强制保证的;对于 batch 推理,每个样本对应一行,各自填充该样本语言对应的 lang2id 值即可。
此外,仓库中的文本生成示例脚本 run_generation.py 支持在生成时指定 XLM 语言:其 argparse 定义 提供了 --xlm_language 参数(Optional language when used with the XLM model.),并在交互模式下提示用户从 tokenizer 可用语言列表中选择(run_generation.py)。运行前需先安装该目录的依赖 examples/pytorch/text-generation/requirements.txt。
不使用语言嵌入的 XLM 模型
FacebookAI/xlm-mlm-17-1280(掩码语言建模,17 语言)FacebookAI/xlm-mlm-100-1280(掩码语言建模,100 语言)
这两个副本用于通用的句子表示(sentence representation),与前面需要显式语言嵌入的 XLM 副本不同,它们在推理时不需要 langs 参数。
BERT 多语模型:从上下文推断语言
以下 BERT 模型可用于多语言任务:
google-bert/bert-base-multilingual-uncased(掩码语言建模 + 下一句预测,102 种语言)google-bert/bert-base-multilingual-cased(掩码语言建模 + 下一句预测,104 种语言)
这两类模型在推理时不要求语言嵌入:语言必须由上下文决定,模型自行推断。也就是说,你可以完全按标准 BERT 的方式调用它们,只需确保输入文本在词表覆盖范围内(如阿拉伯语、中文等非拉丁文字,建议先确认所用副本的 tokenizer 词表支持情况)。
XLM-RoBERTa:面向 100 种语言的双向编码模型
以下 XLM-RoBERTa 模型可用于多语言任务:
FacebookAI/xlm-roberta-base(掩码语言建模,100 种语言)FacebookAI/xlm-roberta-large(掩码语言建模,100 种语言)
XLM-RoBERTa 基于 2.5 TB 的 CommonCrawl 新数据、经优化后的 100 种语料训练,在分类、序列标注、问答等下游任务上,相较 mBERT、XLM 等早期多语言模型有明显收益。由于它是掩码语言建模架构且无需语言嵌入,加载后与标准 BERT 式调用一致(AutoTokenizer / AutoModel 或直接使用对应类),无需传递任何语言参数。
M2M100:100 语言互译与 src_lang 的正确设定
以下 M2M100 模型可用于多语翻译:
facebook/m2m100_418M(翻译)facebook/m2m100_1.2B(翻译)
源码机制:源语言标记如何加入输入
要正确翻译,关键是理解 M2M100 分词器的内部约定。在 tokenization_m2m_100.py 中,set_src_lang_special_tokens 方法会将编码后的输入重写为 X [eos, src_lang_code] 的结构(即无 prefix,suffix 为 [eos, 源语言码])——这正是 文档注释 所述 input_ids(编码器)的形状约定。src_lang 属性带有 setter(tokenization_m2m_100.py),任何对 tokenizer.src_lang = "zh" 的赋值都会触发特殊 token 的重置。默认源语言为 "en"(tokenization_m2m_100.py)。
目标语言则通过 forced_bos_token_id 在生成阶段强制:M2M100 要求第一个生成 token 即目标语言的语言码 token。仓库中翻译 pipeline 的输入构建逻辑 _build_translation_inputs 会自动执行 inputs["forced_bos_token_id"] = tgt_lang_id,并且要求 src_lang 与 tgt_lang 均不为空,否则抛出 ValueError——这为手动调用 model.generate 时的参数约定提供了权威参照。
完整示例:中译英
以 facebook/m2m100_418M 为例,将中文文本翻译为英文。源语言通过在加载分词器时用 src_lang 指定:
>>> from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer
>>> en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger."
>>> chinese_text = "不要插手巫師的事務, 因為他們是微妙的, 很快就會發怒."
>>> tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100_418M", src_lang="zh")
>>> model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M")
将文本切分为 token:
>>> encoded_zh = tokenizer(chinese_text, return_tensors="pt")
在 generate 中用 forced_bos_token_id 强制目标语言为英文,tokenizer.get_lang_id("en") 负责把语言码解析为 token ID(实现见 tokenization_m2m_100.py):
>>> generated_tokens = model.generate(**encoded_zh, forced_bos_token_id=tokenizer.get_lang_id("en"))
>>> tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
'Do not interfere with the matters of the witches, because they are delicate and will soon be angry.'
注意 skip_special_tokens=True 会跳过开头的目标语言码 token 与结尾特殊 token,输出为干净的译文。
MBart:50 语言翻译与 lang_code_to_id
以下 MBart 模型可用于多语翻译:
facebook/mbart-large-50-one-to-many-mmt(多语机器翻译,一对一多,50 语言)facebook/mbart-large-50-many-to-many-mmt(多语机器翻译,多对多,50 语言)facebook/mbart-large-50-many-to-one-mmt(多语机器翻译,多对一,50 语言)facebook/mbart-large-50(多语翻译,50 语言)facebook/mbart-large-cc25
源码机制:fairseq 语言码表与语言码后缀
MBart 分词器在初始化时基于 FAIRSEQ_LANGUAGE_CODES 构建语言码到 token ID 的映射(tokenization_mbart.py):
self.lang_code_to_id = {
lang_code: self.convert_tokens_to_ids(lang_code) for lang_code in FAIRSEQ_LANGUAGE_CODES
}
这与 M2M100 的 get_lang_id 作用相同,但语言码命名不同:MBart 使用 fairseq 风格带区域后缀的代码(如 "fi_FI"、"en_XX"),而 M2M100 使用 ISO 简码(如 "fi"、"en")。同样地,src_lang setter 会在赋值时重置源语言特殊 token(tokenization_mbart.py),默认源语言为 "en_XX"(tokenization_mbart.py);其 _build_translation_inputs 也会像 M2M100 一样把 forced_bos_token_id 设为目标语言 ID,作为 generate 调用约定的实现依据。
完整示例:芬兰语译英文
以 facebook/mbart-large-50-many-to-many-mmt 为例,将芬兰语文本翻译为英文。源语言 src_lang="fi_FI" 在加载分词器时指定(注意使用 Auto 类亦可,因为 MBart 已注册自动映射):
>>> from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
>>> en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger."
>>> fi_text = "Älä sekaannu velhojen asioihin, sillä ne ovat hienovaraisia ja nopeasti vihaisia."
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/mbart-large-50-many-to-many-mmt", src_lang="fi_FI")
>>> model = AutoModelForSeq2SeqLM.from_pretrained("facebook/mbart-large-50-many-to-many-mmt")
将文本切分为 token:
>>> encoded_en = tokenizer(en_text, return_tensors="pt")
在 generate 中把 forced_bos_token_id 设为 "en_XX" 对应的 ID,强制输出为英文(注意这里使用的是 lang_code_to_id 字典而非 get_lang_id 方法,因为 MBart 分词器暴露的是前者):
>>> generated_tokens = model.generate(**encoded_en, forced_bos_token_id=tokenizer.lang_code_to_id["en_XX"])
>>> tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
"Don't interfere with the wizard's affairs, because they are subtle, will soon get angry."
特殊副本的例外:如果使用 facebook/mbart-large-50-many-to-one-mmt(多对一),则不需要强制目标语言 ID 作为首生成 token——该副本被训练为统一输出单一目标语言;除此之外用法完全相同。
三类模型的调用约定速查
| 模型 | 需要语言信息 | 传入方式 | 关键源码 |
|---|---|---|---|
| BERT multilingual / XLM-RoBERTa | 否 | 无需参数,语言从上下文推断 | — |
| XLM(MLM/CLM 双语副本) | 是 | model(input_ids, langs=langs),langs 形状同 input_ids,取值来自 tokenizer.lang2id |
modeling_xlm.py |
XLM xlm-mlm-17/100-1280 |
否 | 常规 MLM 调用 | — |
| M2M100 | 是 | 分词器 src_lang(ISO 简码)+ generate(forced_bos_token_id=tokenizer.get_lang_id(...)) |
tokenization_m2m_100.py |
| MBart(非 many-to-one) | 是 | 分词器 src_lang(fairseq 码如 fi_FI)+ generate(forced_bos_token_id=tokenizer.lang_code_to_id["en_XX"]) |
tokenization_mbart.py |
MBart many-to-one-mmt |
部分 | 只需 src_lang,无需 forced_bos_token_id |
— |
常见陷阱与注意事项
langs形状错误:XLM 前向中assert langs.size() == (bs, slen)会因形状不匹配直接失败。单条输入务必langs.view(1, -1),batch 推理时每行填充对应样本的语言 ID。- 语言码格式混淆:M2M100 用
"en"、"zh"这类 ISO 简码;MBart 用"en_XX"、"fi_FI"这类 fairseq 风格码。跨模型迁移示例代码时,语言码不能照抄。 - 忘记
forced_bos_token_id:M2M100 与多数 MBart 副本若不在generate时强制目标语言首 token,模型可能输出错误的目标语言(或不确定输出);many-to-one-mmt副本除外。 - 默认源语言:M2M100 与 MBart 分词器在未显式指定
src_lang时默认"en"/"en_XX",翻译非英语源语言时必须显式设置。 - 词表覆盖:使用 BERT 多语副本处理阿拉伯语、中文等文字时,先确认对应 tokenizer 的词表支持情况,避免大量
<unk>影响表示质量。
总结
Transformers 中的多语言模型并非"一套调用走天下":BERT 多语与 XLM-RoBERTa 可以按常规方式直接推理;XLM 双语副本要求把语言 ID 编码成与 input_ids 同形状的 langs 张量并加到词嵌入上;M2M100 与 MBart 则需要在分词器层指定 src_lang、在 generate 层用 forced_bos_token_id 锁定目标语言。理解 modeling_xlm.py、tokenization_m2m_100.py 与 tokenization_mbart.py 中的这些实现细节后,你可以准确地把任意 XLM/M2M100/MBart 预训练权重接入自己的多语言推理或翻译流程。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00