Function Call是什么?
让LLM与外部世界连接
一、Function Call为何而生?
LLM模型在文本生成、对话、推理等方面能力强大,但存在几个根本性限制:
- 实时性缺失:LLM的知识停留在训练数据截止时间,无法获取实时信息(如天气、股价、新闻)。比如:当用户询问"上海现在天气如何?"时,LLM只能基于训练数据中的一般知识回答,无法提供准确、实时的天气信息。
- 准确性局限:对于需要精确计算、专业验证的任务(如数学运算、代码执行、数据查询),纯文本生成可能产生事实性错误或“幻觉”。
- 行动能力缺失:LLM本质是"思考者"而非"执行者",无法直接操作现实世界(发送邮件、修改数据库、控制设备、调用API等)
二、Function Call的核心思想
1、目标
为LLM赋予"手脚",让它们能够和现实世界建立联系(包括调用外部工具、API和函数),从而突破自身局限,完成更复杂、更准确、更实用的任务。
本质:让LLM在处理用户问题时,能够正确选择工具、发出准确的调用指令、处理执行结果。
- 正确选择工具:LLM分析用户问题,匹配出能解决用户问题的工具;
- 发出准确调用指令:能从上下文(用户问题及历史对话)中,提取合适的参数值,生成准确的结构化调用指令;
- 处理执行结果:基于历史上下文和外部执行返回的结果,生成对用户友好的最终回复。
2、实现
以上工作流程通过精心设计的系统提示词(System Prompt) 来引导LLM实现。这套提示词通常包括: 这套提示词(System Prompt)里至少包括:
- 角色定义:规定LLM在任务中的身份(如“一个可以调用工具的助手”)。
- 工具标准化描述:清晰定义可用的工具,包括其名称、作用、参数(名称、类型、描述、是否必需)等。
- 工具使用示例:提供调用工具的格式示例(通常是一个JSON结构),让LLM学习如何输出。
- 工作流规范:明确告知LLM在何种情况下应调用工具,以及调用后如何处理结果。
3、核心交互流程
- 工具(函数)信息准备:定义函数的名称、作用描述、所需参数及其格式。
- 构建提示词:将系统提示词、工具定义与用户查询(Query)组合,形成完整的上下文。
- LLM意图理解和决策:应用程序将组合后的提示词发送给LLM。LLM理解用户意图,选择合适的函数,并从查询中提取参数,生成一个结构化的调用指令(通常是JSON格式)。
- 函数实际执行:应用程序解析LLM返回的结构化指令,在本地或远程实际调用对应的函数/API,获得执行结果。
- 最终回复生成:应用程序将函数执行结果作为新的上下文信息,再次发送给LLM。LLM结合初始问题和执行结果,生成面向用户的自然语言回复。
三、Function Call的技术实现
在实际应用中,主流的大模型API服务提供商(如OpenAI、Google、Anthropic、DeepSeek)都定义了一套实现Function Call的标准接口规范(通常基于JSON Schema)。开发者只需按照该规范描述工具,API服务端会负责后续的复杂处理。
这背后的原因是,开发者通常不直接访问“原生大模型”,而是通过厂商提供的API服务端进行交互。该服务端在收到开发者的请求后,会内部进行提示词工程(包括系统提示词构建、工具描述整合、对话历史管理),生成最终发给底层LLM的提示词,并对LLM的回复进行结构化解析,以标准JSON格式返回给开发者。
我们以OpenAI的API为例,来看一个完整的流程:
一、函数信息准备
- 假设有一个获取天气的本地函数:
def get_current_weather(location: str, unit: str = “celsius”):
# 这里应调用真实的天气API,此处为示例直接返回
# 假设真实API返回:{“location”: “上海”, “temperature”: 22, “unit”: “celsius”, “forecast”: “晴”}
return {
“location”: location,
“temperature”: 22,
“unit”: unit,
“forecast”: “晴”
}
- 按照OpenAI的tools参数规范,对该函数进行结构化描述:
{
“type”: “function”,
“function”: {
“name”: “get_current_weather”,
“description”: “获取指定城市的当前天气信息”,
“parameters”: {
“type”: “object”,
“properties”: {
“location”: {
“type”: “string”,
“description”: “城市名称,例如‘北京市’或‘Shanghai’”
},
“unit”: {
“type”: “string”,
“enum”: [“celsius”, “fahrenheit”],
“description”: “温度单位”
}
},
“required”: [“location”]
}
}
}
二、构建请求和提示词
-
输入用户问题,比如“明天上海的天气怎么样?”。
-
【应用程序】按照OpenAI API规范,构造一个包含messages(对话历史)和tools**(函数定义)**的 [请求体JSON],发送给【OpenAI API服务端】。
{
“model”: “gpt-4o”,
“messages”: [
{
“role”: “user”,
“content”: “明天上海的天气怎么样?”
}
],
“tools”: [
{
“type”: “function”,
“function”: {
“name”: “get_current_weather”,
“description”: “获取指定城市的当前天气信息”,
“parameters”: {
“type”: “object”,
“properties”: {
“location”: {
“type”: “string”,
“description”: “城市名称,例如‘北京市’或‘Shanghai’”
},
“unit”: {
“type”: “string”,
“enum”: [“celsius”, “fahrenheit”],
“description”: “温度单位”
}
},
“required”: [“location”]
}
}
}
],
“tool_choice”: “auto”
}
- 【OpenAI API服务端】收到 [请求体JSON] 后,内部会根据模型、tools参数和对话历史,动态生成一个纯文本提示词(Prompt)。这个提示词会包含系统指令、工具描述、对话历史和输出格式要求,对开发者透明。其内容在概念上类似于:
你是一个有帮助的AI助手。你可以使用工具来获取信息。以下是你可以使用的工具:
【工具定义】
工具名称:get_current_weather
功能:获取指定城市的当前天气信息
参数:
- location: string类型,必需。城市名称,如"北京市"或"Shanghai"
- unit: string类型,可选。温度单位,只能是"celsius"或"fahrenheit"
【输出格式要求】
如果需要调用工具,请严格按以下JSON格式回复:
{
"tool_calls": [
{
"id": "生成一个唯一ID",
"type": "function",
"function": {
"name": "工具名称",
"arguments": "{\\"参数名\\":\\"参数值\\"}"
}
}
]
}
如果不需要调用工具,直接回复自然语言。
【当前对话】
用户:明天上海的天气怎么样?
助手:
三、LLM意图理解和决策
-
【OpenAI API服务端】将内部构建的提示词发送给底层的【LLM模型】
-
【LLM模型】理解提示词,进行推理:识别用户意图是查询天气,匹配到get_current_weather工具,并从问题中提取参数(location应为“上海”)。然后,它按照要求的格式生成文本回复// 要检查函数用的对不对,参数对不对,参数值合不合理
{
"name": "get_current_weather",
"arguments": {
"location": "上海市"
}
}
- 【OpenAI API服务端】将LLM生成的文本回复,解析为结构化的响应体JSON,返回给【应用程序】
{
“id”: “chatcmpl-xxx”,
“object”: “chat.completion”,
“choices”: [
{
“index”: 0,
“message”: {
“role”: “assistant”,
“content”: null,
“tool_calls”: [
{
“id”: “call_abc123”,
“type”: “function”,
“function”: {
“name”: “get_current_weather”,
“arguments”: “{\\”location\\”: \\”上海\\”}”
}
}
]
},
“finish_reason”: “tool_calls”
}
]
}
四、函数实际执行
【应用程序】从 [响应体JSON] 的tool_calls 中解析出函数名和参数(name: get_current_weather, arguments: {“location”: “上海”}),然后在本地或自己的服务器上调用对应的get_current_weather(“上海”)函数,获得执行结果。
{
"location": "上海市",
"temperature": 22,
"unit": "celsius",
"forecast": "晴"
}
五、最终回复
- 【应用程序】将上一步得到的工具执行结果,作为一条新的消息追加到对话历史中,构造第二轮API请求。关键是tool_call_id必须与第一轮响应中的ID匹配。
{
“model”: “gpt-4o”,
“messages”: [
// 第一轮:用户原始问题
{ “role”: “user”, “content”: “明天上海的天气怎么样?” },
// 第一轮:模型返回的工具调用请求
{
“role”: “assistant”,
“content”: null,
“tool_calls”: [
{
“id”: “call_abc123”,
“type”: “function”,
“function”: {
“name”: “get_current_weather”,
“arguments”: “{\\”location\\”: \\”上海\\”}”
}
}
]
},
// 第二轮新增:应用程序提供的工具执行结果
{
“role”: “tool”,
“content”: “{\\”location\\”: \\”上海市\\”, \\”temperature\\”: 22, \\”unit\\”: \\”celsius\\”, \\”forecast\\”: \\”晴\\”}”,
“tool_call_id”: “call_abc123”
}
]
// 注意:此轮请求通常无需再次传递 `tools` 参数
}
- 【OpenAI API服务端】收到 [请求体JSON(二轮)] 后, 再次内部构建提示词,这次会包含工具返回的结果。可能是这样的:
【系统指令】
你是一个有帮助的AI助手。请基于用户的提问和工具返回的结果,生成友好、准确的最终回复。
【工具执行结果】
工具 get_current_weather 返回:
{
"location": "上海市",
"temperature": 22,
"unit": "celsius",
"forecast": "晴"
}
【完整对话历史】
用户:明天上海的天气怎么样?
助手:[已调用工具 get_current_weather 查询上海天气]
工具 (get_current_weather):{"location": "上海市", "temperature": 22, "unit": "celsius", "forecast": "晴"}
请基于以上信息,用中文生成最终回复:
-
【LLM模型】基于完整的对话历史(包括工具执行结果),生成最终的自然语言回复,例如:“上海明天的天气为晴天,气温22摄氏度,天气宜人,适合外出。”
-
【OpenAI API服务端】将LLM的回复解析为 [响应体JSON(二轮)],返回给【应用程序】。
{
"choices":[
{
"message": {
"role":"assistant",
"content": "上海明天...适合外出。"
}
}
]
}
- 【应用程序】从 content 字段中提取文本,通过界面(如聊天框)展示给用户。
总结
Function Call 的实现,本质上是通过一套标准化的接口规范(JSON Schema)和精心设计的提示词工程,来引导和激发LLM利用其预训练中获得的理解、规划和推理能力。它将LLM从一个封闭的文本生成器,转变为一个能够协调外部工具、处理现实世界任务的核心“决策大脑”。对于开发者而言,API服务商封装了最复杂的提示词构建和解析过程,使其只需关注工具的定义和调用执行,大大降低了实现门槛。