AutoTokenizer silently corrupts deepseek-math-7b-rl in 5.x: encode strips all spaces, decode emits literal byte-level markers

这个报错通常出现在 5.x 版本用 AutoTokenizer 加载 llama 风格、但词表实际为 ByteLevel-BPE(用 Ġ 做词边界)的模型时,例如 deepseek-ai/deepseek-math-7b-rl :编码会静默丢掉空格,解码输出 'weneedtoadd9and6' ,

快速结论:这个报错通常出现在 5.x 版本用 AutoTokenizer 加载 llama 风格、但词表实际为 ByteLevel-BPE(用 Ġ 做词边界)的模型时,例如 deepseek-ai/deepseek-math-7b-rl:编码会静默丢掉空格,解码输出 'weneedtoadd9and6',生成时还会把 Ġ/Ċ 当作可见字符输出。优先核对你加载后的 tokenizer 组件是否被替换成了 sentencepiece/Metaspace 流程。

适用环境:Issue 中已确认:transformers 5.15.1(4.46.3 无此问题)、tokenizers 0.22.2、Python 3.12、Linux x86_64(另有 Windows 复现);模型 deepseek-ai/deepseek-math-7b-rl,属于 llama 风格 ByteLevel-BPE tokenizer 家族。CUDA、显卡型号未在 Issue 中提供。

最快修复方案:先用绕过方案:改为直接加载仓库原版 tokenizer.json,即用 PreTrainedTokenizerFast(tokenizer_file="<path>/tokenizer.json"),再把 chat_template / bos / eos 从原(有问题的)AutoTokenizer 加载结果上移植过来。Issue 中已验证该方式行为正确,且与 4.46.3 的 AutoTokenizer 输出 token 完全一致(约 4000 条 prompt 验证)。

注意事项:该绕过方案需要在原有流程中手动补回 chat_template、bos、eos 等配置,替换时要确认这一部分没有遗漏。恢复正常 AutoTokenizer 加载的修复方案在 Issue 中未见最终确认版本,升级或打补丁前建议先用下面的验证方法确认 round-trip 是否恢复。

问题场景

用户在 5.x 版本中用 AutoTokenizer.from_pretrained("deepseek-ai/deepseek-math-7b-rl") 加载 tokenizer,然后对普通文本做 encode/decode round-trip,或在生成流程中解码输出时触发问题。表现是编码结果对应的是“去掉空格后的字符串”,解码不能还原空格;在生成管线里,Ġ、Ċ 这类 byte-level 标记会以字面字符出现在解码文本中。该问题静默发生,没有告警,Issue 作者提到它直接导致一整轮评测结果失效。

报错原文

'weneedtoadd9and6'
['w', 'ene', 'ed', 'to', 'add', '9', 'and', '6']

同时对比同一份 tokenizer.json 的原始加载结果:

raw tokenizer.json  -> ['we','Ġneed','Ġto','Ġadd','Ġ','9','Ġand','Ġ','6']   decode: 'we need to add 9 and 6'
AutoTokenizer       -> ['w','ene','ed','to','add','9','and','6']             decode: 'weneedtoadd9and6'

原因分析

Issue 评论中给出了较明确的机制:同一个 tokenizer.json,原始 Tokenizer.from_file 加载正常,而 AutoTokenizer.from_pretrained 加载后组件被替换。对比 tok._tokenizer.to_str() 与文件内容可见:

  • pre_tokenizer:文件中是 ByteLevel BPE 的 Sequence of Split,加载后变成 Metaspace(replacement="▁"、prepend_scheme="always"、split=false);
  • decoder:文件中是 ByteLevel,加载后变成 Sequence[Replace("▁"→" "), ByteFallback, Fuse, …];
  • normalizer:文件中是空的 Sequence,加载后变成 null。

也就是说,被套上的是 Llama 的 sentencepiece 流程,而词表本身是 byte-level、词边界标记是 Ġ 而不是 ▁。Metaspace 预分词找不到 ▁,于是没有 token 携带边界标记、空格被丢弃,得到 ['w','ene','ed',...];解码端的 ▁→" " 规则没有可替换内容,因此无法还原空格,生成时原始 Ġ/Ċ 标记还会直接暴露出来。

两个可用于定位的细节:仓库中没有 tokenizer.model(hf_hub_download(..., "tokenizer.model") 返回 404),只有 4.6 MB 的 tokenizer.json,却被合成了 sentencepiece 流程;tokenizer_config.json 中写着 "tokenizer_class": "LlamaTokenizerFast",返回对象 is_fast=True、类名为 LlamaTokenizer,说明不是 fast/slow 回退,而是 fast 路径本身替换了组件。

环境排查

  • 确认 transformers 版本:5.15.1 复现,4.46.3 正常;
  • 确认 tokenizers 版本:评论复现环境为 0.22.2;
  • 确认 Python 版本:Issue 为 3.12;
  • 确认操作系统:Linux x86_64(Windows 亦有复现);
  • 确认模型:deepseek-ai/deepseek-math-7b-rl,或其他 llama 风格但使用 ByteLevel-BPE(Ġ 词边界)词表的模型;
  • 确认模型仓库是否只有 tokenizer.json、没有 tokenizer.model;
  • 确认 tokenizer_config.json 中的 tokenizer_class 字段值;
  • 确认加载后 tokenizer 的 pre_tokenizer / decoder / normalizer 类型(可用 tok._tokenizer.to_str() 对比文件内容)。

解决步骤

  1. 先做最小复现:用 AutoTokenizer.from_pretrained 编码 "we need to add 9 and 6",convert_ids_to_tokens 看是否缺少带 Ġ 前缀的 token,decode 看是否变成 'weneedtoadd9and6'。
  2. 同时用 tokenizers.Tokenizer.from_file 直接加载同一份 tokenizer.json(可用 hf_hub_download 取路径),做同样编码。若原始加载结果含 Ġ 边界 token、decode 能还原空格,说明问题在 AutoTokenizer 的重建流程,而不是文件本身。
  3. 可优先尝试绕过方案:改用 PreTrainedTokenizerFast(tokenizer_file="<path>/tokenizer.json") 加载,再把 chat_template、bos、eos 等从原来的 AutoTokenizer 加载结果移植过来。
  4. 若无法替换 tokenizer 加载方式,可在升级/回退 transformers 版本前,先用原始 tokenizer.json 的加载结果作为基准,验证新版本 AutoTokenizer 的 round-trip 是否恢复正常。
  5. 不要指望通过 use_fast 参数规避:Issue 中 use_fast=True 和 use_fast=False 都产生损坏输出。

验证方法

用修复后的 tokenizer 重新编码 "we need to add 9 and 6",要求 decode(input_ids) 输出 'we need to add 9 and 6',且 convert_ids_to_tokens 中出现带 Ġ 前缀的词边界 token(例如 Ġneed、Ġto),而不是 ['w','ene','ed',...] 这种去空格切分。再跑若干条真实 prompt,确认生成结果里不再出现字面的 Ġ、Ċ 字符。

参考来源

huggingface/transformers #48206

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 26254

发表回复

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