[大模型]什么是function calling?
什么是function calling?
大模型的 Function Calling(函数调用)是一种让大语言模型(如 GPT、Claude 等)与外部工具、API 或自定义函数交互的机制。
它的核心目的是让模型能够根据用户的需求,动态调用外部功能来完成更复杂的任务,例如查询实时数据、操作数据库、调用数学工具等。
为什么需要 Function Calling?
大模型本身是“静态”的,它的知识截止于训练数据的时间点,且无法直接访问外部系统(如网络、数据库)。通过 Function Calling,模型可以将用户的自然语言请求转化为结构化的函数调用请求,大模型会在每次回答问题之前先检查可以调用哪些工具,并评估用户的问题是否需要调用这些工具。如果需要,它便会调用相应的工具,并根据工具返回的结果来生成答案。
Function Calling不仅极大地扩展了大模型的应用范围,让大模型可以处理实时数据(天气、股票)、执行计算、操作本地文件等;还在一定程度上解决了模型的“幻觉”问题。
Function Calling 的工作原理
开发者预先定义一系列工具函数,并描述函数的功能和参数。
用户输入自然语言请求后,模型分析意图,判断是否需要调用函数。如果需要,模型会生成一个结构化请求(例如 JSON 格式),包含要调用的函数名称和参数。
开发者收到结构化请求后,执行对应的函数或 API 调用。然后将函数执行结果返回给模型,模型再生成最终的自然语言回复。
代码示例
1. 提前构造API
定义了一个函数 get_weather
用于模拟查询天气信息。该函数接收一个参数 location
,根据传入的城市名称返回相应的天气信息,如果未找到对应城市,则返回“未找到该城市天气”。
def get_weather(location: str) -> str:weather_data = {"北京": {"temperature": 25, "humidity": "40%", "condition": "晴"},"上海": {"temperature": 28, "humidity": "65%", "condition": "多云"}}return json.dumps(weather_data.get(location, "未找到该城市天气"))
2. 定义函数描述(JSON Schema)
定义 JSON Schema用于描述 get_weather
函数的结构和参数要求。函数描述指定了函数的名称、描述以及参数的格式和要求,使得模型能够理解如何调用这个函数。
functions = [{"type": "function","function": {"name": "get_weather","description": "获取指定城市的实时天气信息","parameters": {"type": "object","properties": {"location": {"type": "string", "description": "城市名称,如北京"}},"required": ["location"]}}
}]
3. 用户提问
模拟用户的问题,询问北京今天的天气情况。
初始化了一个消息列表 messages,其中包含了用户的提问,用于构建对话历史。
user_question = "北京今天天气如何?"
messages = [{"role": "user", "content": user_question}]
4. 判断是否需要调用函数
调用 OpenAI 的 GPT-4 模型,传入用户的提问和函数描述。模型会根据提问判断是否需要调用函数 get_weather
来获取答案。参数 tool_choice="auto"
表示让模型自动决定是否调用函数。
response = client.chat.completions.create(model="gpt-4",messages=messages,tools=functions,tool_choice="auto"
)
5. 执行函数调用并获取最终回答
先获取模型的响应消息,并将模型的回复添加到对话历史 messages 中。
assistant_message = response.choices[0].message
messages.append(assistant_message)
然后检查模型的回复是否触发了函数调用。
- 如果触发了函数调用,则提取参数并调用
get_weather
函数获取天气信息,并将函数调用的结果封装为工具消息,添加到对话历史中。然后再次调用 OpenAI 模型,将函数结果作为上下文的一部分,生成最终的回答。 - 如果模型没有触发函数调用,则直接输出模型的回复。
if assistant_message.tool_calls:tool_call = assistant_message.tool_calls[0]if tool_call.function.name == "get_weather":# 提取参数并执行函数args = json.loads(tool_call.function.arguments)weather_result = get_weather(args["location"])# 将函数结果封装为工具消息messages.append({"role": "tool","tool_call_id": tool_call.id,"name": "get_weather","content": weather_result})# 7. 第二次调用大模型生成最终回答final_response = client.chat.completions.create(model="gpt-4",messages=messages)print("最终回复:", final_response.choices[0].message.content)
else:print("直接回复:", assistant_message.content)
完整代码
import os
import json
from openai import OpenAI# 初始化大模型客户端
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))def get_weather(location: str) -> str:weather_data = {"北京": {"temperature": 25, "humidity": "40%", "condition": "晴"},"上海": {"temperature": 28, "humidity": "65%", "condition": "多云"}}return json.dumps(weather_data.get(location, "未找到该城市天气"))functions = [{"type": "function","function": {"name": "get_weather","description": "获取指定城市的实时天气信息","parameters": {"type": "object","properties": {"location": {"type": "string", "description": "城市名称,如北京"}},"required": ["location"]}}
}]user_question = "北京今天天气如何?"
messages = [{"role": "user", "content": user_question}]response = client.chat.completions.create(model="gpt-4",messages=messages,tools=functions,tool_choice="auto"
)assistant_message = response.choices[0].message
messages.append(assistant_message) # 将模型回复加入对话历史if assistant_message.tool_calls:tool_call = assistant_message.tool_calls[0]if tool_call.function.name == "get_weather":# 提取参数并执行函数args = json.loads(tool_call.function.arguments)weather_result = get_weather(args["location"])# 将函数结果封装为工具消息messages.append({"role": "tool","tool_call_id": tool_call.id,"name": "get_weather","content": weather_result})# 7. 第二次调用大模型生成最终回答final_response = client.chat.completions.create(model="gpt-4",messages=messages)print("最终回复:", final_response.choices[0].message.content)
else:print("直接回复:", assistant_message.content)