ChatGPT大模型极简应用开发-CH2-深入了解 GPT-4 和 ChatGPT 的 API
文章目录
- 2.1 基本概念
- 2.2 OpenAI API 提供的可用模型
- 2.3 在 OpenAI Playground 中使用 GPT模型
- 2.4 开始使用 OpenAI Python 库
- 2.4.1 OpenAI 访问权限和 API 密钥
- 2.4.2 Hello World 示例程序
- 2.5 使用 GPT-4 和 ChatGPT
- 2.5.1 ChatCompletion 端点的输入选项
- 2.5.2 ChatCompletion 端点的输出格式
- 2.5.3 从文本补全到函数
- 2.6 使用其他文本补全模型
- 2.6.1 Completion 端点的输入选项
- 2.6.2 Completion 端点的输出格式
- 2.7 考虑因素
- 2.7.1 定价和标记限制
- 2.7.2 安全和隐私
- 2.8 其他 OpenAI API 和功能
- 2.8.1 嵌入
- 2.8.2 内容审核模型
- 2.8.3 Whisper 和 DALL · E
2.1 基本概念
OpenAI 提供了多个专为不同任务设计的模型,每个模型都有自己的定价。模型的设计目的——无论是用于补全文本、聊天还是编辑——会影响你如何使用其 API。
提示词就是用户发送给模型的输入文本,用于指导模型执行特定任务。对于 GPT-4 和 ChatGPT 背后的模型,提示词具有聊天格式,输入消息和输出消息存储在列表中。
**标记(token)是词或词的一部分。据粗略估计,100 个标记大约相当于 75 个英语单词。**对 OpenAI 模型的请求是根据所使用的标记数量来定价的,调用 API 的成本取决于输入文本和输出文本的长度。
2.2 OpenAI API 提供的可用模型
通过 OpenAI API,你可以使用 OpenAI 开发的多个模型。这些模型可通过API 作为服务使用(通过直接的 HTTP 调用或提供的库)。每个模型都有自己的功能和定价,且这些模型是专有的,你不能根据自己的需求直接修改模型的代码。但是可以通过 OpenAI API 在特定数据上微调其中的一些模型。
重点介绍以下几个最为重要的模型:
- InstructGPT:这个模型系列可以处理许多单轮文本补全任务。
- text-ada-001 模型只能处理简单的文本补全任务,但它也是 GPT-3 系列中速度最快、价格最便宜的模型。
- text-babbage-001 模型和 text-curie-001 模型稍微强大一些,但也更昂贵。
- text-davinci-003 模型可以出色地执行所有文本补全任务,但它也是 GPT-3 系列 2中最昂贵的。
- 2023年11月下旬, InstructGPT 系列在 2024 年 1 月 4 日统一替换为最新的 gpt-3.5-turbo-instruct 模型。
- ChatGPT:背后的模型是 gpt-3.5-turbo。作为一个聊天模型,它可以将一系列消息作为输入,并生成相应的消息作为输出。
- 在单轮任务中,gpt-3.5-turbo 的性能与 text-davinci-003 相当;由于 gpt-3.5-turbo 的价格只有 text-davinci-003 的十分之一 3,而且两者性能相当,因此建议默认使用它来进行单轮任务。
- gpt-3.5-turbo 模型的上下文窗口大小约为 4000 个标记,这意味着它可以接收约 4000 个标记作为输入。
- gpt-3.5-turbo-16k具有与标准的 gpt-3.5-turbo 模型相同的功能,但上下文窗口大小是后者的 4 倍。
- 截至 2023 年 11 月下旬,最新版本的 text-davinci-003 价格是每千个标记 0.0200 美元,gpt-3.5-turbo-0613 的价格是每千个输入标记 0.0030 美元 + 每千个输出标记 0.0040 美元。
- GPT-4:迄今为止 OpenAI 发布的最大的模型。由于在广泛的文本和图像多模态语料库上进行了训练,因此它精通许多领域。可用于聊天任务和单轮任务,并具有相当高的准确性。
- gpt-4 的上下文窗口大小为 8192 个标记
- gpt-4-32k 的上下文窗口大小为 32 768 个标记。
- 32 768 个标记大约相当于 24 576 个英语单词,即大约 40 页的上下文。
- 截止23年11月,提供了6 个 GPT-4 模型,包括 gpt-4-1106-preview、gpt-4-vision-preview、gpt-4、gpt-4-32k、gpt-4-0613、gpt-4-32k-0613。
开发人员通常希望 LLM 版本具有良好的稳定性和可见性,以便在应用程序中使用它。对于开发人员来说,如果模型的版本在一夜之间发生变化,并且针对相同的输入给出截然不同的回答,那么这样的模型使用起来很困难。为此,OpenAI 提供了这些模型的静态快照版本。在撰写时上述模型最新的静态快照版本分别是
- gpt-3.5-turbo-0613
- gpt-3.5-turbo-16k-0613
- gpt-4-0613
- gpt-4-32k-0613
2.3 在 OpenAI Playground 中使用 GPT模型
OpenAI Playground 是一个基于 Web 的平台。可以使用它直接测试OpenAI 提供的语言模型,而无须编写代码。在 OpenAI Playground 上,可以编写提示词,选择模型,并轻松查看模型生成的输出。
访问 OpenAI Playground 的步骤如下:
-
访问 OpenAI 主页,然后依次单击 Developers → Overview。
-
如果已经拥有一个账户但未登录,请单击屏幕右上方的 Log in。如果还没有 OpenAI 账户,那么你需要创建账户才能使用 Playground和 OpenAI 的大部分功能。请注意,由于 Playground 和 API 是收费的,因此在注册账户时需要提供支付方式。
-
登录后,将在网页的顶部看到加入 Playground 的链接。单击该链接,应该会看到图 2-2 所示的内容。界面中的主要空白处用于输入消息。编写完消息后,单击 Submit 按钮以生成输出。在图 2-2 所示的示例中,我们编写消息“As Descartes said,I think therefore”(正如笛卡儿所说,我思故),然后单击 Submit 按钮。模型用“I am”(我在)补全了文本。每次单击 Submit 按钮时,OpenAI 都会收取相应的费用。
界面的底部和右侧有许多选项。从底部开始在 Submit 按钮右侧的是撤销按钮(在图中标记为 A),用于删除最后生成的文本。在本例中,它将删除“I am”。接下来是重新生成按钮(在图中标记为 B),用于重新生成刚刚删除的文本。再往后是历史按钮(在图中标记为 C),它会给出过去 30 天内的所有请求。一旦进入历史菜单,你就可以出于隐私原因轻松地删除请求。右侧的选项面板提供与界面和所选模型相关的各种设置。
截至 2023 年 11 月下旬,OpenAI Playground 聊天模式可用的模型包括
- gpt-3.5-turbo
- gpt-3.5-turbo-0301
- gpt-3.5-turbo-0613
- gpt-3.5-turbo-1106
- gpt-3.5-turbo-16k
- gpt-3.5-turbo-16k-0613
图 2-3 展示了在聊天模式下使用 Playground 的示例。界面左侧是系统面板(在图中标记为 E)。在这里,你可以描述聊天系统的行为方式。比如,在图 2-3 中,要求它成为一个喜欢猫的有用助手。我们还要求它只谈论猫,并给出简短的回答。根据设置的这些参数所生成的对话显示在界面中央。
Playground 还提供了编辑模式。如图 2-4 所示,在这种模式下,你提供一些文本(在图中标记为 I)和指令(在图中标记为 J),模型将尝试修改文本。在图 2-4 所示的例子中,我们给出了一段描述一个年轻男子要去旅行的文本。同时,我们指示模型将文本中的主人公更改为一位年长的女士。可以看到,结果(在图中标记为 K)符合指令。
界面顶部有一个加载预设项的下拉列表(在图中标记为 N)和 4 个按钮。在图 2-2 中,使用 LLM 来补全句子,但是通过使用适当的提示词,我们也可以让模型执行特定的任务。图 2-5 显示了模型可以执行的常见任务。
2.4 开始使用 OpenAI Python 库
OpenAI 将 GPT-4 和 ChatGPT 作为服务提供。这意味着用户无法直接访问模型代码,也无法在自己的服务器上运行这些模型。OpenAI 负责部署和运行其模型,只要用户拥有 OpenAI 账户和 API 密钥,就可以调用这些模型。
2.4.1 OpenAI 访问权限和 API 密钥
OpenAI 要求你必须拥有 API 密钥才能使用其服务。此密钥有两个用途:
- 它赋予你调用 API 方法的权利;
- 它将你的 API 调用与你的账户关联,用于计费。
进入 API 密钥页面后,请单击“Create new secret key”(创建新密钥)并复制密钥。该密钥是以 sk- 开头的一长串字符。一旦获得了密钥,最好将其导出为环境变量。这样一来,应用程序就能够在不直接将密钥写入代码的情况下使用它。
对于Linux或macOS
# 设置当前会话的环境变量 OPENAI_API_KEY
export OPENAI_API_KEY=sk-(...)
# 检查是否设置了环境变量
echo $OPENAI_API_KEY
对于 Windows:
# 设置当前会话的环境变量 OPENAI_API_KEY
set OPENAI_API_KEY=sk-(...)
# 检查是否设置了环境变量
echo %OPENAI_API_KEY%
以上代码片段将设置一个环境变量,并使密钥对从同一 shell 会话启动的其他进程可用。Linux 用户还可以直接将这段代码添加到 .bashrc 文件中。
2.4.2 Hello World 示例程序
使用 pip 安装 Python 库:
pip install openai
接下来,在 Python 中访问 OpenAI API:
import openai
# 调用 OpenAI 的 ChatCompletion 端点
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Hello World!"}],
)
# 提取响应
print(response["choices"][0]["message"]["content"])
你将看到以下输出:
Hello there! How may I assist you today?
上述代码没有明确提到密钥,原因是已经设置到环境变量中了。也可以使用以下代码将Openai模块只想包含密钥的文件:
# 从文件加载 API 密钥
openai.api_key_path = <PATH>
# 加载 API 密钥
openai.api_key = os.getenv("OPENAI_API_KEY")
建议遵循环境变量使用惯例:将密钥存储在一个 .env
文件中,并在.gitignore
文件中将其从源代码控制中移除。在 Python 中,可以运行load_dotenv
函数来加载环境变量并导入 openai 库:
from dotenv import load_dotenv
load_dotenv()
import openai
2.5 使用 GPT-4 和 ChatGPT
import openai
# 对 GPT-3.5 Turbo 来说,端点是 ChatCompletion
openai.ChatCompletion.create(
# 对 GPT-3.5 Turbo 来说,模型是 gpt-3.5-turbo
model="gpt-3.5-turbo",
# 消息列表形式的对话
messages=[{"role": "system", "content": "You are a helpful teacher."},
{
"role": "user",
"content": "Are there other measures than time \
complexity for an algorithm?",
},
{
"role": "assistant",
"content": "Yes, there are other measures besides time \
complexity for an algorithm, such as space complexity.",
},
{"role": "user", "content": "What is it?"},
],
)
输入消息中的对话格式允许模型进行多轮对话。请注意,API 不会在其上下文中存储先前的消息。问题“What is it?”问的是先前的回答,这只有在模型知道答案的情况下才有意义。每次模拟聊天会话时,都必须发送整段对话。
2.5.1 ChatCompletion 端点的输入选项
1 主要参数
ChatCompletion 端点及其 create 方法有多个输入参数,但只有两个是必需的model
, message
系统消息帮助设置助手的行为,用户消息相当于是用户在 ChatGPT 网页界面中键入的问题或句子。
助手消息有两个作用:要么存储先前的回复以继续对话,要么设置为指令,以提供所需行为的示例。由于模型没有任何关于历史请求的“记忆”,因此存储先前的消息对于给出对话上下文和提供所有相关信息是必要的。
2 对话长度和标记数量
对话的总长度与标记的总数相关。这将影响以下方面。
- 成本:定价基于标记计算。
- 时间:标记越多,响应所需的时间就越长——最长可能需要几分钟。
- 模型是否工作:标记总数必须小于模型的上限。
通过管理消息的长度来控制输入标记的数量,并通过 max_tokens 参数来控制输出标记的数量。
OpenAI 提供了一个名为 tiktoken 的库,让开发人员能够计算文本字符串中的标记数。强烈建议在调用端点之前使用此库来估算成本。
3 可选参数
截至 2023 年 11 月下旬,ChatCompletion 可选参数已更新,其中 functions 和function_call 已被弃用;新增了 tools、response_format、seed 等参数。请以最新的OpenAI 文档为准
2.5.2 ChatCompletion 端点的输出格式
以下是 Hello World 示例程序的完整响应:
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "Hello there! How may I assist you today?",
"role": "assistant",
},
}
],
"created": 1681134595,
"id": "chatcmpl-73mC3tbOlMNHGci3gyy9nAxIP2vsU",
"model": "gpt-3.5-turbo",
"object": "chat.completion",
"usage": {"completion_tokens": 10, "prompt_tokens": 11, "total_tokens": 21},
}
如果将参数 n 设置为大于 1,那么你会发现 prompt_tokens的值不会改变,但 completion_tokens 的值将大致变为原来的 n倍。
2.5.3 从文本补全到函数
可以使用函数定义将自然语言转换为 API 调用或数据库查询,从文本中提取结构化数据,并通过调用外部工具来创建聊天机器人,而无须创建复杂的提示词以确保模型以特定的格式回答可以由代码解析的问题。函数定义需要作为函数对象数组传递。
假设有一个包含公司产品相关信息的数据库。可以定义一个函数来执行对这个数据库的搜索:
# 示例函数
def find_product(sql_query):
# 执行查询
results = [
{"name": "pen", "color": "blue", "price": 1.99},
{"name": "pen", "color": "red", "price": 1.78},
]
return results
接下来定义函数的规范:
# 函数定义
functions = [
{
"name": "find_product",
"description": "Get a list of products from a sql query",
"parameters": {
"type": "object",
"properties": {
"sql_query": { "type": "string", "description": "A SQL query", }
},
"required": ["sql_query"],
},
}
]
可以创建一个对话,并调用 ChatCompletion 端点:
# 示例问题
user_question = "I need the top 2 products where the price is less than 2.00"
messages = [{"role": "user", "content": user_question}]
# 使用函数定义调用 ChatCompletion 端点
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613", messages=messages,
functions=functions
)
response_message = response["choices"][0]["message"]
messages.append(response_message)
使用该模型创建一个查询,打印function_call
对象可以得到如下结果:
"function_call": {
"name": "find_product",
"arguments": '{\n "sql_query": "SELECT * FROM products \
WHERE price < 2.00 ORDER BY price ASC LIMIT 2"\n}',
}
接下来,执行该函数并继续对话:
# 调用函数
function_args = json.loads(
response_message["function_call"]["arguments"]
)
products = find_product(function_args.get("sql_query"))
# 将函数的响应附加到消息中
messages.append(
{
"role": "function",
"name": function_name,
"content": json.dumps(products),
}
)
# 将函数的响应格式化为自然语言
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=messages,
)
最后,提取最终的响应并得到以下内容:
The top 2 products where the price is less than $2.00 are:
1. Pen (Blue) - Price: $1.99
2. Pen (Red) - Price: $1.78
这个简单的例子演示了如何利用函数来构建一个解决方案,使最终用户能够以自然语言与数据库进行交互。你可以使用函数定义将模型限制为按照你希望的方式进行回答,并将其响应集成到应用程序中。
2.6 使用其他文本补全模型
文本补全和聊天补全之间有一个重要的区别:两者都能生成文本,但聊天补全更适用于对话。
与 ChatCompletion 端点相比,Completion 端点的主要区别在于提示词的格式。基于聊天的模型必须采用对话格式,而基于补全的模型只采用单独的提示词:
# 调用 Completion 端点
response = openai.Completion.create(
model="text-davinci-003", prompt="Hello World!"
)
# 提取响应
print(response["choices"][0]["text"])
以上代码片段将输出类似于以下内容的结果:
"\n\nIt's a pleasure to meet you. I'm new to the world"
2.6.1 Completion 端点的输入选项
1 主要的输入参数
2 对话长度和标记数量
与聊天模型一样,文本补全模型的费用也取决于输入和输出。对于输入,必须仔细管理 prompt 参数的长度;如果使用 suffix
参数,还需要管理它的长度。对于输出,使用 max_tokens
参数。
3 可选参数
由于这些参数的用法与 ChatCompletion 端点中的相同,因此这里不再赘述。可以使用 temperature
或 n
来控制输出,使用max_tokens
来控制成本,并使用 stream
在长文本补全场景中提供更好的用户体验。
2.6.2 Completion 端点的输出格式
以下是 Hello World 示例程序使用 davinci 模型后的输出示例。
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"logprobs": null,
"text": "<br />\n\nHi there! It's great to see you.",}
],
"created": 1681883111,
"id": "cmpl-76uutuZiSxOyzaFboxBnaatGINMLT",
"model": "text-davinci-003",
"object": "text_completion",
"usage": {"completion_tokens": 15, "prompt_tokens": 3,
"total_tokens": 18},
}
这个输出与我们使用聊天模型得到的非常相似。唯一的区别在于choices 对象:不再有属性 content 和 role,而有一个包含模型生成文本的属性 text。
2.7 考虑因素
在广泛使用 API 之前,应该考虑两个重要因素:成本和数据隐私。
2.7.1 定价和标记限制
OpenAI 在 Pricing 页面上列出了模型的定价,价格是实时更新的,这里是以2023年11月价格为例:
以下是要注意的一些点:
- 文本补全任务中,text-davinci-003 模型的定价是 gpt-3.5-turbo 模型的 10 倍以上。由于 gpt-3.5-turbo 模型也可用于单轮文本补全任务,并且对于这类任务,两个模型的准确性相当,因此建议使用 gpt-3.5-turbo 模型。
- gpt-3.5-turbo 模型比 gpt-4 模型便宜。对于许多基本任务来说,二者的表现大同小异。然而,在复杂的推理场景中,gpt-4 模型远优于任何先前的模型。
- 与 text-davinci-003 模型不同,聊天系列的模型对于输入和输出有不同的定价策略。
- gpt-4 模型的上下文窗口大小大约是 gpt-3.5-turbo 模型的两倍,gpt-4-32k 模型甚至达到 32 768 个标记,这大概相当于 25 000 个英语单词。gpt-4 模型可以实现长篇内容创作、高级对话,以及文档搜索和分析,但用户需要相应地付出更高的成本。
2.7.2 安全和隐私
OpenAI 声称不会将作为模型输入的数据用于重新训练,除非用户选择这样做。然而,用户的输入将被保留 30 天,用于监控和使用合规检查目的。这意味着 OpenAI 员工和专门的第三方承包商可能会访问你的 API 数据。
请勿通过 OpenAI 的端点发送个人信息或密码等敏感数据。我们建议你查阅 OpenAI 的数据使用规则以获取最新信息,因为使用规则可能会有所变动。如果你是国际用户,请注意,你的个人信息和输入的数据可能会从你的所在地传输到 OpenAI 在美国的服务器上。这可能在法律方面对你的应用程序创建产生影响。
2.8 其他 OpenAI API 和功能
除了文本补全功能,OpenAI 用户还可以使用其他一些功能。如果想深入了解所有 API,那么请查看 OpenAI 的 API reference 页面。
2.8.1 嵌入
由于模型依赖数学函数,因此它需要数值输入来处理信息。然而,许多元素(如单词和标记)本质上并不是数值。为了解决这个问题,用嵌入将这些概念转化为数值向量。通过以数值方式表示这些概念,嵌入使计算机能够更高效地处理它们之间的关系。在某些情况下,嵌入能力可能很有用。OpenAI 提供了一个可以将文本转换为数值向量的模型。嵌入端点让开发人员能够获取输入文本的向量表示,然后将该向量表示用作其他 ML 模型和 NLP 算法的输入。
使用其最新模型text-embedding-ada-002
即可完成
result = openai.Embedding.create(
model="text-embedding-ada-002", input="your text"
)
# 获得嵌入
result['data']['embedding']
嵌入是一个向量,即一个浮点数数组。
嵌入的原则是以某种方式有意义地表示文本字符串,以捕捉其语义相似性。以下是嵌入的一些用例。
- 搜索:按查询字符串的相关性给结果排序。
- 推荐:推荐包含与查询字符串相关的文本字符串的文章。
- 聚类:按相似度为字符串分组。
- 异常检测:找到一个与其他字符串无关的文本字符串。
在 ML 领域,特别是在处理语言模型时,会遇到嵌入这一重要概念。嵌入将分类数据(比如标记,通常是单个词或多组标记)转换为数值格式,具体而言是实数向量。这种转换是必要的,因为 ML 模型依赖数值数据,其直接处理分类数据的能力欠佳。
可以将嵌入视为一种复杂的语言解释器,它将丰富的词汇和句子转换为 ML 模型能够轻松理解的数值语言。嵌入的一个突出特点是,它能够保持语义相似性。也就是说,含义相近的词语或短语在数值空间中更接近。
在信息检索过程中,这是基础属性。信息检索过程涉及从大型数据集中提取相关信息。鉴于其捕捉语义相似性的方式,嵌入是执行这类操作的绝佳工具。LLM 广泛使用嵌入。通常,这些模型处理约 512 维的嵌入,从而提供语言数据的高维数值表示。这些维度很深,使得模型能够区分各种复杂的模式。因此,它们在各种语言任务上表现出色,包括翻译、摘要和生成与人类对话相似的文本回应。
嵌入具有这样的属性:如果两段文本具有相似的含义,那么它们的向量表示也是相似的
为清晰起见,本例将嵌入显示为具有两个维度,但实际上,嵌入通常具有更高的维度,比如 512 维。
2.8.2 内容审核模型
OpenAI 提供了一个模型来检查内容是否符合使用规则。如果构建了一个应用程序,其中用户输入将被用作提示词,那么这个模型将非常有用:可以根据内容审核端点的结果过滤查询。该模型提供分类功能,让你能够针对以下类别搜索内容:
- hate:内容涉及对种族、性别、民族、宗教、国籍、残疾或种姓的仇恨。
- hate/threatening: 内容涉及对特定群体的暴力行为或严重伤害。
- self-harm:内容涉及自残行为。
- sexual:内容涉及性行为(性教育和与健康相关的内容除外)。
- sexual/minors:内容同上,但涉及 18 岁以下的未成年人。
- violence:内容涉及崇尚暴力或者给他人造成痛苦或羞辱。
- violence/graphic:内容涉及详尽地描绘死亡、暴力或严重的身体伤害
内容审核模型的端点是 openai.Moderation.create
,它只有两个可用参数:model
和 input
。有两个内容审核模型可供选择,默认模型是text-moderation-latest
,它会随时间自动更新,以确保你始终使用最准确的模型。另一个模型是 text-moderation-stable
。在更新此模型之前,OpenAI 会通知你。text-moderation-stable
模型的准确性可能稍低于 text-moderation-latest
模型。
以下是使用 text-moderation-latest
模型的示例:
import openai
# 调用 Moderation 端点,并使用 text-moderation-latest 模型
response = openai.Moderation.create(
model="text-moderation-latest",
input="I want to kill my neighbor.",
)
以下是内容审核结果:
{
"id": "modr-7AftIJg7L5jqGIsbc7NutObH4j0Ig",
"model": "text-moderation-004",
"results": [
{
"categories": {
"hate": false,
"hate/threatening": false,
"self-harm": false,
"sexual": false,
"sexual/minors": false,
"violence": true,
"violence/graphic": false,
},
"category_scores": {
"hate": 0.0400671623647213,
"hate/threatening": 3.671687863970874e-06,
"self-harm": 1.3143378509994363e-06,
"sexual": 5.508050548996835e-07,
"sexual/minors": 1.1862029225540027e-07,
"violence": 0.9461417198181152,
"violence/graphic": 1.463699845771771e-06,
},
"flagged": true,
}
],
}
2.8.3 Whisper 和 DALL · E
Whisper 是用于语音识别的多功能模型。它是在大型音频数据集上训练的,也是可以执行多语言语音识别、语音翻译和语言识别的多任务模型。OpenAI Whisper 项目的 GitHub 页面提供了一个开源版本。
2021 年 1 月,OpenAI 推出了 DALL · E,这是一个能够根据自然语言描述创造逼真图像和艺术作品的 AI 系统。DALL · E 2 在技术上进一步提升了分辨率和输入文本理解能力,并添加了新功能。这两个版本的 DALL· E 是通过对图像及其文本描述进行训练的 Transformer 模型创建的。