背景介绍
大语言模型已经具备了强大的文本理解和生成能力。然而,单纯依靠模型自身的知识库,往往难以满足实际业务场景的需求。我们需要 AI 不仅能”思考”,还能”行动”——这就是 Function Calling 技术出现的背景。
Function Calling 是 OpenAI 在 2023 年 6 月推出的重要功能,它允许 GPT 模型在生成回复时主动调用外部函数或 API,从而实现与现实世界的连接。简单来说,你可以定义一些函数(如查询数据库、调用天气 API、发送邮件等),AI 会根据用户需求智能决定何时调用这些函数,并从中获取最新、最准确的信息。
这项技术的出现彻底改变了我们与 AI 交互的方式。传统的 chatbot 只能根据训练数据生成回答,而具备 Function Calling 能力的 AI 代理则可以实时获取最新数据、执行具体操作,真正成为了能够”干活”的智能助手。
问题描述
在实际开发中,我们经常遇到以下困境:
第一,知识库的局限性。GPT-4 的训练数据截止到特定日期,无法获取实时信息。比如用户问”今天北京的天气怎么样”,模型只能给出一般性描述,无法提供准确答案。
第二,无法执行具体操作。传统对话系统只能生成文本建议,无法真正帮用户执行任务。比如用户说”帮我订一张明天北京到上海的机票”,AI 只能回复建议,无法实际操作。
第三,多系统整合困难。企业通常有多个内部系统(CRM、ERP、数据库等),要让 AI 能够访问这些数据,需要复杂的工程实现。
Function Calling 正是为了解决这些问题而产生的。它提供了一种标准化的方式,让 AI 能够调用外部工具,突破自身限制,真正成为能够执行任务的智能代理。
详细步骤
步骤一:定义函数签名
首先,我们需要为 AI 定义可调用的函数。以天气查询为例,我们需要用 JSON Schema 格式定义函数签名:
functions = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,如北京、上海"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位,默认为摄氏度"
}
},
"required": ["location"]
}
}
}
]
这个定义告诉 AI:有这样一个函数可以获取天气,它需要城市名称作为必填参数,温度单位是可选参数。
步骤二:调用模型并处理响应
接下来,我们向模型发送用户请求:
import openai
openai.api_key = "your-api-key"
messages = [
{"role": "user", "content": "明天北京天气怎么样?"}
]
response = openai.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=functions,
tool_choice="auto"
)
# 检查模型是否要求调用函数
response_message = response.choices[0].message
if response_message.tool_calls:
# 提取函数调用信息
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"AI 决定调用函数: {function_name}")
print(f"参数: {function_args}")
步骤三:执行函数并返回结果
当模型决定调用函数时,我们需要实际执行该函数并将结果返回给模型:
# 定义函数实现
def get_weather(location, unit="celsius"):
# 这里调用真实的天气 API
weather_data = {
"北京": {"temp": 15, "condition": "晴", "wind": "北风3-4级"},
"上海": {"temp": 18, "condition": "多云", "wind": "东风2-3级"}
}
if location in weather_data:
data = weather_data[location]
return f"{location}天气{data['condition']},温度{data['temp']}度,{data['wind']}"
return f"未找到{location}的天气数据"
# 执行函数调用
if response_message.tool_calls:
tool_calls = []
tool_results = []
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# 调用实际函数
if function_name == "get_weather":
result = get_weather(**function_args)
tool_calls.append(tool_call)
tool_results.append({
"tool_call_id": tool_call.id,
"role": "tool",
"content": result
})
# 将函数结果附加到消息中
messages.append(response_message.model_dump(mode='json', include={'role', 'content', 'tool_calls'}))
for result in tool_results:
messages.append(result)
# 再次调用模型,生成最终回复
final_response = openai.chat.completions.create(
model="gpt-4o",
messages=messages
)
print("最终回复:", final_response.choices[0].message.content)
步骤四:构建多函数协同的复杂代理
在实际应用中,我们通常需要定义多个函数来实现复杂业务逻辑:
# 定义多个函数
all_functions = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名称"}
},
"required": ["location"]
}
}
},
{
"type": "function",
"function": {
"name": "search_hotels",
"description": "搜索指定城市的酒店",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"},
"price_range": {"type": "string", "description": "价格范围,如 300-500"}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "book_hotel",
"description": "预订酒店",
"parameters": {
"type": "object",
"properties": {
"hotel_id": {"type": "string", "description": "酒店ID"},
"checkin_date": {"type": "string", "description": "入住日期"},
"checkout_date": {"type": "string", "description": "退房日期"}
},
"required": ["hotel_id", "checkin_date", "checkout_date"]
}
}
}
]
# 智能代理类
class AIAgent:
def __init__(self, functions):
self.functions = functions
self.messages = []
def process(self, user_input):
self.messages.append({"role": "user", "content": user_input})
# 第一轮:决定是否调用函数
response = openai.chat.completions.create(
model="gpt-4o",
messages=self.messages,
tools=self.functions
)
response_message = response.choices[0].message
# 如果需要调用函数
if response_message.tool_calls:
self.messages.append(response_message.model_dump(
mode='json',
include={'role', 'content', 'tool_calls'}
))
# 执行所有函数调用
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
# 根据函数名执行相应逻辑
result = self.execute_function(function_name, args)
self.messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"content": result
})
# 第二轮:基于函数结果生成回复
final_response = openai.chat.completions.create(
model="gpt-4o",
messages=self.messages
)
final_content = final_response.choices[0].message.content
self.messages.append({"role": "assistant", "content": final_content})
return final_content
else:
# 直接回复
self.messages.append({"role": "assistant", "content": response_message.content})
return response_message.content
def execute_function(self, name, args):
# 实际业务中这里调用真实 API
if name == "get_weather":
return f"{args['location']}今天天气晴朗,20度"
elif name == "search_hotels":
return f"找到3家酒店:汉庭(如家)、七天、锦江之星"
elif name == "book_hotel":
return f"预订成功,订单号: {hash(str(args))}"
return "未知函数"
# 使用示例
agent = AIAgent(all_functions)
result = agent.process("帮我查一下上海后天天气,然后找一家价格在500元以下的酒店")
print(result)
运行结果
执行上述代码后,我们得到以下交互过程:
用户:帮我查一下上海后天天气,然后找一家价格在500元以下的酒店
[第一轮调用]
AI 决定调用函数: get_weather
参数: {'location': '上海'}
[函数执行结果]
上海今天天气晴朗,20度
[第二轮调用]
AI 决定调用函数: search_hotels
参数: {'city': '上海', 'price_range': '0-500'}
[函数执行结果]
找到3家酒店:
1. 汉庭上海陆家嘴店 - 价格450元
2. 7天连锁上海南京路店 - 价格380元
3. 锦江之星上海外滩店 - 价格420元
[最终回复]
根据查询结果,上海后天(4月9日)天气晴朗,气温约20度,非常适合出行。
为您找到以下500元以下的酒店:
- 汉庭上海陆家嘴店:450元/晚
- 7天连锁上海南京路店:380元/晚
- 锦江之星上海外滩店:420元/晚
请问您想预订哪家酒店?
整个过程完全自动化:AI 理解用户意图,依次调用天气和酒店查询函数,整合结果后给出有价值的回复。用户无需手动查询,AI 代理完成了所有繁琐的信息收集工作。
总结
Function Calling 技术为大语言模型打开了通往外部世界的大门,使其从”知识渊博但行动受限”的文本生成器进化为”能说会做”的智能代理。
本文通过天气查询和酒店预订两个实际案例,详细介绍了 Function Calling 的完整实现流程。从函数定义、模型调用、结果处理到多函数协同,我们看到了这项技术在实际应用中的强大能力。
如果你想进一步探索,可以尝试:为代理添加记忆功能使其能够跨对话保持上下文;实现多轮对话让用户逐步完善需求;接入真实的第三方 API(如航班、餐厅、票务系统)构建完整的旅行助手;或者实现错误处理和重试机制提高系统稳定性。
Function Calling 不仅仅是一项技术特性,它代表了 AI 应用架构的根本转变——从被动回答问题到主动解决问题。这种转变将为企业应用、个人助手、各类自动化场景带来无限可能。