具备思考能力的模型会发出一个 thinking 字段,将推理轨迹与最终答案分离。

利用此功能可以审计模型的步骤、在 UI 中动画展示模型的 thinking(思考)过程,或者当只需要最终响应时完全隐藏推理轨迹。

参见完整的思考模型列表。

发现模型的思考控制选项

思考控制选项因模型而异。使用 /api/show 来发现模型支持的取值以及 Ollama 默认使用的值:

curl http://localhost:11434/api/show -d '{
  "model": "gpt-oss"
}'

响应中包含一个顶层的 thinking 对象:

{
  "thinking": {
    "values": ["low", "medium", "high"],
    "default": "medium"
  }
}
  • values 可以包含布尔值(true 或 false),用于开关控制。它也可以包含模型定义的字符串,用于命名级别。
  • 当未设置 think 时,使用 default 值。
  • values: [false] 表示该模型不支持思考功能。
  • 如果省略了 thinking,则该模型没有思考元数据。模型可能会根据其现有行为进行思考。

在 API 调用中启用思考

在 chat 或 generate 请求中设置 think 字段:

  • true:请求输出思考内容。
  • false:如果模型允许,则请求不输出思考内容。
  • null:使用模型的默认设置。
  • 字符串:从 thinking.values 中选择支持级别。请使用来自 /api/show 的确切值。不支持数字。

如果模型根据 /api/show 元数据解析命名级别,Ollama 会精确应用支持的名称。不支持的名称将使用模型的默认值。

推理输出和答案使用不同的字段。Chat 返回 message.thinking 和 message.content。Generate 返回 thinking 和 response。

cURL

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3",
  "messages": [{
    "role": "user",
    "content": "How many letter r are in strawberry?"
  }],
  "think": true,
  "stream": false
}'

Python

from ollama import chat

response = chat(
  model='qwen3',
  messages=[{'role': 'user', 'content': 'How many letter r are in strawberry?'}],
  think=True,
  stream=False,
)

print('Thinking:\n', response.message.thinking)
print('Answer:\n', response.message.content)

JavaScript

import ollama from 'ollama'

const response = await ollama.chat({
  model: 'deepseek-r1',
  messages: [{ role: 'user', content: 'How many letter r are in strawberry?' }],
  think: true,
  stream: false,
})

console.log('Thinking:\n', response.message.thinking)
console.log('Answer:\n', response.message.content)

流式传输推理轨迹

思考内容的流式传输会在答案令牌之前交错发送推理令牌。检测第一个 thinking 块以渲染“思考”部分,然后在 message.content 到达时切换到最终回复。

Python

from ollama import chat

stream = chat(
  model='qwen3',
  messages=[{'role': 'user', 'content': 'What is 17 × 23?'}],
  think=True,
  stream=True,
)

in_thinking = False

for chunk in stream:
  if chunk.message.thinking and not in_thinking:
    in_thinking = True
    print('Thinking:\n', end='')

  if chunk.message.thinking:
    print(chunk.message.thinking, end='')
  elif chunk.message.content:
    if in_thinking:
      print('\n\nAnswer:\n', end='')
      in_thinking = False
    print(chunk.message.content, end='')

JavaScript

import ollama from 'ollama'

async function main() {
  const stream = await ollama.chat({
    model: 'qwen3',
    messages: [{ role: 'user', content: 'What is 17 × 23?' }],
    think: true,
    stream: true,
  })

  let inThinking = false

  for await (const chunk of stream) {
    if (chunk.message.thinking && !inThinking) {
      inThinking = true
      process.stdout.write('Thinking:\n')
    }

    if (chunk.message.thinking) {
      process.stdout.write(chunk.message.thinking)
    } else if (chunk.message.content) {
      if (inThinking) {
        process.stdout.write('\n\nAnswer:\n')
        inThinking = false
      }
      process.stdout.write(chunk.message.content)
    }
  }
}

main()