LlamaTokenizer in v5 overrides tokenizer.json’s ByteLevel pre-tokenizer with Metaspace, silently breaks DeepSeek V3/R1 family

使用 transformers v5 的 AutoTokenizer.from_pretrained() 加载任何 tokenizer_config.json 中设置了 "tokenizer_class": "LlamaTokenizerFast" 或 "LlamaTokenizer" 的模型。已确

LlamaTokenizer in v5 overrides tokenizer.json's ByteLevel pre-tokenizer with Metaspace, silently breaks DeepSeek V3/R1 family

LlamaTokenizer in v5 overrides tokenizer.json’s ByteLevel pre-tokenizer with Metaspace, silently breaks DeepSeek V3/R1 family

快速结论:该问题出现在使用 Hugging Face Transformers v5 版本的 AutoTokenizer 加载 DeepSeek V3/R1 系列模型时,LlamaTokenizerFast 的 __init__ 会无条件地用 Metaspace pre-tokenizer 覆盖 tokenizer.json 中声明的 ByteLevel pre-tokenizer,导致空格丢失、文本黏连。优先排查 Transformers 版本是否 ≥5.7.0,或使用 PreTrainedTokenizerFast 作为临时绕过方案。

问题场景

使用 transformers v5 的 AutoTokenizer.from_pretrained() 加载任何 tokenizer_config.json 中设置了 "tokenizer_class": "LlamaTokenizerFast""LlamaTokenizer" 的模型。已确认受影响的模型包括:DeepSeek-V3DeepSeek-V3.1DeepSeek-V3.2-ExpDeepSeek-R1DeepSeek-R1-0528,以及 DeepSeek-R1-Distill-Llama-70B(包括其 FP8 量化变体)。在 vLLM 0.25.0 等推理框架中调用推理接口时,可能以原始 byte-level 标记(如 Ġ)的形式出现在输出中。

报错原文

# 复现代码
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("deepseek-ai/DeepSeek-V3")
print(repr(tok.decode(tok.encode("hello world", add_special_tokens=False))))
# 'helloworld'  — expected 'hello world'

# vLLM 下游症状(接口返回原始 byte-level 标记)
"content": "\n\nOkay,ĠtheĠuserĠgreetedĠme..."

原因分析

DeepSeek V3/R1 的 tokenizer.json 使用的是 ByteLevel BPE(GPT-2 风格,非 SentencePiece),其 pre-tokenizer 为 Sequence([..., ByteLevel])。但在 Transformers v5 的 LlamaTokenizer.__init__ 中,当加载现有 tokenizer.json 时,会无条件安装一个 Metaspace pre-tokenizer(replacement="▁", split=False),覆盖了原始配置。由于词汇表中没有 前缀的 token,Metaspace 标记空间消失,导致 round-trip 后空格丢失。

相同文件通过 tokenizers.Tokenizer.from_file(...)PreTrainedTokenizerFast.from_pretrained(...) 加载时工作正常——问题特定于 LlamaTokenizer__init__

环境排查

  • transformers:确认版本(v5.0.0 – v5.6.2 受影响,v5.7.0 已修复,但后续 v5.13.0 等版本仍有复现报告)。
  • tokenizers:确认版本(0.22.0、0.22.1、0.22.2 均复现)。
  • Python:3.12 / Linux(报告环境中)。
  • 加载方式:使用 AutoTokenizer.from_pretrained() 而不是 PreTrainedTokenizerFast.from_pretrained()
  • 检查预训练仓库的 tokenizer_config.json:确认 tokenizer_class 是否包含 Llama 关键字(如 DeepSeek-R1-Distill-Llama-8B 可能错误映射到 Llama pre-tokenizer)。

解决步骤

  1. 首要修复:更新 Transformers 到 v5.7.0 或更新版本(虽然 v5.8.0/v5.8.1 在一定条件下仍有复现,但 main 分支已修复)。若仍不行,切换到 main 分支:
    pip install git+https://github.com/huggingface/transformers.git@main
  2. 临时绕过:使用 PreTrainedTokenizerFast 加载(建议 v5.6.x 及以下版本优先尝试):
    from transformers import PreTrainedTokenizerFast
    tok = PreTrainedTokenizerFast.from_pretrained("deepseek-ai/DeepSeek-V3")
  3. 如果模型是 DeepSeek-R1-Distill-Llama-8B 等可能错误映射到 Llama 的仓库:需要等待 Transformers 的 workaround PR(#45936)合并,或在 Hub 上修正模型配置。目前可手动加载时指定 trust_remote_code=False 并检查 tokenizer_config.json 中的 class name。

验证方法

运行以下 round-trip 测试,确认输出是否保留空格:

from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("deepseek-ai/DeepSeek-V3")
print(repr(tok.decode(tok.encode("hello world", add_special_tokens=False))))
# 期望输出:'hello world'

如果输出为 'helloworld',说明问题未解决;如果输出为 'hello world',则修复成功。

同时验证 convert_ids_to_tokens 是否包含正确的 byte-level 标记(如 Ġ)——如果 tokenize 步骤正确但 decode 步骤丢失空格,则属于此 bug 的典型表现。

参考来源

huggingface/transformers #45488

修复 PR:#44801(初始修复)、#45936(针对 Distill 模型的 workaround)、#46091(后续修复)

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

celebrityanime
celebrityanime
文章: 13535

发表回复

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