Ollama 新增串流工具呼叫支援

TL;DR

Ollama 引入了串流工具呼叫,讓聊天應用程式能夠在接收逐個 token 的模型輸出時,同時呼叫如天氣查詢或數學計算等函數。

串流工具呼叫的功能

串流工具呼叫讓模型可以在不等待整個回應完成的情況下,將一般文字與函數呼叫交錯進行。應用程式可以立即向使用者顯示部分內容,並在模型發出呼叫訊號時立即執行工具(例如 API 呼叫)。

支援工具呼叫的模型

以下由 Ollama 託管的模型與新的串流功能相容:

  • Qwen 3
  • Devstral
  • Qwen2.5 與 Qwen2.5‑coder
  • Llama 3.1
  • Llama 4
  • Ollama 模型庫中「tool calling」篩選器下列出的其他模型。

簡單的工具呼叫範例(天氣)

一個 cURL 請求使用 get_current_weather 函數串流天氣查詢。回應包含增量 JSON 片段,並在模型決定呼叫函數時立即提供 tool_calls 欄位。

{
  "model": "qwen3",
  "created_at": "2025-05-27T22:54:58.100509Z",
  "message": {
    "role": "assistant",
    "content": "",
    "tool_calls": [{
      "function": {
        "name": "get_current_weather",
        "arguments": {"format": "celsius", "location": "Toronto"}
      }
    }]
  },
  "done": false
}

串流會在函數結果可用時繼續進行。

Python SDK 使用方式

Python 函式庫(pip install -U ollama)接受原生 Python 可呼叫物件作為工具。在下方的範例中,一個簡單的 add_two_numbers 函數被傳遞給 chat() 並設定 stream=True。客戶端會列印串流文字並在 tool_calls 出現時偵測到它們。

from ollama import chat, ChatResponse

def add_two_numbers(a: int, b: int) -> int:
    return a + b

messages = [{"role": "user", "content": "what is three minus one?"}]
response: ChatResponse = chat(model='qwen3', messages=messages, tools=[add_two_numbers], stream=True)

for chunk in response:
    print(chunk.message.content, end='', flush=True)
    if chunk.message.tool_calls:
        print(chunk.message.tool_calls)

輸出


[ToolCall(function=Function(name='add_two_numbers', arguments={'a': 3, 'b': 1}))]

JavaScript SDK 使用方式

JavaScript 客戶端(npm i ollama)運作方式類似。定義一個工具架構(schema),然後 ollama.chat() 會串流文字與工具呼叫。

import ollama from 'ollama';

const addTool = {
  type: 'function',
  function: {
    name: 'addTwoNumbers',
    description: 'Add two numbers together',
    parameters: {
      type: 'object',
      required: ['a', 'b'],
      properties: {
        a: {type: 'number', description: 'The first number'},
        b: {type: 'number', description: 'The second number'}
      }
    }
  }
};

async function run(model) {
  const messages = [{role: 'user', content: 'What is 2 plus 3?'}];
  for await (const chunk of await ollama.chat({model, messages, tools: [addTool], stream: true})) {
    if (chunk.message.tool_calls) {
      console.log('Tool call:', chunk.message.tool_calls);
    } else {
      process.stdout.write(chunk.message.content);
    }
  }
}

run('qwen3').catch(console.error);

輸出

Question: What is 2 plus 3?

Tool call: {function: {name: "addTwoNumbers", arguments: {a: 2, b: 3}}}

增量解析器如何運作

背景

早期的 Ollama 版本會緩衝整個模型的輸出,將其解析為 JSON,然後發出工具呼叫。這會阻礙串流,因為工具呼叫可能出現在文字中的任何位置。

增量解析策略

新的解析器會讀取每個模型的模板來識別工具呼叫前綴(例如,特殊 token 或字串)。它可以:

  • 在模型串流 token 時偵測部分前綴。
  • 將一般內容與待處理的工具呼叫分開。
  • 當模型發出不帶預期前綴的原始 JSON 物件時,退回到通用 JSON 偵測。

處理邊緣情況

如果模型重複了先前已進行的工具呼叫,或將呼叫包含在解釋性文字中,解析器的狀態機可以避免重複呼叫。實證測試顯示,格式錯誤或重複的呼叫現在會減少到單次、正確的呼叫。

準確度提升

先前,模型可能會在敘述中重複呼叫時,產生兩個相同的工具呼叫。更新後的解析器會比對前綴並追蹤 JSON 解析狀態,確保只發出一個呼叫。舊版失敗範例:

[TOOL_CALL] [{"name":"get_conditions","arguments":{"city":"Sydney"}}]
... (text) ...
[{"name":"get_conditions","arguments":{"city":"Sydney"}}]
]

現在解析器會回傳單一的 tool_calls 項目。

Model Context Protocol (MCP) 與更大的視窗大小

串流工具呼叫可與 Ollama 的 Model Context Protocol 運作。使用者回報,將上下文視窗(context window)增加到 32k token 或更多,可以同時提升工具偵測的可靠性與生成回答的品質。

透過 cURL 調整上下文視窗

curl -X POST "http://localhost:11434/api/chat" -d '{
  "model": "llama3.2",
  "messages": [{"role": "user", "content": "why is the sky blue?"}],
  "options": {"num_ctx": 32000}
}'

注意:較大的視窗會增加記憶體消耗。

開始使用

  1. 下載最新的 Ollama 版本https://ollama.com/download
  2. 安裝語言特定的 SDKs – Python 使用 pip install -U ollama,JavaScript 使用 npm i ollama
  3. 使用 stream: true 旗標 在 API 呼叫中,並包含一個 tools 陣列來描述您想要模型呼叫的函數。

參考資料

Sources

相關

  • Dispatch
  • Dispatch
  • Dispatch
  • Dispatch
  • Dispatch