返回手记列表
技术研究

Function Call是什么?

让LLM与外部世界连接

一、Function Call为何而生?

LLM模型在文本生成、对话、推理等方面能力强大,但存在几个根本性限制:

  1. 实时性缺失:LLM的知识停留在训练数据截止时间,无法获取实时信息(如天气、股价、新闻)。比如:当用户询问"上海现在天气如何?"时,LLM只能基于训练数据中的一般知识回答,无法提供准确、实时的天气信息。
  2. 准确性局限:对于需要精确计算、专业验证的任务(如数学运算、代码执行、数据查询),纯文本生成可能产生事实性错误或“幻觉”。
  3. 行动能力缺失:LLM本质是"思考者"而非"执行者",无法直接操作现实世界(发送邮件、修改数据库、控制设备、调用API等)

二、Function Call的核心思想

1、目标

为LLM赋予"手脚",让它们能够和现实世界建立联系(包括调用外部工具、API和函数),从而突破自身局限,完成更复杂、更准确、更实用的任务。

本质:让LLM在处理用户问题时,能够正确选择工具、发出准确的调用指令、处理执行结果。

  • 正确选择工具:LLM分析用户问题,匹配出能解决用户问题的工具;
  • 发出准确调用指令:能从上下文(用户问题及历史对话)中,提取合适的参数值,生成准确的结构化调用指令;
  • 处理执行结果:基于历史上下文和外部执行返回的结果,生成对用户友好的最终回复。

2、实现

以上工作流程通过精心设计的系统提示词(System Prompt) 来引导LLM实现。这套提示词通常包括: 这套提示词(System Prompt)里至少包括:

  • 角色定义:规定LLM在任务中的身份(如“一个可以调用工具的助手”)。
  • 工具标准化描述:清晰定义可用的工具,包括其名称、作用、参数(名称、类型、描述、是否必需)等。
  • 工具使用示例:提供调用工具的格式示例(通常是一个JSON结构),让LLM学习如何输出。
  • 工作流规范:明确告知LLM在何种情况下应调用工具,以及调用后如何处理结果。

3、核心交互流程

  1. 工具(函数)信息准备:定义函数的名称、作用描述、所需参数及其格式。
  2. 构建提示词:将系统提示词、工具定义与用户查询(Query)组合,形成完整的上下文。
  3. LLM意图理解和决策:应用程序将组合后的提示词发送给LLM。LLM理解用户意图,选择合适的函数,并从查询中提取参数,生成一个结构化的调用指令(通常是JSON格式)。
  4. 函数实际执行:应用程序解析LLM返回的结构化指令,在本地或远程实际调用对应的函数/API,获得执行结果。
  5. 最终回复生成:应用程序将函数执行结果作为新的上下文信息,再次发送给LLM。LLM结合初始问题和执行结果,生成面向用户的自然语言回复。

三、Function Call的技术实现

在实际应用中,主流的大模型API服务提供商(如OpenAI、Google、Anthropic、DeepSeek)都定义了一套实现Function Call的标准接口规范(通常基于JSON Schema)。开发者只需按照该规范描述工具,API服务端会负责后续的复杂处理。

这背后的原因是,开发者通常不直接访问“原生大模型”,而是通过厂商提供的API服务端进行交互。该服务端在收到开发者的请求后,会内部进行提示词工程(包括系统提示词构建、工具描述整合、对话历史管理),生成最终发给底层LLM的提示词,并对LLM的回复进行结构化解析,以标准JSON格式返回给开发者。

我们以OpenAI的API为例,来看一个完整的流程:

一、函数信息准备

  1. 假设有一个获取天气的本地函数:
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”: “晴”
    }
  1. 按照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”]
    }
  }
}

二、构建请求和提示词

  1. 输入用户问题,比如“明天上海的天气怎么样?”。

  2. 【应用程序】按照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”
}
  1. 【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意图理解和决策

  1. 【OpenAI API服务端】将内部构建的提示词发送给底层的【LLM模型】

  2. 【LLM模型】理解提示词,进行推理:识别用户意图是查询天气,匹配到get_current_weather工具,并从问题中提取参数(location应为“上海”)。然后,它按照要求的格式生成文本回复// 要检查函数用的对不对,参数对不对,参数值合不合理

{
  "name": "get_current_weather",
  "arguments": {
    "location": "上海市"
  }
}
  1. 【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": "晴"
}

五、最终回复

  1. 【应用程序】将上一步得到的工具执行结果,作为一条新的消息追加到对话历史中,构造第二轮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` 参数
}
  1. 【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": "晴"}
 
请基于以上信息,用中文生成最终回复:
  1. 【LLM模型】基于完整的对话历史(包括工具执行结果),生成最终的自然语言回复,例如:“上海明天的天气为晴天,气温22摄氏度,天气宜人,适合外出。”

  2. 【OpenAI API服务端】将LLM的回复解析为 [响应体JSON(二轮)],返回给【应用程序】。

{
        "choices":[
                {
                        "message": {
                                "role":"assistant", 
                                "content": "上海明天...适合外出。"
                        }
                }
        ]
}
  1. 【应用程序】从 content 字段中提取文本,通过界面(如聊天框)展示给用户。

总结

Function Call 的实现,本质上是通过一套标准化的接口规范(JSON Schema)和精心设计的提示词工程,来引导和激发LLM利用其预训练中获得的理解、规划和推理能力。它将LLM从一个封闭的文本生成器,转变为一个能够协调外部工具、处理现实世界任务的核心“决策大脑”。对于开发者而言,API服务商封装了最复杂的提示词构建和解析过程,使其只需关注工具的定义和调用执行,大大降低了实现门槛。