Ollama Modelfile 参考
Modelfile 是自定义模型的"配方文件"。想固定一个角色设定、改采样参数、换上自己的提示词模板,甚至导入外部的 GGUF 权重,全写在一个纯文本文件里,然后 ollama create 一下,就得到一个可以反复 run 的模型。
它比想象中简单——就是一个指令列表,一行一条。
版本基线 v0.40.12,官方
docs.ollama.com/modelfile。
一、基本格式
## 这是注释
INSTRUCTION arguments
就两条规则:# 开头是注释,其余每行是「指令 + 参数」。指令不区分大小写(示例里用大写只是为了和参数区分开),顺序也无所谓(示例把 FROM 放第一位纯粹为了好读)。
全部可用的指令:
| 指令 | 是否必需 | 作用 |
|---|---|---|
FROM |
必需 | 指定基础模型 |
PARAMETER |
可选 | 设置模型运行参数 |
TEMPLATE |
可选 | 完整的提示词模板 |
SYSTEM |
可选 | 系统消息(设定角色行为) |
MESSAGE |
可选 | 预置对话历史(few-shot 示例) |
LICENSE |
可选 | 声明许可协议 |
REQUIRES |
可选 | 声明所需的最低 Ollama 版本 |
CAPABILITY |
可选 | 额外声明模型能力 |
二、最简单的例子
FROM llama3.2
## 温度调到 1:数值越高越有创造性,越低越稳定一致
PARAMETER temperature 1
## 上下文窗口设为 4096:模型生成下一个 token 时最多能看到多少 token
PARAMETER num_ctx 4096
## 系统消息:让模型扮演马里奥
SYSTEM You are Mario from super mario bros, acting as an assistant.
四步就能用起来:
## ① 把上面的内容保存为 Modelfile
## ② 创建模型(-f 指定文件位置,名字自己取)
ollama create my-mario -f ./Modelfile
## ③ 运行
ollama run my-mario
三、FROM:基础模型从哪来
FROM 决定模型的权重来源,三种写法对应三种来源:
## ① 从已有的本地/官方模型出发(最常用)
FROM llama3.2
## ② 从 Safetensors 目录出发(需要受支持的架构)
FROM /path/to/model-directory
## ③ 从 GGUF 文件出发
FROM ./ollama-model.gguf
GGUF 路径可以是绝对路径,也可以是相对于 Modelfile 所在目录的路径——后者更方便把模型和配方一起打包分发。
分片 GGUF(大模型常切成多个文件)有两种处理方式,用通配符最省事:
## 保留原始分片文件名,用通配符一次匹配全部
FROM ./model-*.gguf
## 或者用多个 FROM 逐片列出
FROM ./model-00001-of-00004.gguf
FROM ./model-00002-of-00004.gguf
FROM ./model-00003-of-00004.gguf
FROM ./model-00004-of-00004.gguf
一个常见误解:FROM 只是引用基础模型,不会复制权重。所以基于 llama3.2 创建的模型不会额外占用一份磁盘——它记录的是"派生关系"。
四、PARAMETER:调模型的行为
PARAMETER <参数名> <值>
完整参数表(官方列出的是这些,其中前四个是日常最常改的):
| 参数 | 作用 | 取值范围 | 默认值 |
|---|---|---|---|
num_ctx |
上下文窗口大小,决定模型能"记住"多少 token | 整数 | 2048(见下方说明) |
temperature |
温度。越高越有创造性,越低越稳定 | 浮点 | 0.8 |
top_k |
候选词数量。高(如 100)更发散,低(如 10)更保守 | 整数 | 40 |
top_p |
与 top_k 配合的累积概率阈值,高(0.95)更发散,低(0.5)更聚焦 |
浮点 | 0.9 |
repeat_last_n |
回看多少 token 以避免重复;0 关闭,-1 等于 num_ctx |
整数 | 64 |
repeat_penalty |
重复惩罚强度。高(1.5)惩罚更重,低(0.9)更宽松 | 浮点 | 1.0(关闭) |
num_predict |
最多生成多少 token | 整数 | -1(不限) |
seed |
随机种子。固定值可让相同提示词产出相同结果 | 整数 | 0 |
stop |
停止序列,命中即停止生成;可写多个 | 字符串 | 无 |
min_p |
top_p 的替代方案,按"相对最高概率的比例"过滤 |
浮点 | 0.0 |
draft_num_predict |
有草稿模型时,每步最多推测多少草稿 token;0 关闭推测解码 |
整数 | 4(内嵌 MTP 张量时需显式设置) |
关于 num_ctx 的默认值要留个心:Modelfile 文档标的是 2048,而 FAQ 里说明当前默认上下文长度是 4096,并可用 OLLAMA_CONTEXT_LENGTH 覆盖。两处口径不完全一致,说明默认值随版本调整过。判断某个模型实际用多大上下文,最可靠的方式是 ollama show 模型名 看输出,而不是背默认值。
stop 值得单独提一句:写多个 stop 就写多行。
## 命中任意一个序列就停止生成
PARAMETER stop "<|start_header_id|>"
PARAMETER stop "<|end_header_id|>"
PARAMETER stop "<|eot_id|>"
五、TEMPLATE:提示词怎么拼
TEMPLATE 定义送给模型的完整提示词格式。这部分和模型强相关——不同模型训练时用的格式不一样(ChatML、Llama 3 的头标记、Gemma 的 turn 标记……),模板写错会导致模型输出混乱,甚至不停自问自答。
Ollama 使用 Go 的 text/template 语法,有三个核心变量:
| 变量 | 含义 |
|---|---|
{{ .System }} |
系统消息 |
{{ .Prompt }} |
用户输入 |
{{ .Response }} |
模型输出。生成时,这个变量之后的内容会被忽略 |
一个 ChatML 风格的模板(<|im_start|> / <|im_end|> 系列模型使用):
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
"""
注意结尾停在 assistant 标记处,没有闭合——因为接下来由模型续写,这正是「.Response 之后的内容被忽略」的实际体现。
绝大多数情况下不要手写 TEMPLATE。 官方模型都自带正确模板,FROM 一个官方模型就能继承。只有自己导入 GGUF/Safetensors、或官方模板确实不适合你的场景时才需要改。
六、SYSTEM:设定角色
SYSTEM """<系统消息>"""
三引号支持多行。这是最常用的自定义手段——不改模型、不动参数,只加一段行为约束:
FROM qwen3
SYSTEM """你是一位资深 Linux 运维工程师。
回答时先给结论,再给命令,最后解释原因。
不确定的地方明确说"需要确认",不要猜测。"""
MESSAGE 里也能写 system 角色,效果等同,但通常还是写在 SYSTEM 更清晰。
七、MESSAGE:用示例教它怎么答
MESSAGE 预置一段对话历史,让模型照着示例的风格回答(也就是 few-shot)。格式是 MESSAGE <角色> <内容>,角色只能取三个值:
| 角色 | 含义 |
|---|---|
system |
另一种写系统消息的方式 |
user |
示例中"用户会怎么问" |
assistant |
示例中"模型应该怎么答" |
MESSAGE user Is Toronto in Canada?
MESSAGE assistant yes
MESSAGE user Is Sacramento in Canada?
MESSAGE assistant no
MESSAGE user Is Ontario in Canada?
MESSAGE assistant yes
这段示例的作用很直接:教模型只回答 yes 或 no,不要废话。比起在 SYSTEM 里写"请只回答是或否",给几个例子通常更有效——模型对模式的模仿能力强于对指令的遵守。
八、LICENSE / REQUIRES / CAPABILITY
这三个不常用,但需要时很关键。
LICENSE 声明模型的分发许可:
LICENSE """
<许可协议全文>
"""
REQUIRES 声明最低 Ollama 版本,避免别人在旧版本上跑出奇怪问题:
REQUIRES 0.14.0
CAPABILITY 给 GGUF 或 MLX 模型额外声明能力,不会影响已继承或推断出的能力。需要多个就写多行:
CAPABILITY decision
decision 这个能力只应对训练过 System One 决策提示词的权重声明——乱加不会让普通模型变成决策模型,只会让调用走错分支。
九、反查:看一个模型用的是什么配方
不知道某个模型的内置模板长什么样?直接反查:
ollama show --modelfile llama3.2
输出会打印一份完整的 Modelfile,包括模板和全部 PARAMETER:
## Modelfile generated by "ollama show"
## To build a new Modelfile based on this one, replace the FROM line with:
## FROM llama3.2:latest
FROM /Users/you/.ollama/models/blobs/sha256-00e131...
TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"""
PARAMETER stop "<|start_header_id|>"
PARAMETER stop "<|end_header_id|>"
PARAMETER stop "<|eot_id|>"
这是写自定义模板最好的起点:把官方的拷出来,只改你需要的部分,比从零手写安全得多。
注意那个 FROM 指向的是一个 blob 路径。想基于它再派生,按注释提示把 FROM 换回模型名即可(FROM llama3.2:latest)。
十、几个实用提醒
改完 Modelfile 要重新 create。 Modelfile 不是运行时配置,改完必须再跑一次 ollama create 让新配方生效;同名创建会覆盖旧模型。
参数优先级:请求 > Modelfile > 服务端环境变量。 运行时在 API 里传的 options 会覆盖 Modelfile 的 PARAMETER;Modelfile 又优先于服务端的 OLLAMA_CONTEXT_LENGTH 等全局设置。
模型体积按 blob 去重,但每个自定义模型仍占一份元数据。 基于同一基础模型派生十个角色,不会占十份权重,磁盘压力主要来自基础模型本身。
调试模板问题时先简化。 输出乱码、重复、停不下来,先把 TEMPLATE 去掉让 Ollama 用继承的默认模板试一次,能立刻判断问题是不是出在自己写的模板上。
完整的模型导入流程(GGUF/Safetensors 转 Ollama 格式)见 8.1 Ollama 导入自定义模型;想在命令层面查参数与环境变量,回看 4.1 Ollama CLI 参考。

TRAE-AI编程


更多建议: