OpenAi 近期推出了一项很酷的新功能,称为“函数调用”。本文将讨论此功能如何通过提供让用户通过自然语言与现有产品进行交互的功能来改进您的现有产品。此外本文将展示一个使用此新功能的Python构建的基本应用程序的示例。
什么是“OpenAi函数调用”?
Open ai 函数调用是一项新功能,让 Openai 模型(例如 GPT-3.r Turbo 和 GPT-4)通过你调用代码中编写的函数,以响应用户的自然语言输入。它的工作原理是告诉模型你的系统上有哪些功能可用,并解释它们的用途和参数。然后OpenAi 可以了解用户的输入何时与这些描述匹配,并进行适当的功能调用。这增加了交互和用户友好性的新水平,允许非技术用户使用简单的提示与技术功能进行交互。
GPT-4 和 GPT-3.5-turbo 更新
下面是稳定版、旧模型和新模型之间的映射。
各型号均已发布后缀为0613的型号,也可以使用评估模型的框架 Evals 来比较和评估这些版本。旧模型中不存在的gpt-3.5-turbo-16k已经出现,它是最大token数量扩大四倍的模型,如下所示。
l gpt-3.5-turbo的最大token数:4096token
l gpt-3.5-turbo-16k的最大token数: 16384token
如下所述,16k 的费用增加了一倍,但代币长度增加了四倍,因此也许可以将其应用于过去在不使用单独框架的情况下难以应用的应用程序。官方公告称16k的token长度足以通过一次请求处理大约20页文本。正如API文档中所述,TRAINING DATA仍然是“Up to Sep 2021”,并且像以前一样使用2021年9月之前的训练数据。
l 具有稳定型号名称的访问将于6月27日自动升级至上述新型号
l 此后,如果明确指定,则可以访问旧模型,但旧模型的访问截止日期为 9 月 13 日。
l 从现在开始访问旧模型将导致请求失败
官方公告还表示,OpenAI希望在未来几周内完成新版本的等待名单,预计将有更多的人能够使用它。
价格
好消息是定价也进行了修改,一些功能现在更便宜.
首先,关于gpt-3.5-turbo的价格修改,成本在输入token和输出token之间划分如下。
虽然计算方法稍微复杂一些,但输入token端的费用便宜了25%。
GPT-4的价格没有变化,GPT-3.5中增加了16k版本,所以整体费用结构如下。
此外,流行的嵌入 API text-embedding-ada-002 的定价已修改如下:
Embeddings API 通常用于创建矢量化数据,因此 75% 降价也很不错了。
我们来尝试一下OpenAi函数调用
1. 设置您的环境
1.1 首先在本地计算机上创建venv
打开终端并创建一个虚拟环境。
python -m venv venv
然后激活它:
venv\Scripts\activate
您现在可以在终端中看到 ( Venv )。
1.2 安装所需的依赖项
Pip install python-dotenv==1.0.0 , open ai == 0.27.7
1.3 我们需要为 OpenAI API 密钥设置一个环境变量
set OPENAI_API_KEY=
2. 一切准备就绪,让我们开始吧!
创建一个名为“ main.py”的文件,我们将在其中编写用于回答问题的函数。
让我们导入所需的依赖项:
import openai
from dotenv import load_dotenv
import os
读取文件
load_dotenv()
openai_key = os.getenv(“OPENAI_API_KEY”)
用下面的代码尝试
model_name = “gpt-3.5-turbo-0613”
question = “Please tell me how to set up an environment with pyenv and pipenv.”
response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
],
)
print(response.choices[0][“message”][“content”].strip())
”pyenv is a Python version control tool that allows you to install multiple Python versions and switch between them. pipenv is a tool that simplifies the creation of virtual environments and package management when used in combination with pyenv.”
我尝试了 gpt-3.5-turbo-0613 和gpt-4–0613,可以确认能正常运行。
这里需要注意的是GPT-4 可能并不总是有效,因为它取决于等待列表的状态。
3. 尝试调用该函数
我将根据下面的 API 文档进行尝试。
首先,定义一个获取天气的函数,这次我们返回固定的天气信息。
import json
def get_current_weather(location, unit=”fahrenheit”):
weather_info = {
”location”: location,
”temperature”: “30”,
”unit”: unit,
”forecast”: [“sunny”, “windy”],
}
return json.dumps(weather_info)
接下来,为了向 OpenAI API 提供有关此功能的信息,创建包含如下描述的数据。
functions=[
{
”name”: “get_current_weather”,
”description”: “Get the current weather at the specified location.”,
”parameters”: {
”type”: “object”,
”properties”: {
”location”: {
”type”: “string”,
”description”: “City names, place names, prefecture names,”,
},
”unit”: {“type”: “string”, “enum”: [“celsius”, “fahrenheit”]},
},
”required”: [“location”],
},
}
]
从这里开始,有必要设计一些使用 OpenAI API 的方法。
使用调用函数时,你可能会多次调用OpenAI API。
第一次是普通查询,但函数的参数给出了先前创建的函数的信息。
(function_call should be “auto”)
model_name = “gpt-3.5-turbo-0613”
question = “Please tell me about the weather in New York, USA”
response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
],
functions=functions,
function_call=”auto”,
)
function_call如果第一个响应的消息包含如下内容,则第二个请求将被抛出。
message = response[“choices”][0][“message”]
message
JSON: {
”role”: “assistant”,
”content”: null,
”function_call”: {
”name”: “get_current_weather”,
”arguments”: “{\n \”location\”: \”\u6771\u4eac\u90fd\u6e2f\u533a\”\n}”
}
此外,此响应还包括作为参数提供的内容,因此你可以根据该信息调用您你自己定义的函数并发送第二个请求。
实现如下所示:
function_name = message[“function_call”][“name”]
arguments = json.loads(message[“function_call”][“arguments”])
function_response = get_current_weather(
location=arguments.get(“location”),
unit=arguments.get(“unit”),
)
second_response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
message,
{
”role”: “function”,
”name”: function_name,
”content”: function_response,
},
],
)
print(second_response.choices[0][“message”][“content”].strip())
The current weather in New York, USA is clear, with a temperature of 30 degrees. It’s windy.
我能够确认我可以根据我自己定义的功能做出响应。
function_call如果不包含一个content(如果像往常一样包含),则可以在第一个响应中获得答案,因此如果您实现如下所示的条件分支,您还可以处理与定义的功能无关的请求:
if message.get(“function_call”):
function_name = message[“function_call”][“name”]
arguments = json.loads(message[“function_call”][“arguments”])
function_response = get_current_weather(
location=arguments.get(“location”),
unit=arguments.get(“unit”),
)
second_response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
message,
{
”role”: “function”,
”name”: function_name,
”content”: function_response,
},
],
)
print(second_response.choices[0][“message”][“content”].strip())
else:
print(response.choices[0][“message”][“content”].strip())
你还可以使用它来发布与天气无关的查询:
model_name = “gpt-3.5-turbo-0613”
question = “Please tell me how to set up an environment with pyenv and pipenv.”
response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
],
functions=functions,
function_call=”auto”,
)
message = response[“choices”][0][“message”]
if message.get(“function_call”):
function_name = message[“function_call”][“name”]
arguments = json.loads(message[“function_call”][“arguments”])
function_response = get_current_weather(
location=arguments.get(“location”),
unit=arguments.get(“unit”),
)
second_response = openai.ChatCompletion.create(
model=model_name,
messages=[
{“role”: “user”, “content”: question},
message,
{
”role”: “function”,
”name”: function_name,
”content”: function_response,
},
],
)
print(second_response.choices[0][“message”][“content”].strip())
else:
print(response.choices[0][“message”][“content”].strip())
Sure!
Pyenv and Pipenv are handy tools for managing Python environments. Here, we will explain how to set up an environment on macOS or Linux.
综上所述:
能够确认的是不使用以这种方式定义的函数也可以完成处理。
对于开发人员来说,这是一个非常好的更新,函数中可以设置多种功能,使用范围非常广泛。