快速结论:当 GGUF 词表对应的 Hugging Face tokenizer 不需要清理空格时,llama.cpp 仍对 BPE 词表启用了 clean_spaces,导致 llama_detokenize 删掉 “!”“?”“.”“,” 前面的空格以及 “’s”“’re” 前面的空格,表现为解码文本与原文不一致。优先排查词表的 pretokenizer 类型是否被错误地开启了 clean_spaces。
适用环境:llama.cpp b11769-14-g339f3242c(Mac 上报告);Linux master 0a1ef309c 已复现。涉及 libllama 的 llama_tokenize 与 llama_detokenize。受影响模型包括 Gemma 4、GLM-4.x/5.x、LFM2、Mellum2、Nemotron(pixtral)、Granite 4.1(dbrx)、MiniCPM5。其他随附版本未在 Issue 中确认。
最快修复方案:暂无确认的一步修复方案。Issue 中已验证的折中办法是在 Gemma 4 分支的 pretokenizer 配置里加上 clean_spaces = false;,评论者报告该修改可修复问题且 test-tokenizer-0 仍通过;作者已计划在转换脚本与加载器中一并调整,但 Issue 关闭时没有给出可直接套用的完整补丁。
注意事项:直接改默认值只对 Issue 列出的 pretokenizer 生效,不能自动适配所有词表;如果模型自带的 Hugging Face 配置明确设置了 clean_up_tokenization_spaces,GGUF 当前并未保存该设置,因此单改默认值可能仍与实际配置不一致。流式输出不受影响,问题主要体现在重新分词或调用 llama_detokenize 的场景。
问题场景
在 llama.cpp 中使用 Gemma 4 等模型的 GGUF 词表时,先调用 llama_tokenize 编码,再调用 llama_detokenize 解码,得到的文本与输入不一致。Issue 中的复现脚本通过 llama_tokenize + llama_detokenize 的 harness 对比 Hugging Face tokenizer 的输出。用户可见的场景包括 llama-mtmd-cli 的聊天历史(后续会重新分词)、server 的 prompt 字段,以及任何直接调用 llama_detokenize 的应用。
报错原文
'if (x != y) {' -> 'if (x!= y) {'
'x = a ? b : c' -> 'x = a? b : c'
"It 's fine" -> "It's fine"
MISMATCH
原因分析
最可能的原因是 llama-vocab.cpp 对每个 BPE 词表都设置了 clean_spaces = true,而只为部分 pretokenizer(qwen2、deepseek、qwen35、command-r)关闭了该选项。Hugging Face 的 clean_up_tokenization_spaces 设置没有被存入 GGUF,Gemma 4 等模型的 tokenizer 实际不清理这些空格,于是 llama.cpp 的解码结果与 Hugging Face 不一致。该清理逻辑并非回归,最早由 #8039(2024 年 7 月)引入。
环境排查
- 确认 llama.cpp 版本或提交号,Issue 涉及 b11769-14-g339f3242c 与 master 0a1ef309c。
- 确认所用 GGUF 词表及其 pretokenizer 类型,重点看 gemma4、lfm2、glm4/glm5、mellum2、minicpm5、dbrx 等分支是否开启了 clean_spaces。
- 对照同一模型的 Hugging Face tokenizer,检查
clean_up_tokenization_spaces是否未设置或为 false。 - 确认问题是否出现在 llama_detokenize、llama-mtmd-cli 聊天历史或 server prompt 字段中,而流式输出正常。
- 如果自行修改源码,运行
test-tokenizer-0确认现有分词行为未被破坏。
解决步骤
- 先用 Issue 中的方法或自己的 harness 对比同一字符串在 llama.cpp 与 Hugging Face tokenizer 下的解码结果,确认空格消失的位置。
- 定位到
llama-vocab.cpp中对应模型的 pretokenizer 分支,例如 gemma4 分支。 - 可优先尝试在该分支增加
clean_spaces = false;。Issue 评论者验证此修改可修复 Gemma 4,且test-tokenizer-0通过。 - 对 Issue 列出的其他受影响模型,按其 pretokenizer 分支分别评估是否需要关闭清理;不要在未验证的情况下全局关闭。
- 若需要长期修复,关注作者计划的方案:转换脚本在 tokenizer_config.json 设置
clean_up_tokenization_spaces时写入新键tokenizer.ggml.clean_spaces,加载器优先读取该键,缺省时保留各 pretokenizer 的默认值。 - 重新编译后,用相同字符串再次执行编码与解码对比。
验证方法
用相同输入分别执行 llama.cpp 的 llama_tokenize + llama_detokenize 与 Hugging Face tokenizer 的 encode/decode,确认 'if (x != y) {'、'x = a ? b : c'、"It 's fine" 等字符串解码后与原文完全一致,且 test-tokenizer-0 通过。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


