LM Studio 导出的 GGUF 模型被 Ollama 加载后,如果对话模板没有同步过去,聊天界面会出现不按预期格式化输出的情况。问题通常不在模型文件本身,而是 Ollama 在导入时不会主动识别 GGUF 内的聊天模板。需要你从模型原配置中复制模板,手动写入 Modelfile 的 TEMPLATE 指令,然后重建模型并验证。
对话模板并不是导出时被删掉,而是 Ollama 导入 GGUF 时不会自动把原模型的 chat template 映射为自身的 TEMPLATE。你需要先确认模板缺失,再从原模型的 tokenizer_config.json 中提取模板并转换为 Modelfile 的 TEMPLATE,最后通过 ollama show 和实际对话确认效果。模板必须与模型训练时的格式一致,否则修复无效。
先确认模板是否真的丢失
使用 ollama show 检查目标模型的模板。例如:
ollama show my-imported-model `--modelfile`
如果输出的 Modelfile 里 TEMPLATE 为空,或只有 {{ .Prompt }} 这类占位,说明模板没有正确加载。另一种表现是使用 ollama run 对话时,模型不打印系统提示,或每次回复都出现意外的重复。这时再检查模板才有意义。
从模型原始配置中获取正确模板
Ollama 使用 Go 模板渲染 Prompt。模板字符串通常可以在原模型的 tokenizer_config.json 的 chat_template 字段找到。如果你是从 LM Studio 导出的模型,可以在 LM Studio 的模型缓存目录中查找同名文件的 tokenizer_config.json;如果模型来自 Hugging Face,也可以直接在该模型的模型卡 Files 里打开这个文件。
复制出来的 chat_template 不一定能直接放进 Modelfile,因为 Ollama 支持的变量名和辅助函数有限。常见做法是把变量名改为 {{ .Prompt }}、{{ .System }}、{{ .Response }},并删除原有 Jinja 语法中的循环和宏。例如 ChatML 格式的模板通常可以精简为:
TEMPLATE """{{- if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{- end }}
<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
{{ .Response }}<|im_end|>
"""
这个例子假定模型使用 ChatML 的 <|im_start|> 和 <|im_end|> 标记。如果你的模型原始模板不是这个格式,不要直接套用,要去对照 tokenizer_config.json 里的内容。
写入 Modelfile 并重建
创建一个 Modelfile,至少需要 FROM 和 TEMPLATE。FROM 指向你导出的 GGUF 文件路径,例如:
FROM ./my-model.gguf
TEMPLATE """..."""
然后执行:
ollama create my-model-fixed -f ./Modelfile
注意,如果原模型还包含 SYSTEM 消息或停止词,可以在 Modelfile 中一并添加 PARAMETER stop 或 SYSTEM 指令。但这些都是补充,核心是 TEMPLATE 的格式。
验证模板是否生效
重建后先查看模板是否被写入:
ollama show my-model-fixed `--template`
如果输出和你写的一致,说明模板已保存。然后实际运行对话,可以使用 ollama run `--verbose` 查看发送给模型的完整 prompt,确认其中是否包含模板中定义的特殊标记。若模板没有生效,检查 Modelfile 的语法,或确认 GGUF 文件本身是否损坏。
常见问题
是不是所有模型都要手动加 TEMPLATE?
不是所有模型都要加。部分 GGUF 文件自带模板,或者你使用的 Ollama 版本在导入时已识别模板,但手动验证仍是最可靠的做法。若你发现导入的模型对话格式不对,再按上面的步骤补 TEMPLATE 即可。
模板写错了会怎样?
模板写错通常不会导致模型报错,而是模型回复时不去用你指定的格式标记,看起来像模板没生效。因此写完后必须执行 ollama show `--template` 和实际对话两个验证,不能只看创建是否成功。