Function Call 原理详解
FunctionCalling是大语言模型(如GPT-3.5、GPT-4)的重要特性,允许模型智能调用外部工具或API,扩展其能力以完成实时数据获取、计算、数据库交互等任务。
前言
Function Calling(函数调用)是大语言模型(如GPT-3.5、GPT-4)的一个重要特性,它允许模型根据用户的需求,智能地决定是否需要调用外部工具或API,并生成符合要求的参数。这极大地扩展了模型的能力,使其能够执行一些它本身无法完成的任务,比如获取实时数据、执行计算、与数据库交互等。
一、Function Calling 是什么?—— 核心概念
简单来说,Function Calling 是让大语言模型根据用户的需求,智能地决定是否需要调用外部工具(函数),并自动生成正确的调用参数。
一个生动的比喻:
-
没有 Function Calling:你向一个无所不知但被关在房间里的专家提问。他能告诉你理论,但无法实际操作。
-
有 Function Calling:这位专家现在有了一个对讲机,可以指挥外面的助手(各种 API 和工具)去执行具体任务,比如查天气、订机票、分析数据,然后把结果告诉他,他再综合这些信息给你一个完整的答案。
技术定义: 它是一种特殊的提示工程技术,通过向模型描述可用的工具(函数),模型能够输出结构化的 JSON 数据,表明它希望调用哪个函数以及传递什么参数。
二、Function Calling的流程
Function Calling通常包含以下步骤:
-
定义函数:首先,开发者需要定义一系列可供模型调用的函数,包括函数名称、描述、参数(参数类型、描述等)。这些定义会作为系统提示的一部分提供给模型。
-
用户查询:用户提出一个自然语言请求。
-
模型决策:模型根据用户请求和可用的函数定义,决定是否需要调用函数。如果不需要,则直接生成自然语言回复;如果需要,则选择要调用的函数并生成参数。
-
执行函数:系统收到模型生成的函数调用请求后,在本地执行相应的函数(或调用API)。
-
结果返回:将函数执行的结果返回给模型。
-
生成回复:模型根据函数返回的结果,生成最终的自然语言回复给用户。
Function Calling 的整个过程是一个典型的“人机协同”循环,下图清晰地展示了其工作流:

这个过程的核心在于 步骤 1 中的函数定义。它通常是一个 JSON 对象,详细描述了函数的“身份”和“能力”,例如:
{
"name": "get_current_weather", // 函数名
"description": "Get the current weather in a given location", // 描述,模型据此判断是否调用
"parameters": { // 参数定义,模型据此生成参数
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
三、Function Calling的参数定义
大语言模型本身有三大局限,Function Calling 正好解决了它们:
| 局限 | Function Calling 的解决方案 |
|---|---|
| 知识截止 | 模型不知道最新信息(如今天天气、股价)。→ 可以调用 实时数据 API(天气、新闻、金融)。 |
| 无法执行操作 | 模型不能直接操作外部系统(如发邮件、查数据库)。→ 可以调用 外部服务 API(发送邮件、查询数据库)。 |
| 纯文本输出 | 模型输出是非结构化的自然语言。→ 可以强制模型输出 结构化数据(如 JSON),便于程序处理。 |
在OpenAI的API中,Function Calling是通过在聊天完成API(Chat Completions API)中传递functions参数来实现的。每个函数的定义包括:
-
name:函数名,模型通过这个名字来指定要调用的函数。 -
description:函数描述,模型通过描述来理解函数的作用。 -
parameters:函数的参数,是一个JSON Schema对象,定义了参数的类型、属性、是否必需等。
例如,一个获取天气函数的定义如下:
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The unit of temperature"
}
},
"required": ["location"]
}
}
四、API调用示例
以下是一个使用OpenAI Chat Completions API进行Function Calling的示例:
第一步:定义函数并发送用户请求
我们向API发送一个请求,包括用户消息和函数定义。
import openai
import json
# 定义函数列表
functions = [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The unit of temperature"
}
},
"required": ["location"]
}
}
]
# 用户消息
messages = [
{"role": "user", "content": "What's the weather like in Boston?"}
]
# 调用API
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=messages,
functions=functions,
function_call="auto" # 让模型决定是否调用函数
)
第二步:模型响应
模型的响应可能如下:
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-3.5-turbo-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"function_call": {
"name": "get_current_weather",
"arguments": "{\"location\": \"Boston, MA\"}"
}
},
"finish_reason": "function_call"
}
]
}
注意,模型返回了一个function_call对象,其中包含了要调用的函数名和参数。
第三步:执行函数
我们根据模型返回的函数名和参数,在本地执行函数(或调用外部API)。
# 假设我们有一个函数get_current_weather
def get_current_weather(location, unit="fahrenheit"):
# 这里应该是真实的天气API调用,这里用模拟数据
weather_info = {
"location": location,
"temperature": "72",
"unit": unit,
"forecast": ["sunny", "windy"]
}
return json.dumps(weather_info)
# 从模型响应中提取函数名和参数
function_name = response.choices[0].message.function_call.name
function_args = json.loads(response.choices[0].message.function_call.arguments)
# 调用函数
function_response = get_current_weather(
location=function_args.get("location"),
unit=function_args.get("unit")
)
第四步:将函数结果返回给模型
我们将函数执行的结果作为新的消息追加到对话中,并再次调用API,让模型生成对用户的回复。
# 将函数调用的响应追加到消息列表
messages.append(response.choices[0].message) # 添加助理的函数调用消息
messages.append(
{
"role": "function",
"name": function_name,
"content": function_response,
}
)
# 再次调用API,让模型生成回复
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=messages,
)
# 这次模型会根据函数返回的结果生成自然语言回复
print(second_response.choices[0].message.content)
最终的回复可能是:“The weather in Boston is 72 degrees fahrenheit and it's sunny and windy.”
五、一个完整的代码示例(Python 伪代码)
假设我们有一个获取天气的函数。
# 1. 定义可用的函数列表(这是给模型看的“工具手册”)
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定城市的当前天气情况",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名称,例如:北京"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "description": "温度单位"}
},
"required": ["location"]
}
}
}
]
# 2. 用户请求
user_query = "今天北京热吗?需要穿什么衣服?"
# 3. 第一次调用模型:让模型判断是否需要调用函数
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": user_query}],
tools=tools, # 关键:把“工具手册”传给模型
tool_choice="auto", # 让模型自己决定是否调用工具
)
response_message = response.choices[0].message
# 4. 检查模型是否想调用函数
if response_message.tool_calls:
# 5. 解析模型生成的函数调用请求
tool_call = response_message.tool_calls[0]
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments) # 模型生成的参数:{"location": "北京", "unit": "celsius"}
# 6. 在开发者自己的代码中执行真实的函数
if function_name == "get_current_weather":
weather_data = get_current_weather(
location=function_args.get("location"),
unit=function_args.get("unit")
) # 假设返回:{"temperature": 28, "condition": "晴朗"}
# 7. 第二次调用模型:把函数执行结果返回给模型,让它生成最终回答
second_response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": user_query},
response_message, # 模型上次的回复(包含函数调用意图)
{
"role": "tool", # 关键:以“tool”的角色返回结果
"content": json.dumps(weather_data),
"tool_call_id": tool_call.id
}
],
)
# 8. 输出最终答案
print(second_response.choices[0].message.content)
# 输出:"北京今天天气晴朗,气温28摄氏度。天气较热,建议穿短袖、短裤等夏装,并注意防晒。"
else:
# 如果模型认为不需要调用函数,直接输出回答
print(response_message.content)
六、Function Calling的注意事项
-
模型不会执行函数:模型只负责生成函数名和参数,实际执行由开发者负责。
-
安全性:由于模型生成的参数是文本,需要谨慎处理,避免注入攻击。确保对参数进行验证。
-
错误处理:函数执行可能会失败,需要有自己的错误处理机制,并将错误信息返回给模型,让模型决定如何回复用户。
-
成本:Function Calling会增加API调用的次数(有时需要两次调用:一次决定调用函数,一次根据函数结果生成回复),从而增加成本。
七、Function Calling 的核心优势
-
可靠性:模型输出的是结构化的 JSON,而非自由文本,极大降低了解析的难度和错误率。
-
安全性:模型只负责“思考”和“规划”,真正的操作(如发送邮件、支付)由开发者的安全代码执行,控制权在开发者手中。
-
能力扩展:理论上,可以为模型连接任何可通过 API 调用的服务,使其能力无限扩展。
-
标准化:OpenAI 等公司将其标准化,使得不同应用和工具之间的集成变得简单。
八、主要应用场景
| 场景 | 说明 |
|---|---|
| RAG(检索增强生成) | Function Calling 是实现 RAG 的优雅方式。可以将“向量数据库检索”定义为一个函数,模型在需要时调用它来获取相关知识。 |
| AI Agent(智能代理) | Agent 的核心就是“思考-行动”循环。Function Calling 为模型提供了“行动”的手段,使其能完成复杂多步任务。 |
| 自然语言接口 | 将任何软件系统(CRM、数据库、智能家居)的 API 封装成函数,用户就可以用自然语言与之交互。 |
| 数据提取与标准化 | 从非结构化的文本(如用户邮件、文档)中提取出结构化的信息(如订单号、客户需求),填入预定义的 JSON 格式。 |
总结
Function Calling是大语言模型与外部工具连接的关键桥梁,它使模型能够突破纯文本生成的限制,实现更复杂的功能。通过精心设计的函数描述和参数定义,可以引导模型在合适的场景下调用正确的函数,从而完成各种任务。
Function Calling 的本质是赋予大语言模型“动手能力”。它将模型的“大脑”(强大的理解和推理能力)与外部工具的“手脚”(执行能力)完美结合,是构建真正实用、强大的 AI 应用的核心技术之一。 它标志着大模型从“对话式AI”向“行动式AI”的范式转变。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)