你有没有过这种体验:问AI“纽约现在多少度?”,它张口就编了个数字;让它算个复杂数学题,结果错得离谱还理直气壮?
其实不是AI笨,是它缺了“动手能力”——只会靠自己的知识库瞎猜,不会调用外部工具。而Ollama的“函数调用(Function Call)”功能,就是给AI装上一双“小手”,让它能调用咱们写好的工具(比如查天气的函数、计算器函数),先做事,再回答,再也不瞎蒙了!
今天咱们就从零开始,用最接地气的话、最详细的例子,手把手教你玩透Ollama函数调用。
一、先搭好“玩耍环境”
要玩函数调用,得先把基础环境搭好,就像玩游戏前先装客户端一样。
1. 安装Ollama
- 去Ollama官网(https://ollama.com/)下载对应系统的安装包,一键安装(Windows/Mac/Linux都支持)。
- 安装完打开终端,输入
ollama run qwen3:这个命令会自动下载并启动“通义千问3”模型(这个模型对函数调用支持超友好,新手首选)。 - 验证是否成功:打开浏览器访问
http://localhost:11434,能看到Ollama的页面就说明服务跑起来了。
2. 安装Python SDK(新手首选Python,简单易上手)
终端里输入下面的命令,安装Ollama的Python工具包:
# 用pip安装(最常用)
pip install ollama -U
# 如果你用uv包管理工具,也可以这样装
# uv add ollama
二、先搞懂核心逻辑:用“拍戏”理解函数调用
动手写代码前,先花2分钟搞懂核心概念,用“拍戏”打比方,一看就懂:
- 你(用户):提问的人,比如“纽约现在多少度?”
- AI助手(演员):Ollama跑的模型,负责理解你的问题,判断要不要调用工具、调用哪个工具。
- 工具(道具组):咱们写的函数(比如查气温的
get_temperature),能解决具体问题。 - 对话剧本(messages列表):记录所有“剧情”——你的问题、AI的思考、调用的工具、工具返回的结果,AI全靠这个剧本判断下一步该做啥。
函数调用的核心流程就4步,像拍小短片一样:
- 你把“问题 + 工具清单”交给AI(递剧本);
- AI看完剧本,说“我需要调用查气温工具,查纽约的温度”(出指令);
- 你执行这个工具,得到“22°C”(道具组干活);
- 把工具结果加到剧本里,再交给AI,AI整理出最终回答(演员收尾)。
三、入门篇:让AI查纽约的气温(单次工具调用)
先从最简单的“单次调用”开始,目标:问AI“纽约现在多少度?”,AI调用我们写的气温函数,返回准确答案。
步骤1:写好“气温查询工具”
先写一个模拟的气温查询函数(先不用真实API,重点看逻辑):
from ollama import chat
def get_temperature(city: str) -> str:
"""
模拟查询城市当前气温的工具函数
:param city: 城市名称(比如New York、London)
:return: 该城市的气温,查不到就返回Unknown
"""
# 模拟的气温数据,实际可以换成真实的天气API
temperature_dict = {
"New York": "22°C",
"London": "15°C",
"Tokyo": "18°C",
}
# 查得到就返回气温,查不到返回Unknown
return temperature_dict.get(city, "Unknown")
步骤2:写对话逻辑,让AI调用工具
# 1. 初始化“对话剧本”,先把用户的问题写进去
messages = [{
"role": "user", "content": "What is the temperature in New York?"}]
# 2. 把问题+工具交给AI,让它判断要不要调用工具
# think=True:让AI输出思考过程,方便我们看它咋想的
response = chat(
model="qwen3", # 用咱们刚才启动的qwen3模型
messages=messages, # 对话剧本
tools=[get_temperature], # 给AI的工具清单
think=True
)
# 3. 把AI的回复加到剧本里(剧情更新)
messages.append(response.message)
# 4. 判断AI是否要调用工具
if response.message.tool_calls:
# 这里只处理单个工具调用(新手先看这个)
call = response.message.tool_calls[0]
print(f"AI想调用工具:{call.function.name}")
print(f"调用参数:{call.function.arguments}")
# 5. 执行工具函数,获取结果
result = get_temperature(**call.function.arguments)
print(f"工具返回结果:{result}")
# 6. 把工具结果加到剧本里
messages.append({
"role": "tool", # 角色是“工具”
"tool_name": call.function.name, # 工具名
"content": str(result) # 工具返回的内容
})
# 7. 把更新后的剧本交给AI,让它生成最终回答
final_response = chat(
model="qwen3",
messages=messages,
tools=[get_temperature],
think=True
)
# 8. 打印最终结果
print("\n===== AI最终回答 =====")
print(final_response.message.content)
else:
# 如果AI没调用工具,直接打印它的回答
print(response.message.content)
步骤3:运行代码,看效果
运行后会看到这样的输出(超直观):
AI想调用工具:get_temperature
调用参数:{'city': 'New York'}
工具返回结果:22°C
===== AI最终回答 =====
The current temperature in New York is 22°C.
是不是超简单?AI没有瞎编,而是乖乖调用我们写的函数,返回了准确结果!
四、进阶篇1:一次查多个信息(并行工具调用)
如果问“纽约和伦敦的气温+天气状况分别是啥?”,总不能让AI一个个查吧?这时候就需要“并行调用”——AI一次调用多个工具,效率拉满。
步骤1:新增“天气状况工具”
先加一个查天气状况的函数:
def get_conditions(city: str) -> str:
"""
模拟查询城市当前天气状况的工具函数
:param city: 城市名称
:return: 天气状况(晴/多云/下雨等)
"""
conditions_dict = {
"New York": "Partly cloudy",
"London": "Rainy",
"Tokyo": "Sunny",
}
return conditions_dict.get(city, "Unknown")
步骤2:修改对话逻辑,处理多个工具调用
from ollama import chat
# 1. 初始化剧本,问更复杂的问题
messages = [{
"role": "user", "content": "What are the current weather conditions and temperature in New York and London?"}]
# 2. 把两个工具都交给AI
response = chat(
model="qwen3",
messages=messages,
tools=[get_temperature, get_conditions], # 工具清单加了新成员
think=True
)
messages.append(response.message)
# 3. 处理多个工具调用(重点!)
if response.message.tool_calls:
print("===== AI调用的所有工具 =====")
for call in response.message.tool_calls:
print(f"工具名:{call.function.name},参数:{call.function.arguments}")
# 执行对应的工具函数
if call.function.name == "get_temperature":
result = get_temperature(**call.function.arguments)
elif call.function.name == "get_conditions":
result = get_conditions(**call.function.arguments)
else:
result = "Unknown tool"
print(f"工具返回:{result}\n")
# 把每个工具的结果都加到剧本里
messages.append({
"role": "tool",
"tool_name": call.function.name,
"content": result
})
# 4. 生成最终回答
final_response = chat(
model="qwen3",
messages=messages,
tools=[get_temperature, get_conditions],
think=True
)
print("===== AI最终回答 =====")
print(final_response.message.content)
步骤3:运行效果
===== AI调用的所有工具 =====
工具名:get_temperature,参数:{'city': 'New York'}
工具返回:22°C
工具名:get_conditions,参数:{'city': 'New York'}
工具返回:Partly cloudy
工具名:get_temperature,参数:{'city': 'London'}
工具返回:15°C
工具名:get_conditions,参数:{'city': 'London'}
工具返回:Rainy
===== AI最终回答 =====
New York currently has a temperature of 22°C with partly cloudy conditions, while London has a temperature of 15°C and is rainy.
看!AI一次性调用了4次工具(两个城市×两个工具),把所有信息都收集齐了,再整理成通顺的回答,比一个个问高效多了!
五、进阶篇2:让AI自己“循环解题”(多轮工具调用/智能体循环)
遇到复杂问题,比如“(11434+12341)*412等于多少?”,AI没法一步算出来,这时候需要“多轮调用”——AI先调用加法,得到结果后,再调用乘法,直到算出最终答案,就像个会自己思考的小助手。
步骤1:写加法、乘法工具
from ollama import chat, ChatResponse
def add(a: int, b: int) -> int:
"""两数相加的工具函数"""
return a + b
def multiply(a: int, b: int) -> int:
"""两数相乘的工具函数"""
return a * b
# 把工具存到字典里,方便调用
available_tools = {
"add": add,
"multiply": multiply
}
步骤2:写“智能体循环”逻辑
# 1. 初始化剧本,问复杂数学题
messages = [{
"role": "user", "content": "What is (11434+12341)*412?"}]
# 2. 核心:循环让AI解题,直到它说“不用调用工具了”
while True:
# 每次循环都把最新的剧本交给AI
response: ChatResponse = chat(
model="qwen3",
messages=messages,
tools=available_tools.values(), # 把加法、乘法工具传进去
think=True
)
messages.append(response.message)
# 打印AI的思考过程,看它咋解题的
print(f"===== AI思考过程 =====\n{response.message.thinking}\n")
print(f"===== AI当前回复 =====\n{response.message.content}\n")
# 3. 判断是否需要调用工具
if response.message.tool_calls:
# 执行每个工具调用
for call in response.message.tool_calls:
tool_name = call.function.name
tool_args = call.function.arguments
print(f"调用工具:{tool_name},参数:{tool_args}")
# 执行工具函数
result = available_tools[tool_name](**tool_args)
print(f"工具返回:{result}\n")
# 把结果加到剧本里
messages.append({
"role": "tool",
"tool_name": tool_name,
"content": str(result)
})
else:
# 没有工具调用了,说明解题完成,退出循环
print("===== 解题完成!=====")
break
步骤3:运行效果(超有意思!)
===== AI思考过程 =====
用户现在问的是(11434+12341)*412,我需要先算加法,再算乘法。首先调用add工具计算11434+12341,得到结果后再调用multiply工具乘以412。
===== AI当前回复 =====
I need to calculate 11434 + 12341 first, then multiply the result by 412.
调用工具:add,参数:{'a': 11434, 'b': 12341}
工具返回:23775
===== AI思考过程 =====
现在已经算出11434+12341=23775,接下来需要调用multiply工具计算23775*412。
===== AI当前回复 =====
Now I will calculate 23775 * 412.
调用工具:multiply,参数:{'a': 23775, 'b': 412}
工具返回:9795300
===== AI思考过程 =====
已经算出最终结果是9795300,不需要再调用任何工具了,可以直接回答用户。
===== AI当前回复 =====
(11434+12341)*412 = 9795300
===== 解题完成!=====
是不是超酷?AI像个小学生一样,先算加法再算乘法,一步步把复杂问题拆解开,自己循环解题,完全不用我们干预!
六、高阶篇:实时看到AI的思考过程(流式工具调用)
前面的例子都是“一次性等结果”,流式调用能让你实时看到AI的思考、回复、工具调用,就像看AI“边想边说”,体验更丝滑。
完整代码(带详细注释)
from ollama import chat
def get_temperature(city: str) -> str:
"""还是用这个气温查询函数"""
temperature_dict = {
"New York": "22°C",
"London": "15°C",
}
return temperature_dict.get(city, "Unknown")
# 初始化剧本
messages = [{
"role": "user", "content": "What is the temperature in New York?"}]
# 流式调用的核心循环
while True:
# 开启stream=True,返回流式数据
stream = chat(
model="qwen3",
messages=messages,
tools=[get_temperature],
stream=True, # 关键:开启流式
think=True
)
# 用来聚合流式返回的内容(因为流式是分块返回的)
thinking = ""
content = ""
tool_calls = []
done_thinking = False
# 逐块接收AI的回复
for chunk in stream:
# 聚合思考过程
if chunk.message.thinking:
thinking += chunk.message.thinking
# 实时打印思考过程(不换行,模拟打字效果)
print(chunk.message.thinking, end="", flush=True)
# 聚合回复内容
if chunk.message.content:
if not done_thinking:
done_thinking = True
print("\n") # 思考完换行,打印回复
content += chunk.message.content
print(chunk.message.content, end="", flush=True)
# 聚合工具调用指令
if chunk.message.tool_calls:
tool_calls.extend(chunk.message.tool_calls)
# 把聚合后的内容加到剧本里
if thinking or content or tool_calls:
messages.append({
"role": "assistant",
"thinking": thinking,
"content": content,
"tool_calls": tool_calls
})
# 处理工具调用
if tool_calls:
print("\n") # 换行
for call in tool_calls:
print(f"调用工具:{call.function.name},参数:{call.function.arguments}")
result = get_temperature(**call.function.arguments)
print(f"工具返回:{result}")
messages.append({
"role": "tool",
"tool_name": call.function.name,
"content": result
})
else:
# 没有工具调用,退出循环
break
运行效果(实时输出,超有代入感)
用户问纽约的气温,我需要调用get_temperature工具,参数是city=New York
我需要调用工具查询纽约的气温。
调用工具:get_temperature,参数:{'city': 'New York'}
工具返回:22°C
纽约当前的气温是22°C。
流式调用的关键是“聚合分片内容”——因为AI的思考、回复、工具调用是分小块返回的,必须把这些小块拼起来,AI才能记住完整的上下文。
七、Python专属小技巧:函数自动变工具
Ollama的Python SDK超贴心——不用手动写复杂的JSON工具定义,直接把函数传进去就行!对比一下就知道多方便:
# ❶ 懒人版:直接传函数(推荐!)
response = chat(
model="qwen3",
messages=messages,
tools=[get_temperature], # 直接传函数,SDK自动解析
think=True
)
# ❷ 手动版:写JSON定义(麻烦,不推荐)
# 只有特殊需求时才用这个
custom_tool = [
{
"type": "function",
"function": {
"name": "get_temperature",
"description": "Get the current temperature for a city",
"parameters": {
"type": "object",
"required": ["city"],
"properties": {
"city": {
"type": "string", "description": "The name of the city"}
}
}
}
}
]
response = chat(
model="qwen3",
messages=messages,
tools=custom_tool,
think=True
)
Python SDK会自动读取函数的注释、参数类型,转换成AI能识别的工具定义,省了超多事!现在你已经掌握了Ollama函数调用的核心玩法,快去试试让AI帮你做更多实际的事吧!