引言
Function Calling 是一个允许大型语言模型(如 GPT)在生成文本的过程中调用外部函数或服务的功能。
Function Calling允许我们以 JSON 格式向 LLM 模型描述函数,并使用模型的固有推理能力来决定在生成响应之前是否调用该函数。模型本身不执行函数,而是生成包含函数名称和执行函数所需的参数的 JSON。
function calling 执行原理
现在我们定义提示词像大语言模型问一下当前北京的天气?
因为
LLM大语言模型缺乏实时数据,所以无法回答实时数据这种场景。
我们用SK来测试一下
Console.WriteLine("===>没有设置function calling=<==="); { var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(config.ModelId, endpoint: config.Endpoint, apiKey: config.ApiKey).Build(); var template = "当前北京的天气?"; Console.WriteLine($"User: {template}"); var function = kernel.CreateFunctionFromPrompt(template); var functionResult = await function.InvokeAsync(kernel); Console.WriteLine($"Assistant:{functionResult}"); }
输出:
User: 当前北京的天气? Assistant:对不起,作为一个AI,我无法为你提供实时信息。你可以查看可信的天气应用或网站来获取当前北京的天气。
这时候就需要用到
LLM的Function Calling功能来帮助回答用户的问题
使用 OpenAI API function calling
OpenAI 的 function calling的核心是我们将Prompts 提示词和可用函数列表一起发送给LLM。
OpenAI Chat Completions 接口
{ "tool_choice": "auto", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "我想知道现在北京的天气状况" } ], "tools": [ { "type": "function", "function": { "name": "Get_Weather_For_City", "description": "获取指定城市的天气", "parameters": { "type": "object", "properties": { "cityName": { "type": "string", "description": "城市名" } } } } } ] }
核心参数解释
tool_choice:
这个参数决定了模型是否应该自动选择是否调用函数。值为 "auto" 表示模型将根据情况自动决定是否调用函数。 默认情况下,如果请求中不存在任何函数,则将其设置为“none”,则设置为“auto”。
tools
在 tools 部分定义了一个函数,这个函数可以被 OpenAI 的模型调用。以下是 tools 部分参数的简单解释:
-
type: 指定了这个工具的类型,这里是
"function",表示这是一个函数调用。 -
function: 包含函数的详细信息,是一个对象。
-
name: 函数的名称,这里是
"Get_Weather_For_City",这是调用时使用的函数名。 -
description: 函数的描述,这里是
"获取指定城市的天气",用于说明这个函数的作用。 -
parameters: 定义了函数调用时需要的参数,是一个对象。
-
type: 参数对象的类型,这里是
"object",表示参数是一个对象类型。 -
properties: 包含具体的参数定义,是一个对象,每个属性对应一个参数。
- cityName: 这是一个参数的名称,表示城市名称。
- type: 此参数的类型,这里是
"string",表示参数应该是一个字符串。 - description: 参数的描述,这里是
"城市名",用于解释这个参数的意义。
- type: 此参数的类型,这里是
- cityName: 这是一个参数的名称,表示城市名称。
-
-
这个 tools 部分定义了一个名为 Get_Weather_For_City 的函数,它需要一个名为 cityName 的字符串参数,用于指定想要查询天气的城市。当模型需要调用这个函数时,它将使用这个参数来获取相应的天气信息。
function calling 输出
{ "id": "chatcmpl-9TOuIqnuMirU3BUDluCrHMTlsjz97", "object": "chat.completion", "created": 1716794282, "model": "gpt-4", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_DQU6OKHWyv3HVLyWVjSRqvwZ", "type": "function", "function": { "name": "Get_Weather_For_City", "arguments": "{n "cityName": "北京"n}" } } ] }, "logprobs": null, "finish_reason": "tool_calls" } ], "usage": { "prompt_tokens": 83, "completion_tokens": 20, "total_tokens": 103 }, "system_fingerprint": null }
最核心的方法是tool_calls回参里面返回了我们需要的方法名和一个 json 参数 比如"{n "cityName": "北京"n}"包含了我们的参数和值。
返回函数结果上下文
{ "max_tokens": 3000, "tool_choice": "auto", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "我想知道北京的天气状况" }, { "role": "assistant", "function_call": { "name": "Get_Weather_For_City", "arguments": "{n "cityName": "北京"n}" } }, { "role": "function", "name": "Get_Weather_For_City", "content": "27度,晴朗" } ], "tools": [ { "type": "function", "function": { "name": "Get_Weather_For_City", "description": "获取指定城市的天气", "parameters": { "type": "object", "properties": { "cityName": { "type": "string", "description": "城市名" } } } } }, {
需要把上下文信息和function calling的result回答的信息传给LLM
ToolCall上下文信息
{ "role": "assistant", "function_call": { "name": "Get_Weather_For_City", "arguments": "{n "cityName": "北京"n}" } }
ToolCallResponse
{ "role": "function", "name": "Get_Weather_For_City", "content": "27度,晴朗" }
LLM 输出
{ "id": "chatcmpl-9TRZBqCcRMBYIojuZimio6GOpsTi4", "object": "chat.completion", "created": 1716804505, "model": "gpt-4", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "北京的天气状况是27度,晴朗。" }, "logprobs": null, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 133, "completion_tokens": 19, "total_tokens": 152 }, "system_fingerprint": null }
到现在为止简单的function calling的简单调用已经完成了
具体的流程可以总结为

可以看到function calling跟大预言模型至少有两次交互的的过程
总结
根据文档中的描述,OpenAI的函数调用(function calling)过程可以简化为以下几个步骤,并且可以用一个流程图来表示:

- 用户提出问题。
- 系统接收到问题,并检查是否有可用的函数可以调用。
- 如果有,系统会生成一个工具调用请求(ToolCall),并发送给应用程序。
- 应用程序执行请求的函数,并返回结果。
- 系统将函数的响应(ToolCallResponse)发送回 LLM 模型。
- LLM 模型使用这个响应来生成最终的用户响应。
下面是一个简化的流程图,描述了上述过程:
在这个流程图中:
- A 代表用户。
- B 是用户提出的问题。
- C 是
LLM模型,它检查是否有函数可以调用。 - D 是生成工具调用(
ToolCall)的步骤。 - E 是应用程序,它接收
ToolCall并执行相应的函数。 - F 是应用程序返回的
ToolCallResponse,即函数执行的结果。 - G 是 LLM 模型,它使用
ToolCallResponse来生成用户响应。 - H 是最终接收到用户响应的用户。
这个流程图是基于文档内容的简化表示,实际的系统可能包含更多的细节和步骤。
最后
本章的主要了解function calling及其工作原理的简单介绍。在下一篇博客中,我们 x 学习在Semantic kernel下使用使用function calling。
参考资料