目录
Ollama 工具调用教程:使用工具扩展模型能力
语言模型不知道今天的天气、你的数据库里有什么,也不擅长精确计算。工具调用(tool calling,也叫 function calling)让模型可以“请你的程序帮忙执行某个函数”,再根据结果回答。
只有支持工具的模型才能使用此功能。在 ollama.com 的模型页面上会标注 tools,例如 qwen3、llama3.1、gpt-oss、mistral。
工作流程
1. 你:问题 + 可用工具的说明 ──────────▶ 模型
2. 模型:「请调用 get_weather(city="台北")」◀──
3. 你的程序执行 get_weather("台北") → "24°C,多云"
4. 你:把结果发回 ─────────────────────▶ 模型
5. 模型:「台北现在 24 度、多云,建议带件薄外套。」
模型本身不会执行任何程序,它只是决定要调用哪个工具、传入什么参数。真正执行的是你的程序,所以你可以完全控制它能做什么。
Python 示例
ollama Python 包可以直接把 Python 函数作为工具传入,它会自动根据函数的类型标注和 docstring 生成工具说明:
from ollama import chat
def get_weather(city: str) -> str:
"""
查询城市当前的天气。
Args:
city: 城市名称,例如“台北”
Returns:
天气描述
"""
fake_data = {"台北": "24°C,多云", "高雄": "29°C,晴天"}
return fake_data.get(city, "没有查询到数据")
tools = {"get_weather": get_weather}
messages = [{"role": "user", "content": "台北和高雄现在天气如何?"}]
response = chat(model="qwen3:8b", messages=messages, tools=[get_weather])
messages.append(response.message)
# 模型可能一次要求调用多个工具
for call in response.message.tool_calls or []:
fn = tools[call.function.name]
result = fn(**call.function.arguments)
print(f"调用 {call.function.name}({call.function.arguments}) → {result}")
messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})
final = chat(model="qwen3:8b", messages=messages)
print(final.message.content)
要点:
- 把模型的响应(包括
tool_calls)添加回messages。 - 将每个工具的执行结果以
role: "tool"添加回去。 - 再调用一次
chat,模型就会根据结果回答。
让模型自行决定调用次数
有些问题需要连续调用多个工具,例如“先查汇率,再计算金额”。可以用循环处理,直到模型不再要求调用工具:
from ollama import chat
def get_exchange_rate(currency: str) -> float:
"""获取 1 单位外币兑换新台币的汇率。currency 例如 USD、JPY。"""
return {"USD": 32.1, "JPY": 0.21}.get(currency.upper(), 0.0)
def multiply(a: float, b: float) -> float:
"""计算 a 乘以 b。"""
return a * b
tools = {f.__name__: f for f in [get_exchange_rate, multiply]}
messages = [{"role": "user", "content": "350 美元大约是多少新台币?"}]
while True:
response = chat(model="qwen3:8b", messages=messages, tools=list(tools.values()))
messages.append(response.message)
if not response.message.tool_calls:
break
for call in response.message.tool_calls:
result = tools[call.function.name](**call.function.arguments)
messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})
print(response.message.content)
实际使用时,请设置最多调用次数,避免模型陷入无限循环。
使用 REST API 定义工具
不使用 Python 包时,可以通过 JSON Schema 描述工具:
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{ "role": "user", "content": "台北天气如何?" }],
"stream": false,
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询城市当前的天气",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "城市名称" }
},
"required": ["city"]
}
}
}]
}'
响应中的 message.tool_calls:
"tool_calls": [
{ "function": { "name": "get_weather", "arguments": { "city": "台北" } } }
]
执行后,将结果以 {"role": "tool", "tool_name": "get_weather", "content": "24°C,多云"} 的形式添加到 messages,再发送一次。
编写清晰的工具说明
模型完全根据名称和说明来判断何时使用工具、如何填写参数:
- 函数名称要清楚表达用途:
search_orders比query1好。 - 在说明中写清楚什么情况下该使用、参数格式和示例。
- 参数尽量少,类型要明确;能使用枚举(enum)就使用枚举。
- 工具数量不要太多,小模型面对十几个工具时容易选错。
安全注意事项
- 模型会根据用户输入触发工具。如果用户可以控制输入,就等于用户可以间接调用你的工具。
- 不要提供可执行任意代码、任意 SQL 或删除数据的工具。
- 付款、发邮件、删除等有副作用的操作,应在执行前让用户确认。
- 检查模型提供的参数,不要直接信任。
更新于 2026年10月12日