在学习 LLM 的过程中,你应该经常听到 function call 和 tool。那么 function call 和 tool 是什么?有什么作用呢?本文就来详细给你介绍下。
如何让 AI 模型学会"做"而不仅仅是"说"
函数调用使大型语言模型(LLMs)能够根据用户的输入与外部工具、API 和函数进行交互。LLM 不仅生成文本,还能判断需要采取特定动作,然后请求外部函数执行该动作。
函数调用允许用户使用自然语言与复杂系统进行交互,而 LLM 则处理基本功能的执行。因此,LLM 能够专注于解决实际问题,而不仅仅是生成文本。
例如,如果用户询问天气,模型可以调用天气 API 获取实时数据,而不是仅仅生成一个普通的回答。如果有下雨的可能,它还可以提醒你带上雨伞。
函数调用过程解析
让我们详细分解一下函数调用在 LLM 内部是如何工作的:

- 用户查询:该过程开始于用户提问或请求操作(例如,"今天的天气怎么样?"或"检查产品 X 是否有货。");
- LLM 处理 :LLM 分析查询,并识别到它需要外部数据或某个操作来满足请求。例如:
- 如果用户询问天气,LLM 会识别出需要提取实时数据;
- 如果用户想要库存详情,它会触发数据库查找。
- 函数调用决策 :LLM 决定执行函数调用,这可能是:
- API 调用:连接到外部服务(例如,天气 API 以获取实时天气预报);
- 自定义函数:访问内部工具或数据库(例如,库存访问以检查库存水平)。
- 数据检索:函数获取所需的数据显示(例如,从天气 API 获取温度,从仓库数据库获取产品可用性);
- 数据整合:检索到的数据被发送回 LLM,LLM 处理这些数据并为用户生成上下文准确的响应。
函数调用的用例及如何提升性能
通过能够调用函数,LLM 不仅局限于文本生成。它可以执行诸如检索实时数据或与其他软件交互等操作。这使得该模型在实际应用中更具动态性和实用性。例如:
- 提供最新信息:如果模型可以通过函数调用获取最新信息,它可以提供更准确的答案。例如,关于当前事件的提问,如果没有函数调用,可能导致信息过时,但通过访问新闻 API,答案可以保持更新;
- 自动化重复任务:函数调用可以自动化重复的任务。例如,如果用户想要安排一个会议,LLM 可以调用日历 API 自动添加事件。这节省了时间,并减少了手动输入的需要;
- 与其他服务连接:LLMs 可以成为更大生态系统的一部分,与数据库、客户关系管理(CRM)或其他企业系统连接。这使它们在专业环境中更具多功能性;
- 处理复杂工作流程:LLM 不仅可以回答单个问题,它可以协调多个函数调用以解决多步骤问题。例如,通过检查航班可用性、预订酒店和租车来计划一次旅行;
- 在不重训练的情况下更新信息:随着新功能或 API 的出现,LLM 可以在不重训练整个模型的情况下更新以使用它们。这保持了系统的最新状态,且只需最小的努力。
函数调用示例
如果你使用过 ChatGPT 市场的任何 GPT,你可能已经看到或体验过函数调用。这些 GPT 执行自定义函数,让人们创建像待办事项列表构建器、提示增强器、应用连接器以及问答机器人等特定工具。ChatGPT 内置的"任务"功能也使用了这一点------它可以在特定时间触发函数设置提醒。
Claude 的模型上下文协议(MCP)做了类似的事情。通过 Sonnet 3.5,Claude 可以激活工具,如 Brave Search 以获取网页结果,访问其图记忆系统或链接到其他应用。两个系统展示了AI如何使用这些"函数调用"将其核心智能与现实世界工具连接起来。
支持函数调用的AI模型
注意:有时函数调用也被称为工具调用。这两个术语是相同的。
一些支持函数调用的模型包括:
- GPT-4o
- Llama 3.2
- 谷歌的Gemini 2.0 Flash Experimental
- Claude
- Mistral
- Cohere的Command R
虽然还有更多模型,但这些模型通过 API 很容易访问,还有一些可以通过 Ollama 本地使用并且是开源的。
函数调用实例 --- 创建一个使用 Ollama 的 AI 搜索工具
我们将构建一个搜索工具,Llama 3.2 将充当决策者------它首先分析查询是否需要实时网页数据。如果需要,它会通过 Ollama 的工具调用 API 自动触发 web_search 工具。这模仿了 Perplexity 如何平衡 AI 推理与实时数据。
我们需要的:
- Ollama:在本地托管 Llama 3.2 模型。
- Python 3.11+:支持 async/await 模式(对性能至关重要)。
- SearchAPI:免费层支持每日 100 个请求。(链接)
让我们开始定义该函数:
注意:Ollama 将其称为工具调用,这与函数调用是相同的。这将是我们的工具,其参数基于通过 SearchAPI 返回的答案。
python
# 定义我们的搜索工具
search_tool = {
'type': 'function',
'function': {
'name': 'web_search',
'description': '搜索有关主题的当前信息',
'parameters': {
'type': 'object',
'required': ['query'],
'properties': {
'query': {
'type': 'string',
'description': '要查找的搜索查询'
}
}
}
}
}
此代码将在我们的文件 main.py 中使用,我们将调用 Ollama 并尝试决定是否调用工具。我们的项目结构大致如下:
plain
project_folder/
├── .env
├── search_tool.py
└── main.py
文件说明:
- .env:将 API 密钥与代码隔离。
- search_tool.py:分离搜索逻辑以实现可重用性。
- main.py:专注于协调(模型 ↔ 工具交互)。
可以通过以下命令安装相关的包:
bash
pip install ollama python-dotenv requests
主要工作流程(main.py)
- AsyncClient:处理并发工具调用而不阻塞。
- 工具响应处理:检查响应中的 tool_calls。
- 错误传播:直接将身份验证/搜索错误返回给用户。
main.py 的代码如下:
python
import asyncio
from ollama import AsyncClient
from search_tool import web_search, extract_content
async def process_query(query: str) -> str:
client = AsyncClient()
# 定义我们的搜索工具
search_tool = {
'type': 'function',
'function': {
'name': 'web_search',
'description': '搜索有关主题的当前信息',
'parameters': {
'type': 'object',
'required': ['query'],
'properties': {
'query': {
'type': 'string',
'description': '要查找的搜索查询'
}
}
}
}
}
# 首先,让Ollama决定是否需要搜索
response = await client.chat(
'llama3.2',
messages=[{
'role': 'user',
'content': f'回答这个问题:{query}'
}],
tools=[search_tool]
)
# 初始化可用功能
available_functions = {
'web_search': web_search
}
# 检查Ollama是否要使用搜索工具
if response.message.tool_calls:
print("正在搜索网络...")
for tool in response.message.tool_calls:
if function_to_call := available_functions.get(tool.function.name):
# 调用搜索函数
search_results = function_to_call(**tool.function.arguments)
if "error" in search_results:
if search_results["error"] == "authentication_failed":
return "身份验证失败。请检查你的API密钥。"
return f"搜索错误:{search_results['error']}"
# 提取相关内容
content = extract_content(search_results)
if not content:
return "未找到相关信息。"
# 将搜索结果添加到对话中
messages = [
{'role': 'user', 'content': query},
response.message,
{
'role': 'tool',
'name': tool.function.name,
'content': content
}
]
# 结合搜索结果从Ollama获取最终响应
final_response = await client.chat(
'llama3.2',
messages=messages
)
return final_response.message.content
# 如果没有工具调用,直接返回响应
return response.message.content
async def main():
question = input("你想知道什么?")
print("\n正在处理你的问题...")
answer = await process_query(question)
print("\n答案:")
print(answer)
if __name__ == "__main__":
asyncio.run(main())
现在,让我们专注于创建我们的 search_tool,在这里我们需要保存函数以进行API调用并获取结果。代码基于此处提供的模式。
搜索实现(search_tool.py)
- API错误处理:显式捕获 401/429。
- 内容提取 :
- 优先考虑 nswer_box(精选摘要)。
- 限制为 4 个结果以避免令牌溢出。
search_tool.py 的代码如下:
python
import os
import requests
from typing import Dict, Any
from dotenv import load_dotenv
# 使用SearchAPI搜索网络
def web_search(query: str) -> Dict[Any, Any]:
load_dotenv()
api_key = os.getenv('SEARCH_API_KEY')
if not api_key:
return {"error": "环境变量中未找到API密钥"}
url = "https://www.searchapi.io/api/v1/search"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
params = {
"engine": "google_news",
"q": query,
"num": 5
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 401:
return {"error": "无效的API密钥或身份验证失败"}
elif response.status_code == 429:
return {"error": "超出速率限制"}
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
error_msg = f"获取搜索结果时出错:{e}"
if hasattr(e, 'response') and e.response:
try:
error_details = e.response.json()
error_msg = f"{error_msg} - {error_details.get('message', '')}"
except:
pass
return {"error": error_msg}
# 从搜索结果中提取相关内容,因为API返回了大量数据
def extract_content(search_results: dict) -> str:
content = []
if "organic_results" in search_results:
for result in search_results["organic_results"][:4]: # 取前4个结果
if "snippet" in result:
content.append(result["snippet"])
if "answer_box" in search_results and search_results["answer_box"]:
if "answer" in search_results["answer_box"]:
content.insert(0, search_results["answer_box"]["answer"])
return "\n\n".join(content)
创建一个.env文件并在其中存储你的API密钥。获取你的SearchAPI密钥在这里:
plain
SEARCH_API_KEY=ABCD123
然后执行以下命令测试整个流程:
bash
python main.py
接下来,你可以询问任何问题,Ollama 将决定是否使用工具:


结论
函数调用让 AI 模型不仅仅是对话------它们现在可以触发动作,如拉取实时天气数据或检查库存,通过连接到工具和 API。它们不再提供普通答案,而是通过将自然语言与软件和现实世界数据相结合来解决实际问题。这使得聊天机器人变成动态助手,能够自动化任务、获取更新以及与其他系统交互,重新塑造我们在日常需求中使用AI的方式。