[LLaMA3] ‘add_bos_token=True, add_eos_token=True’ seems not taking effect

用户使用 Transformers 加载 LLaMA 3(如 llama3-8b)的 AutoTokenizer ,在 from_pretrained 中或通过 tokenizer.add_bos_token = True / tokenizer.add_eos_token = True 尝试控制

[LLaMA3] 'add_bos_token=True, add_eos_token=True' seems not taking effect

[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(而非 LLamaTokenizerLlamaTokenizerFast),它的 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 侧始终可用。

解决步骤

  1. 方案一:升级到 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)
  2. 方案二:手动设置后处理器(适用于 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
  3. 方案三:使用社区修补函数(备选)
    如果需要在运行时动态控制 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

如果输出与预期一致,说明修复生效。

参考来源

huggingface/transformers #30947

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 14356

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注