- 作成日: 2025/06/01
- 最終更新日: 2025/06/01
前提: Thinking
- 回答の前に検討過程を出力すること、またはそう訓練されたモデルの機能
- 推論性能が向上する
- Reasoning とも呼ぶ
ollama では v0.9 からサポート(think の有効/無効切り替えオプション追加、ハイライト表示)を追加
- Thinking · Ollama Blog
- 2025/06/01 時点では qwen3, deepseek-r1 のみ
概要
- 前処理
- thinking サポートモデルかどうかをプロンプトテンプレートから判定
- リクエスト
- プロンプトテンプレートに thinking 追加
- レスポンス
- 愚直にパースして分解
ollama/server/images.go at 5c42800fca4da07d1c362c0f190429993e53c3b5 · ollama/ollama
- モデルテンプレートに Think 関連の属性があれば Capability に追加される
- より正確には、Thinking の開始・終了タグがあるかを判定
ollama/server/thinking.go at v0.9.0 · ollama/ollama
{{ .Thinking }}
のようなテンプレートを探し、その前後の値を切り出すことで、開始・終了タグを特定
<think>{{ .Thinking }}</think>
ollama/template/template.go at 5c42800fca4da07d1c362c0f190429993e53c3b5 · ollama/ollama
- テンプレート置換に Think、IsThinkSet を追加
- Think(boolean): Think 機能が有効かどうか。モデルがサポートしていればデフォルト true
- IsThinkSet(boolean): ユーザーが明示的に Think 機能を設定したかどうか
- 主にプロンプトテンプレートにおいて、明示的な指定時のみ置換が行われる箇所があるため
テンプレート側にも対応が追加されている
qwen3/template より抜粋
{{- if and $.IsThinkSet (eq $i $lastUserIdx) }}
{{- if $.Think -}}
{{- " "}}/think
{{- else -}}
{{- " "}}/no_think
{{- end -}}
{{- end }}<|im_end|>
{{ else if eq .Role "assistant" }}<|im_start|>assistant
{{ if (and $.IsThinkSet (and .Thinking (or $last (gt $i $lastUserIdx)))) -}}
<think>{{ .Thinking }}</think>
{{ end -}}
(中略)
{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant
{{ if and $.IsThinkSet (not $.Think) -}}
<think>
</think>
{{ end -}}
{{ end }}
ollama/server/routes.go at 5c42800fca4da07d1c362c0f190429993e53c3b5 · ollama/ollama
- think サポートなら addContent に渡す
ollama/server/thinking.go at v0.9.0 · ollama/ollama
- eat 関数による愚直なステートパーサーで
<think>
</think>
部分とそれ以外に分割
ollama/server/thinking.go at v0.9.0 · ollama/ollama
- eat の結果を受けて、think 部分と残りのレスポンスに分割して返す
ollama/cmd/cmd.go at 5c42800fca4da07d1c362c0f190429993e53c3b5 · ollama/ollama
- response に thinking が含まれていればそれを表示
ollama/cmd/cmd.go at 5c42800fca4da07d1c362c0f190429993e53c3b5 · ollama/ollama
- think 部分を出力
- plainText でなければ(ターミナル上なら)色をグレーにする
/set nothink
した際、旧バージョンでは表示されていた空の <think></think>
が出ないよう改善されている
これは不思議
- 実装では
/set nothink
のときはそもそもレスポンスのパーサーが実行されない - じゃあどうやって
<think>
を特定して消してるの?
実は ollama のソースコード上では処理していない
モデルのテンプレートにあらかじめ、/set nothink
のときだけ空の<think></think>
をプロンプトに埋め込むよう指示がある
{{- if and (ne .Role "assistant") $last }}<|im_start|>assistant
{{ if and $.IsThinkSet (not $.Think) -}}
<think>
</think>
{{ end -}}
{{ end }}
これによりLLMは<think>
を生成しない
∵ LLM の立場では <think></think>
までは生成済みで、その後を考えるタスクになる
実際にモデルのプロンプトから上記の対応部分を削除すると、空の <think></think>
が出力されるようになる
→ Ollama のソースコードで処理しているわけではないとわかる
- 2025/06/01 公開