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)的工作方式类似。定义一个工具架构,然后 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 条目。
模型上下文协议 (MCP) 和更大的窗口
流式工具调用可以与 Ollama 的模型上下文协议 (MCP) 配合使用。用户报告称,将上下文窗口增加到 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}
}
}
注意:更大的窗口会增加内存消耗。
入门指南
- 下载最新的 Ollama 版本 – https://ollama.com/download
- 安装语言特定的 SDK – Python 使用
pip install -U ollama,JavaScript 使用npm i ollama。 - 使用
stream: true标志 在 API 调用中,并包含一个tools数组,用于描述你希望模型调用函数。
参考资料
- 实现流式工具调用的 Pull request:https://github.com/ollama/ollama/pull/10415
Sources
相关
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch