![[LLaMA3] 'add_bos_token=True, add_eos_token=True' seems not taking effect](https://www.chat-gpts.plus/wp-content/uploads/2026/07/30947-cde5267c.jpg)
[LLaMA3] ‘add_bos_token=True, add_eos_token=True’ seems not taking effect
快速结论:在 Transformers 4.41.0 中,LLaMA 3 使用 PreTrainedTokenizerFast,其 add_bos_token/add_eos_token 参数在初始化或赋值后均无效。该问题已在 Transformers v5(当前 main 分支)中修复。临时方案是通过手动设置 TemplateProcessing 后处理器来生效。
问题场景
用户使用 Transformers 加载 LLaMA 3(如 llama3-8b)的 AutoTokenizer,在 from_pretrained 中或通过 tokenizer.add_bos_token = True / tokenizer.add_eos_token = True 尝试控制 BOS/EOS token 的添加,但 tokenizer 的编码结果始终包含 BOS token(token id 128000)且不包含 EOS token(token id 128001),与参数设置无关。
报错原文
# 用户脚本输出示例
# 无论 add_bos_token/add_eos_token 如何设置,编码结果始终为:
[128000, 6151, 11, 1268, 527, 499, 3432, 30]
# 期望当 add_bos_token=True, add_eos_token=True 时应包含 128001;当两者为 False 时应无 128000
原因分析
LLaMA 3 的 tokenizer 是 PreTrainedTokenizerFast(而非 LLamaTokenizer 或 LlamaTokenizerFast),它的 add_bos_token/add_eos_token 属性实际上并未连接到底层的快速 tokenizer 后处理器(post_processor)。该控制需要在 tokenizers 库的 TemplateProcessing 层实现,而当时 Transformers 4.41.0 未支持从 Python 侧动态更新。相关讨论参见 #30607。
环境排查
- Transformers 版本:需确认是否为 4.41.0 或更早版本(v5 之前的所有版本均受影响)。
- PyTorch 版本:用户报告使用 PyTorch 2.3.0,但问题与 PyTorch 版本无关。
- tokenizers 库版本:建议保持较新版本(至少 0.19.0 以上),但后处理器的设置逻辑在 tokenizers 侧始终可用。
解决步骤
- 方案一:升级到 Transformers v5(推荐)
该问题已在 Transformers 当前 main 分支上修复。v5 的 tokenizer 重构中,PreTrainedTokenizerFast已原生支持add_bos_token/add_eos_token参数,可直接生效。运行以下代码验证:
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B", add_bos_token=True, add_eos_token=True) - 方案二:手动设置后处理器(适用于 v4.x 版本,可优先尝试)
通过直接在底层 tokenizer 对象上设置TemplateProcessing来强制添加 BOS/EOS token:from transformers import AutoTokenizer from tokenizers import processors model_id = "/path/to/llama3-8b" tokenizer = AutoTokenizer.from_pretrained(model_id) bos = "<|begin_of_text|>" eos = "<|end_of_text|>" tokenizer._tokenizer.post_processor = processors.Sequence( [ processors.ByteLevel(trim_offsets=False), processors.TemplateProcessing( single=f"{bos}:0 $A:0 {eos}:0", pair=f"{bos}:0 $A:0 {bos}:1 $B:1 {eos}:1", special_tokens=[ (bos, tokenizer.bos_token_id), (eos, tokenizer.eos_token_id), ], ), ] ) # 现在 tokenizer 会在编码时自动添加 BOS 和 EOS inputs = tokenizer(['hi, how are you today?'], padding=True, return_tensors='pt') print(inputs) # 输出应包含 128001 - 方案三:使用社区修补函数(备选)
如果需要在运行时动态控制add_bos_token/add_eos_token,可参考 kddubey 提供的补丁函数,它会修改 tokenizer 的内部行为以响应属性赋值。
验证方法
运行用户原始测试脚本,对比以下输出的第一个和最后一个 token:
tokenizer = AutoTokenizer.from_pretrained(LLaMAPath, add_bos_token=True, add_eos_token=True)
inputs = tokenizer(['hi, how are you today?'], padding=True, return_tensors='pt')
print(inputs) # 应输出 [128000, ..., 30, 128001]
tokenizer2 = AutoTokenizer.from_pretrained(LLaMAPath, add_bos_token=False, add_eos_token=False)
inputs2 = tokenizer2(['hi, how are you today?'], padding=False, return_tensors='pt')
print(inputs2) # 应输出 [6151, ..., 30],无 128000 和 128001
如果输出与预期一致,说明修复生效。



