0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OllamaのModelfileはChat Templateを4パターンで上書き

0
Last updated at Posted at 2026-09-18

Ollama Modelfileの4ディレクティブ (SYSTEM=SAFE / PARAMETER=SAFE / MESSAGE=CAREFUL / TEMPLATE=RISKY)、qwen2.5/gemma2/qwen3.5/deepseek-r1で実測

Ollama の Modelfile は「カスタム設定ファイル」だと思っていました。実態は、base model の chat template を含む挙動を、4種類のディレクティブでまるごと上書きできる仕組みです。ローカル LLM の応答が Modelfile 記述で毎回変わる原因は、ここにあります。本記事は Ollama Modelfile の 4ディレクティブ(TEMPLATE / SYSTEM / PARAMETER / MESSAGE)が chat template をどう上書きするかを、ollama show + ollama create で実測して確かめた話です。num_ctx デフォルトの罠、ランタイム比較、TTFT 指標、量子化、Cold Start 時間とは別軸で、「Modelfile を書き換えるとモデルの応答がどう変わるか」だけに絞ります。

Modelfile の4種類のディレクティブ

Ollama 公式ドキュメント(github.com/ollama/ollama/blob/main/docs/modelfile.mdx)によると、Modelfile で base model の挙動を上書きできるのは、主に次の4つのディレクティブです。

ディレクティブ 上書きする対象 影響範囲
TEMPLATE chat template (プロンプトのフォーマット) 生成時の入力形式そのもの
SYSTEM system prompt モデルの応答方針・ペルソナ
PARAMETER サンプリング/context 設定 温度・top_p・num_ctx など
MESSAGE 事前会話履歴 (few-shot) few-shot 例の埋め込み

他にも FROM ADAPTER LICENSE などがあります。応答の中身に一番効くのはこの4つです。

実測1: base model の Modelfile を覗く

ollama show <model> --modelfile を打つと、そのモデルが持っている Modelfile が全部出てきます。手元の4モデルで実測しました。

qwen2.5:1.5b

TEMPLATE """{{- if .Messages }}
{{- if or .System .Tools }}<|im_start|>system
{{- if .System }}
{{ .System }}
{{- end }}
{{- if .Tools }}

# Tools

You may call one or more functions to assist with the user query.

Qwen 系のトークン(<|im_start|> <|im_end|>)を使った chat template。Tools 対応の分岐が最初から入っています。

gemma2:2b

TEMPLATE """{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1 }}
{{- if or (eq .Role "user") (eq .Role "system") }}<start_of_turn>user
{{ .Content }}<end_of_turn>

Gemma 系のトークン(<start_of_turn> <end_of_turn>)を使う別の chat template。同じ Ollama から起動しているのに、モデルごとに template が完全に別物 です。

qwen3.5:0.8b

TEMPLATE {{ .Prompt }}
RENDERER qwen3.5
PARSER qwen3.5
PARAMETER presence_penalty 1.5

Qwen 3.5 系は TEMPLATE が {{ .Prompt }} だけで、代わりに RENDERERPARSER が別途指定されています。Tool call のパースは Ollama 側の RENDERER/PARSER が担う、新しめの設計です。

deepseek-r1:1.5b

TEMPLATE """{{- if .System }}{{ .System }}{{ end }}
{{- range $i, $_ := .Messages }}
{{- if eq .Role "user" }}<|User|>{{ .Content }}
{{- else if eq .Role "assistant" }}<|Assistant|>
  {{- if and $.IsThinkSet (and $last .Thinking) -}}
<think>
{{ .Thinking }}
</think>

DeepSeek R1 は独自の全角 U+FF5C トークン(<|User|> <|Assistant|>)を使い、<think> タグで reasoning ブロックを分離できる設計です。

4モデルで chat template が完全に別々 です。

「同じ Ollama で ollama run するのだから同じインターフェイスだろう」という直感は、Modelfile を覗いた瞬間に崩れます。

実測2: Modelfile で上書きする

ollama create で Modelfile を渡すと、上記の template や parameter を自由に差し替えられます。手元で試したものはこれです。

cat > /tmp/test_modelfile << 'EOF'
FROM qwen2.5:1.5b
SYSTEM """You are a laconic assistant. Answer in exactly one sentence."""
PARAMETER temperature 0.1
PARAMETER num_ctx 4096
EOF

ollama create test-laconic -f /tmp/test_modelfile

作った直後に ollama show test-laconic --modelfile を確認すると:

FROM /home/iris/.ollama/models/blobs/sha256-183715c...
TEMPLATE """{{- if .Messages }}  ← qwen2.5 の TEMPLATE を継承
SYSTEM You are a laconic assistant. Answer in exactly one sentence.
PARAMETER num_ctx 4096
PARAMETER temperature 0.1

指定した SYSTEM と PARAMETER が上書きされ、TEMPLATE は qwen2.5 のものが継承されました。書いた分だけ上書き書かなければ base のまま です。全上書きでも部分上書きでも動きます。以降、ollama run test-laconic すると、system prompt が「一文で答える」に固定された状態でモデルが動きます。

実測3: TEMPLATE をゼロから書き換えると何が起きるか

TEMPLATE {{ .Prompt }} だけの最小構成に置き換えた Modelfile を作ってみます。

FROM qwen2.5:1.5b
TEMPLATE """{{ .Prompt }}"""

これで ollama create すると、chat template のトークン(<|im_start|> <|im_end|>)が消えます。Ollama から ollama run すると、モデルが「システムメッセージ何それ?」の状態になり、応答が急にランダム化します。Qwen 系は chat template のトークンを前提に学習されているので、テンプレートを外すと事後学習の重みが機能しなくなるためです。TEMPLATE を書き換えるときは、base model が学習したトークンを維持すること。必須です。ここを守らずに書き換えて「Ollama のモデルが急に嘘つきになった」を経験するのが、Modelfile カスタマイズの最初の落とし穴です。

4パターンで整理

上書きするディレクティブの組み合わせで、応答がどう変わるかをまとめます。

パターン 変えるもの 応答への影響
A SYSTEM のみ ペルソナ・答え方が変わる。安全
B PARAMETER のみ 温度・context 長・stop トークンが変わる。挙動チューニング
C MESSAGE を追加 few-shot 例を仕込める。回答フォーマット固定に有効
D TEMPLATE を全上書き chat template トークンが変わる。壊しやすい、慎重に

A / B / C は日常的に使ってよい上書きD はモデルの再学習を疑うレベルの変更 だと思って扱うのが安全です。Hugging Face の tokenizer_config.json から chat template を取ってきて Modelfile に貼り付ける、というワークフローも可能です。これはパターン D に該当します。tokenizer 側の template と Ollama の Go template 文法({{- if .Messages }} など)の変換が必要になるので、単純コピペでは動かない点も注意です。

MESSAGE ディレクティブの実用

見落とされがちなのが MESSAGE です。few-shot 例を仕込めるので、フォーマットを固定したいときに便利です。

FROM qwen2.5:1.5b
SYSTEM """You are a JSON API. Always respond with valid JSON."""
MESSAGE user What is 2 plus 2?
MESSAGE assistant {"answer": 4}
MESSAGE user What is 3 times 5?
MESSAGE assistant {"answer": 15}

この状態で ollama run すると、JSON以外の形式で返してくる確率が明確に下がります。SYSTEM だけで指示するより、MESSAGE で1-2例見せた方が効くのは、通常の in-context learning と同じです。Ollama 単体で軽い few-shot エージェントを作りたいときに、MESSAGE ディレクティブは覚えておく価値があります。

実測 - Modelfile 上書きで PARAMETER が本当に効くか

「PARAMETER を Modelfile に書いても、実行時のリクエストに options で渡さないと効かないのでは?」を確かめました。

cat > /tmp/temp_low << 'EOF'
FROM qwen2.5:1.5b
PARAMETER temperature 0.01
EOF
ollama create test-cold -f /tmp/temp_low

# API 経由でリクエスト
curl -s http://localhost:11434/api/generate -d '{
  "model": "test-cold",
  "prompt": "Say a random word",
  "stream": false
}' | jq -r .response

同じプロンプトを5回投げると、test-cold はほぼ同じ単語(私の環境では "Sure" が5回中4回)を返しました。base の qwen2.5:1.5b にリクエスト時 options: {temperature: 1.0} を渡した場合と比べると、明確にサンプリングが決定的になっているのが分かります。Modelfile の PARAMETER は、API リクエストで options を渡さない限りのデフォルト値として機能します。リクエスト側で options を渡すと、そちらが Modelfile の PARAMETER を上書きします (Ollama の設定継承ルールの通り)。両方書いてどちらが効くかは、リクエスト側優先です。

実測 - num_ctx を Modelfile で固定する

num_ctx のデフォルト値の低さは、以前の記事(Ollama num_ctx = default 2048 の話)でも書きました。Modelfile で PARAMETER num_ctx 8192 を書いておけば、そのモデルを叩くたびに明示指定しなくて済みます。

FROM qwen2.5:1.5b
PARAMETER num_ctx 8192

これで ollama create qwen-8k -f Modelfileollama run qwen-8k すると、8k コンテキストで起動します。API 経由でも options に num_ctx を指定しなくても8kで動きます。長文入力するモデルには、Modelfile で num_ctx を固定しておく。安全です。VRAM 12GB で 32B モデルを動かすときは、Modelfile で num_ctx を明示的に4096 or 8192 にキャップしておかないと、モデルが自称する最大 context (32k超) を試そうとして OOM で落ちる、というのが実務でよくハマる箇所です。

Chat Template を書き換えたい実務ケース

TEMPLATE を全上書きするのは危険と書きました。以下のケースでは書き換えが必要になります。

  1. Tool call の JSON フォーマットを変えたい — base の template が想定していない Tool 呼び出しをさせたい場合、TEMPLATE の Tools 分岐を書き直す必要がある
  2. thinking モードを外したい — DeepSeek R1 のような <think> タグを応答から消したい場合、TEMPLATE の分岐を書き換える
  3. RAG 用にコンテキスト注入位置を変えたい — system prompt の中に検索結果を挿入する専用フォーマットを組みたい場合

いずれも、base model が学習した chat template トークンは維持したまま、周辺のディレクティブだけを追加/削除する形で書き換えます。トークン自体(<|im_start|> <start_of_turn> など)を消してはいけません。Ollama の TEMPLATE は Go の text/template 文法で書かれているので、慣れれば分岐や range を自由に組めます。ただし、書き換えた Modelfile を CI で回して「壊れていないか」をテストする仕組みを合わせて用意する必要があります。壊しやすい。けど、それに気付ける仕組みも簡単に組める、という設計です。

罠 - Modelfile を書き換えると再ダウンロードが必要なわけではない

Modelfile を上書きしても、モデルの重み(blob)は再ダウンロードされません。ollama create は base model の blob をそのまま参照して、新しい manifest(小さな JSON) だけを作ります。

ollama show test-laconic --modelfile の1行目に、

FROM /home/iris/.ollama/models/blobs/sha256-183715c...

と出ていたのは、上書きした Modelfile も qwen2.5:1.5b と同じ blob を指しているためです。Modelfile カスタマイズはディスクをほぼ消費しない。実務でありがたい設計です。数十パターンの Modelfile を試しても、ディスク占有は base model 1個分のままです。

まとめ

  • Ollama の Modelfile は4種類のディレクティブ(TEMPLATE / SYSTEM / PARAMETER / MESSAGE)で base model の挙動を上書きする
  • ollama show <model> --modelfile で base model の chat template を確認できる。qwen / gemma / deepseek で全部別のトークンを使っていることが分かる
  • ollama create <new> -f Modelfile で上書き版を作れる。書いた分だけ差し替え、書かなければ base のまま
  • SYSTEM / PARAMETER / MESSAGE の上書きは安全、TEMPLATE の全上書きは壊しやすい
  • MESSAGE で few-shot を仕込むと、SYSTEM だけよりフォーマット固定が効きやすい
  • Modelfile の上書きは blob を再ダウンロードしない。ディスクをほぼ消費せずに複数バリアント運用可

Ollama Modelfile は「カスタム設定ファイル」ではなく、モデルの挙動を4方向から上書きできる小さな DSL でした。base model の chat template を尊重した上で、SYSTEM と PARAMETER と MESSAGE を上手く組み合わせるのが、Ollama を実務投入するときの基本作法です。同じ base model から、用途別に3-5個のバリアント (myapp-json / myapp-narrative / myapp-code) を Modelfile で作り分ける、というのが Ollama を業務投入するときのよくある実装パターンです。ディスクを消費しないので、思ったより気軽にできます。プロンプトを毎回長々と書く代わりに、Modelfile 側で持たせておく方が、システム全体の再現性も上がります。

ローカル LLM のより広い運用ノウハウは、以下の書籍で章立てして解説しています。

Claude Code Mastery

参考

  • Ollama 公式: Modelfile documentation
  • Ollama 実測コマンド: ollama show <model> --modelfile / ollama create <new> -f Modelfile
  • 実測モデル: qwen2.5:1.5b / gemma2:2b / qwen3.5:0.8b / deepseek-r1:1.5b
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?