心情随笔
OpenAI Function call实践
00 分钟
2024-3-29
2024-3-29
type
status
date
slug
summary
tags
category
icon
password
😀
在与模型的聊天过程中,可以通过描述函数作用及相关参数,让模型智能地选择调用一个或多个函数。可以使模型能力得到扩充,如发送电子邮件、在线发布内容、购买等流程。

一、前置准备

我们结合实际的应用场景,构建一个用户询问ChatGPT,在用户提问的所在地信息的天气情况,模型结合外部API的能力,回答给用户实时切真实的数据。
 
  • OpenAI API Key
  • 使用 IP API 获取用户的位置接口
  • 使用 Open Meteo API 获取当前天气数据
 

getLocation函数

获取当前用户位置,使用 IP API 获取用户的位置,IP API 返回一堆关于您的位置的数据,包括您的纬度和经度。

getCurrentWeather函数

将上面的纬度和经度用作参数。它使用 Open Meteo API 获取当前天气数据,如下所示:

二、给模型描述提供的函数功能

为了让 OpenAI 理解这些函数的用途,我们需要使用特定的模式来描述它们。我们将创建一个名为的数组 functionDefinitions ,该数组包含每个函数一个对象。每个对象将有三个键: name 、 description 和 parameters

设置message数组

我们还需要定义一个 messages 数组。这将跟踪我们的应用程序和 OpenAI 之间的所有消息来回。
数组中的第一个对象应始终将 role 属性设置为 "system" ,这告诉 OpenAI 这就是我们希望它的行为方式。

创建代理函数

现在,我们已准备好构建应用的逻辑,该逻辑存在于 agent 函数中。它是异步的,并接受一个参数 userInput 。
我们首先将 userInput 推送到 messages 数组。这一次,我们将 role 设置为 "user" ,以便 OpenAI 知道这是来自用户的输入。

通过简单的输入运行我们的应用程序

让我们尝试使用需要函数调用才能给出合适回复的输入来运行。 agent
当我们运行上面的代码时,我们看到 OpenAI 的响应注销到控制台,如下所示:
此响应告诉我们,我们应该调用我们的函数之一,因为它包含以下键: finish:_reason: "function_call" 函数的名称可以在键中找到,该 response.choices[0].message.function_call.name 键设置为 "getLocation" 。

将 OpenAI 响应转换为函数调用

现在我们已经将函数的名称转换为字符串,我们需要将其转换为函数调用。为了帮助我们解决这个问题,我们将把两个函数都收集到一个名为 availableFunctions
这很方便,因为我们可以通过括号表示法和从 OpenAI 返回的字符串来访问该 getLocation 函数,如下所示: availableFunctions["getLocation"] .
我们还抓住了 OpenAI 希望我们传递到函数中的任何论点: message.function_call.arguments .但是,对于第一个函数调用,我们不需要任何参数。
如果我们使用相同的输入 ( "Where am I located right now?" ) 再次运行代码,我们将看到一个 functionResponse 对象,里面填充了用户现在所处位置的位置。就我而言,那是北京。
getCurrentWeather 调用时候生成的链接如下:api.open-meteo.com/v1/forecast…
我们将此数据添加到数组中的新项中 messages ,其中我们还指定了我们调用的函数的名称。
请注意,设置为 role "function" 。这告诉 OpenAI,该参数包含函数调用的结果, content 而不是用户的输入。
此时,我们需要使用这个更新 messages 的数组向 OpenAI 发送一个新请求。但是,我们不想对新的函数调用进行硬编码,因为我们的代理可能需要在自身和 GPT 之间来回切换几次,直到它为用户找到最终答案。
这可以通过几种不同的方式解决,例如递归、while 循环或 for 循环。为了简单起见,我们将使用一个好的旧 for 循环。

创建循环

在 agent 函数的顶部,我们将创建一个循环,让我们最多可以运行整个过程五次。
如果我们从 GPT 返回 finish_reason: "function_call" ,我们只会将函数调用的结果推送到数组并 messages 跳转到循环的下一次迭代,从而触发新的请求。
如果我们回来 finish_reason: "stop" ,那么 GPT 已经找到了合适的答案,所以我们将返回函数并取消循环。
如果我们在五次迭代中没有看到 a finish_reason: "stop" ,我们将返回一条消息,说我们找不到合适的答案。

运行最终应用

在这一点上,我们准备尝试我们的应用程序!我会要求程序根据我的位置和当前的天气建议一些活动。
以下是我们在控制台中看到的内容(格式化以使其更易于阅读):
notion image
如果我们在引擎盖下达到顶峰,并在循环的每次迭代中注销 response.choices[0].message ,我们会看到 GPT 在得出答案之前已经指示我们使用这两个函数。
现在,您已经使用 OpenAI 函数和 Node.js SDK 构建了 AI 代理!如果您正在寻找额外的挑战,请考虑增强此应用程序。例如,您可以添加一个函数,用于获取有关用户所在位置的事件和活动的最新信息。
Complete code 完整代码