# 开始

## OpenAI 官方文档中文版

| [OpenAI 中文在线官方文档](https://openaidoc.kaimingwan.com/) | [OpenAI 官方文档](https://platform.openai.com/docs/introduction) |
| ---------------------------------------------------- | ------------------------------------------------------------ |

## 介绍

我翻译了OpenAI官方文档，旨在帮助读者更好地理解和学习OpenAI。然而，我承认我的翻译可能存在不准确或不严谨的地方，因此文中可能会有一些错误或瑕疵。如果您发现了任何问题，欢迎提交PR（Pull Request），帮助完善文档。感谢您的支持。

## 翻译进度

出于学习目的，我仅翻译了开始和指南部分的内容，针对剩余内容有兴趣翻译的朋友可以自行提交翻译内容。

* 开始(已完成)
  * 介绍(已完成)
  * 快速开始(已完成)
  * 库(已完成)
  * 模型(已完成)
  * 引导(已完成)
  * 数据使用政策(已完成)
  * 使用政策(已完成)
* 指南
  * 文本完成(已完成)
  * 代码完成(内测)(已完成)
  * 聊天完成(已完成)
  * 图片生成(已完成)
  * 微调(已完成)
  * 嵌入(已完成)
  * 语音转文本(已完成)
  * 内容审核(已完成)
  * 速率限制(已完成)
  * 错误码
  * 安全最佳实践
  * 生产应用最佳实践
* API参考
  * 介绍
  * 身份认证
  * 创建请求
  * 模型
  * 完成
  * 聊天
  * 编辑
  * 图片
  * 嵌入
  * 音频
  * 文件
  * 微调
  * 内容审核
  * 引擎
  * 参数详情

## 翻译技巧

可以使用ChatGPT或者[**bob-plugin-openai-translator**](https://github.com/yetone/bob-plugin-openai-translator)协助翻译，速度是很快的，质量也不错。

## 如何贡献

如需贡献内容请直接到[GitHub仓库](https://github.com/KaimingWan/openai-official-doc-zh)提交PR。

## 翻译待优化项

* 超链接补全：官方文档中有很多超链接，我在翻译的时候很多都没加
* 内容补全：参考翻译进度，没有标注已完成的就是没有翻译的

## 贡献名单

* [KaimingWan](https://github.com/KaimingWan?tab=repositories)


# 介绍

## 概览

OpenAI API可以应用于几乎任何涉及理解或生成自然语言或代码的任务。我们提供一系列具有不同能力级别的模型，适用于不同的任务，并且还能够微调您自己的定制模型。这些模型可用于从内容生成到语义搜索和分类等各种任务。

## 关键概念

我们建议完成我们的快速入门教程，通过实践互动示例来熟悉关键概念。

### Prompts and completions(提示和完成)

Completion(完成)是我们API的核心。它提供了一个非常灵活和强大的接口，用于访问我们的模型。您可以将一些文本作为Prompt(提示)输入，模型将生成一个文本补全，试图匹配您给出的任何上下文或模式。例如，如果您向API提供提示“为冰淇淋店编写标语”，它会返回类似于“我们会带着微笑为每一勺服务!” 的补全结果。设计您的提示实际上就是如何“编程”该模型，通常通过提供一些说明或几个示例来完成。这与大多数其他NLP服务不同，后者专门针对单个任务（例如情感分类或命名实体识别）而设计。相反，“完成”端点可用于几乎任何任务，包括内容或代码生成、摘要、扩展、对话、创意写作、风格转换等等。”

### Tokens(词元)

我们的模型通过将文本分解成Token(词元)来理解和处理文本。 词元可以是单词或仅是字符块。 例如，“hamburger”一词被拆分为“ham”，“bur”和“ger”三个词元，而像“pear”这样的短且常见的单词则是一个词元。 许多词元以空格开头，例如“你好”和“再见”。在给定API请求中处理的词元数量取决于您输入和输出的长度。作为粗略规则，对于英语文本，1个词元约为4个字符或0.75个单词。要牢记的一个限制是您的文本提示和生成完成组合必须不超过模型最大上下文长度（对于大多数模型而言，这是2048个词元或约1500个单词）。请查看我们的分词器工具以了解有关如何将文本转换为词元的更多信息。

### Models(模型)

API由一组具有不同功能和价格点的模型驱动。我们的基础GPT-3模型称为Davinci、Curie、Babbage和Ada。我们的Codex系列是GPT-3的后代，它经过了自然语言和代码的训练。要了解更多信息，请访问我们的模型文档。

### 接下来的步骤

* 在开始构建您的应用程序时，请牢记我们的使用政策。
* 浏览我们的示例库以获取灵感。
* 阅读我们的指南之一，开始构建。


# 快速开始

OpenAI已经训练了先进的语言模型，非常擅长理解和生成文本。我们的API提供对这些模型的访问，并可用于解决几乎涉及处理语言的任何任务。在这个快速入门教程中，您将构建一个简单的示例应用程序。在此过程中，您将学习到使用API进行任何任务所必需的关键概念和技术，包括：

* 内容生成
* 摘要分类
* 归类和情感分析
* 数据提取
* 翻译
* 更多！

## 介绍

“completions” 端点是我们 API 的核心，提供了一个简单而极其灵活和强大的接口。您输入一些文本作为提示，API 将返回一个文本完成，试图匹配您给出的任何指令或上下文。

```
提示：为冰淇淋店写一个标语。
完成：我们每勺都带来微笑！
```

您可以将其视为非常高级的自动完成功能 - 模型处理您的文本提示，并尝试预测最有可能出现的内容。

> 注意：文中涉及的例子请在ChatGPT聊天窗口执行查看效果

## 从一个指令开始

想象一下，你想创建一个宠物名字生成器。从零开始想出名字很难！首先，您需要一个明确表明您要求的提示。让我们从一条指令开始。提交此提示以生成第一个完成。

```
为马建议一个名称。
```

不错！现在，请尝试使您的指令更具体。

```
为黑马建议一个名称。
```

正如您所看到的，将简单形容词添加到我们的提示中会改变结果完成情况。设计您的提示基本上就是对模型编程的过程。

## 增加一些例子

制作好的说明对于获得良好的结果非常重要，但有时这还不够。让我们尝试使您的指示更加复杂。

```
为一只超级英雄马建议三个名字。
```

这个完成度还不太符合我们的要求。这些名称相当通用，似乎模型没有理解我们指令中的“马”的部分。让我们看看是否可以得到一些更相关的建议。在许多情况下，向模型展示和告诉您想要什么是有帮助的。将示例添加到提示中可以帮助传达模式或细微差别。尝试提交包含几个示例的此提示。

```
为一只超级英雄动物建议三个名字。
动物：猫
名字：锐爪队长，毛球特工，惊奇猫咪
动物：狗
名字：保护者拉夫，奇妙小犬，吠叫大师巴克斯
动物：马
名字：
```

> 注意：上面例子给出的结果比较像漫威英雄的名字了

不错！为给定的输入添加输出示例有助于模型提供我们正在寻找的名称类型。

## 调整你的设置

提示设计并不是你可以使用的唯一工具。您还可以通过调整设置来控制完成度。其中最重要的设置之一称为温度(Temperature)。您可能已经注意到，如果在上面的示例中多次提交相同的提示，则模型将始终返回相同或非常相似的完成。这是因为您的温度设置为0。请尝试使用温度设置为1重新提交相同的提示几次。

> 不像官网可以支持调节温度看不同温度下的输出结果，这边略过案例

看到发生了什么吗？当温度高于0时，提交相同的提示会导致每次不同的完成。请记住，模型预测哪个文本最有可能跟在前面的文本后面。温度是一个介于0和1之间的值，它实际上让您控制模型在进行这些预测时应该有多大信心。降低温度意味着它将冒更少的风险，并且完成将更准确和确定性。增加温度将导致更多样化的完成。

### 理解词元和概率

我们的模型通过将文本分解为称为词元的较小单元来处理文本。 词元可以是单词，单词块或单个字符。 编辑下面的文本以查看它如何被标记化(略过例子，因为没办法动态调节)。

```
I have an orange cat named Butterscotch.
```

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FW6j1G99BxjqhB6MTapL4%2Fimage.png?alt=media\&token=0df60dae-b0f9-40be-add4-a86653a46f89)

像“猫(cat)”这样的常见词是一个单一的词元，而不太常见的词通常被分解成多个词元。例如，“Butterscotch”翻译为四个词元：“But”，“ters”，“cot”和“ch”。许多词元以空格开头，例如“ hello”和“ bye”。给定一些文本，模型确定下一个最有可能出现的词元。例如，“Horses are my favorite”的文本最有可能跟随词元“ animal”。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2Fm8zeJvJQrpCgZeYDRJaN%2Fimage.png?alt=media\&token=96d77cdb-d437-43a1-b360-0b45393b3578)

这就是温度发挥作用的地方。如果您将此提示提交4次，并将温度设置为0，则模型始终会返回“动物(animal)”，因为它具有最高的概率。如果您增加温度，它将更冒险并考虑概率较低的词元。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FzuIiDmgv6ZKkRRyAxhdi%2Fimage.png?alt=media\&token=0504149a-2834-4559-9869-54a344083a4c)

通常情况下，对于需要定义明确输出的任务，最好设置较低的温度。如果需要多样性或创造力，则较高的温度可能会有用；或者如果您想为最终用户或人类专家生成几个变体以供选择，则也可以使用较高的温度。

## 构建你的应用

> 仅展示基于NODE.js的方式，官网还有python的方式，如果要查看使用python的方式请到官方查看

现在你已经找到了一个好的提示和设置，准备构建你的宠物名字生成器！我们编写了一些代码来帮助你入门 - 按照下面的说明下载代码并运行应用程序。

### 设置

如果您没有安装Node.js，请从此处安装。然后通过克隆该存储库来下载代码。

```
git clone https://github.com/openai/openai-quickstart-node.git
```

如果您不想使用git，您也可以通过此[zip文件](https://github.com/openai/openai-quickstart-node/archive/refs/heads/master.zip)下载代码。

### 添加你的API key

进入项目目录并复制示例环境变量文件。

```
cd openai-quickstart-node
cp .env.example .env
```

复制您的秘密 API 密钥，并将其设置为新创建的 .env 文件中的 OPENAI\_API\_KEY。如果您尚未创建秘密密钥，则可以到OpenAI官网个人中心->View API keys添加。

> 重要提示：在使用Javascript时，所有API调用应仅在服务器端进行，因为在客户端浏览器代码中进行调用将会暴露您的API密钥。请参阅[此处](https://platform.openai.com/docs/api-reference/authentication)以获取更多详细信息。

### 运行应用

在项目目录中运行以下命令以安装依赖项并运行应用程序。

```
npm install
npm run dev
```

在浏览器中打开 [http://localhost:3000，您应该会看到宠物名字生成器！](https://openaidoc.kaimingwan.com/readme/http:/localhost:3000，您应该会看到宠物名字生成器！)

### 理解代码

在openai-quickstart-node/pages/api文件夹中打开generate.js。 在底部，您将看到生成我们上面使用的提示的函数。 由于用户将输入其宠物类型，因此它会动态替换指定动物部分的提示。

```javascript
function generatePrompt(animal) {
  const capitalizedAnimal = animal[0].toUpperCase() + animal.slice(1).toLowerCase();
  return `Suggest three names for an animal that is a superhero.

Animal: Cat
Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
Animal: Dog
Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
Animal: ${capitalizedAnimal}
Names:`;
}
```

在generate.js的第9行，您将看到发送实际API请求的代码。如上所述，它使用温度为0.6的完成端点。

```javascript
const completion = await openai.createCompletion({
  model: "text-davinci-003",
  prompt: generatePrompt(req.body.animal),
  temperature: 0.6,
});
```

就是这样！现在你应该完全了解你的（超级英雄）宠物名字生成器如何使用OpenAI API了！

## 结尾

这些概念和技术将有助于您构建自己的应用程序。话虽如此，这个简单的例子只展示了可能性的一小部分！完成端点足够灵活，可以解决几乎任何语言处理任务，包括内容生成、摘要、语义搜索、主题标记、情感分析等等。需要注意的一个限制是，在大多数模型中，单个API请求只能在提示和完成之间处理最多2048个词元（大约1500个词）。

> 关于模型和价格：
>
> 我们提供一系列不同能力和[价格](https://openai.com/api/pricing/)的模型。在本教程中，我们使用了text-davinci-003，这是我们最强大的自然语言模型。我们建议在实验时使用此模型，因为它将产生最佳结果。一旦您使事情正常运行，您可以查看其他模型是否可以以更低的延迟和成本产生相同的结果。单个请求（提示和完成）处理的词元总数不能超过该模型的最大上下文长度。对于大多数模型而言，这是2,048个词元或约1,500个单词左右。作为一个粗略的经验法则，在英文文本中，1个词元约等于4个字符或0.75个单词。定价按每1000词元计费，并提供$5免费信用额度，在前3个月内可用。了解[更多信息](https://openai.com/api/pricing/).

## 接下来

获取灵感并了解如何为不同任务设计提示的方法：&#x20;

* 阅读我们的完成指南。&#x20;
* 浏览我们的示例提示库。&#x20;
* 在 Playground 中开始尝试。&#x20;
* 在开始构建之前，请牢记我们的[使用政策](https://platform.openai.com/docs/usage-policies)。


# 库

## Python库

我们提供一个Python库，你可以按照如下方式安装：

```
$ pip install openai
```

安装完成后，您可以使用他们和您的密钥来运行以下操作：

```python
import os
import openai

# Load your API key from an environment variable or secret management service
openai.api_key = os.getenv("OPENAI_API_KEY")

response = openai.Completion.create(model="text-davinci-003", prompt="Say this is a test", temperature=0, max_tokens=7)
```

该Python库也会安装一个命令行工具，你可以按照如下方式使用：

```
$ openai api completions.create -m text-davinci-003 -p "Say this is a test" -t 0 -M 7 --stream
```

## Node.js库

我们还有一个 Node.js 库，您可以通过在 Node.js 项目目录中运行以下命令来安装：

```
$ npm install openai
```

安装完成后，您可以使用他们和您的密钥来运行以下操作：

```javascript
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
const response = await openai.createCompletion({
  model: "text-davinci-003",
  prompt: "Say this is a test",
  temperature: 0,
  max_tokens: 7,
});
```

## 社区库

以下的库是由广大开发者社区构建和维护的。如果您想在此处添加新库，请按照我们帮助中心文章中关于添加社区库的说明进行操作。请注意，OpenAI不验证这些项目的正确性或安全性。

### C# / .NET

* [Betalgo.OpenAI.GPT3](https://github.com/betalgo/openai) by [Betalgo](https://github.com/betalgo)

### Crystal

* [openai-crystal](https://github.com/sferik/openai-crystal) by [sferik](https://github.com/sferik)

### Go

* [go-gpt3](https://github.com/sashabaranov/go-gpt3) by [sashabaranov](https://github.com/sashabaranov)

### Java

* [openai-java](https://github.com/TheoKanning/openai-java) by [Theo Kanning](https://github.com/TheoKanning)

### Kotlin

* [openai-kotlin](https://github.com/Aallam/openai-kotlin) by [Mouaad Aallam](https://github.com/Aallam)

### Node.js

* [openai-api](https://www.npmjs.com/package/openai-api) by [Njerschow](https://github.com/Njerschow)
* [openai-api-node](https://www.npmjs.com/package/openai-api-node) by [erlapso](https://github.com/erlapso)
* [gpt-x](https://www.npmjs.com/package/gpt-x) by [ceifa](https://github.com/ceifa)
* [gpt3](https://www.npmjs.com/package/gpt3) by [poteat](https://github.com/poteat)
* [gpts](https://www.npmjs.com/package/gpts) by [thencc](https://github.com/thencc)
* [@dalenguyen/openai](https://www.npmjs.com/package/@dalenguyen/openai) by [dalenguyen](https://github.com/dalenguyen)
* [tectalic/openai](https://github.com/tectalichq/public-openai-client-js) by [tectalic](https://tectalic.com/)

### PHP

* [orhanerday/open-ai](https://packagist.org/packages/orhanerday/open-ai) by [orhanerday](https://github.com/orhanerday)
* [tectalic/openai](https://github.com/tectalichq/public-openai-client-php) by [tectalic](https://tectalic.com/)

Python

* [chronology](https://github.com/OthersideAI/chronology) by [OthersideAI](https://www.othersideai.com/)

### R

* [rgpt3](https://github.com/ben-aaron188/rgpt3) by [ben-aaron188](https://github.com/ben-aaron188)

### Ruby

* [openai](https://github.com/nileshtrivedi/openai/) by [nileshtrivedi](https://github.com/nileshtrivedi)
* [ruby-openai](https://github.com/alexrudall/ruby-openai) by [alexrudall](https://github.com/alexrudall)

### Scala

* [openai-scala-client](https://github.com/cequence-io/openai-scala-client) by [cequence-io](https://github.com/cequence-io)

### Swift

* [OpenAIKit](https://github.com/dylanshine/openai-kit) by [dylanshine](https://github.com/dylanshine)

### Unity

* [OpenAi-Api-Unity](https://github.com/hexthedev/OpenAi-Api-Unity) by [hexthedev](https://github.com/hexthedev)

### Unreal Engine

* [OpenAI-Api-Unreal](https://github.com/KellanM/OpenAI-Api-Unreal) by [KellanM](https://github.com/KellanM)


# 模型

## 概览

OpenAI API由多种具有不同能力和价格点的模型驱动。您还可以使用微调对我们的原始基础模型进行有限的自定义，以适应您的特定用例。

| 模型                | 描述                                     |
| ----------------- | -------------------------------------- |
| GPT-3.5           | 一组模型，改进了GPT-3，可以理解并生成自然语言或代码。          |
| DALL·E            | 一个模型，可以根据自然语言提示生成和编辑图像。                |
| Whisper           | 一个模型，可以将音频转换为文本。 嵌入 一组模型，可以将文本转换为数字形式。 |
| CodexLimited beta | 一组模型，可以理解并生成代码，包括将自然语言翻译为代码。           |
| Moderation        | 经过微调的模型，可以检测文本是否可能敏感。                  |

我们还发布了开源模型，包括Point-E、Whisper、Jukebox和CLIP。

请访问我们提供给研究人员的[模型索引](https://platform.openai.com/docs/model-index-for-researchers)，以了解更多关于哪些模型在我们的研究论文中亮相以及InstructGPT和GPT-3.5等模型系列之间的区别的信息，供研究人员参考。

## GPT 3.5

GPT-3.5 模型能够理解和生成自然语言或代码。我们最具实力和性价比的模型是 gpt-3.5-turbo，它经过优化以适用于聊天，但也适用于传统的自动完成任务。

| 最新模型               | 描述                                                                                               | 最大请求      | 训练数据          |
| ------------------ | ------------------------------------------------------------------------------------------------ | --------- | ------------- |
| gpt-3.5-turbo      | GPT-3.5 最具实力的模型，经过优化以适用于聊天，与 text-davinci-003 相比成本只有其 1/10。将会更新到我们最新的模型版本。                       | 4,096 个词元 | 截至 2021 年 9 月 |
| gpt-3.5-turbo-0301 | gpt-3.5-turbo 在 2023 年 3 月 1 日的快照。与 gpt-3.5-turbo 不同，该模型将不会接受更新，并且仅在 2023 年 6 月 1 日结束的三个月期间得到支持。 | 4,096 个词元 | 截至 2021 年 9 月 |
| text-davinci-003   | 能够完成任何语言任务，比 curie、babbage 或 ada 模型具有更好的质量、更长的输出和一致的指令遵循，还支持在文本中插入完成。                            | 4,000 个词元 | 截至 2021 年 6 月 |
| text-davinci-002   | 具有类似 text-davinci-003 的功能，但是通过监督微调进行训练而不是强化学习。                                                   | 4,000 个词元 | 截至 2021 年 6 月 |
| code-davinci-002   | 优化用于代码自动完成任务。                                                                                    | 4,000 个词元 | 截至 2021 年 6 月 |
|                    |                                                                                                  |           |               |

我们建议在体验过程中使用 gpt-3.5-turbo，因为它会产生最好的结果。一旦您已经成功，我们鼓励尝试其他模型，以查看是否可以以更低的延迟或成本获得相同的结果。

> OpenAI模型是非确定性的，这意味着相同的输入可能会产生不同的输出。将温度设置为0会使输出大部分确定性，但仍可能存在一些变异性。

## 特定功能的模型

虽然新的gpt-3.5-turbo模型针对聊天进行了优化，但在传统的completion任务上也表现非常出色。原始的GPT-3.5模型针对文本补全进行了优化。

我们用于创建嵌入(embedding)和编辑文本(editing text)的端点使用其专门的模型集。

## Turbo

Turbo是与ChatGPT相同的模型系列。它针对会话聊天输入和输出进行了优化，但与Davinci模型系列相比，在完成任务时同样表现出色。在API中，任何ChatGPT能够很好完成的用例都应该能够在Turbo模型系列中表现出色。

Turbo模型系列也是第一个像ChatGPT一样定期接收模型更新的模型系列。

擅长：对话和文本生成

## Davinci

Davinci是最能胜任的模型系列，可以执行其他模型（ada、curie和babbage）能执行的任何任务，并且通常需要更少的指令。对于需要大量理解内容的应用，如特定受众的摘要和创意内容生成，Davinci将产生最佳结果。这些增强的功能需要更多的计算资源，因此每个API调用的Davinci成本更高，速度也不如其他模型快。

另一个Davinci闪耀的领域是理解文本的意图。Davinci非常擅长解决许多逻辑问题和解释角色的动机。Davinci已经能够解决一些涉及因果关系的最具挑战性的人工智能问题。

擅长：复杂意图、因果关系和面向受众的摘要。

## Whisper(耳语)&#x20;

Whisper是一种通用语音识别模型。它是基于大量多样化音频训练的多任务模型，可以进行多语言语音识别、语音翻译和语言识别。目前，通过我们的API，Whisper v2-large模型可以使用whisper-1模型名称进行访问。

目前，Whisper的开源版本和通过我们的API提供的版本没有区别。然而，通过我们的API，我们提供了一个优化的推理过程，使得通过我们的API运行Whisper比通过其他方式更快。如果您想了解更多关于Whisper的技术细节，可以阅读[相关论文](https://arxiv.org/pdf/2212.04356.pdf)。

## Embeddings(嵌入)

嵌入是文本的数值表示形式，可以用于衡量两个文本之间的相关性。我们的第二代嵌入模型，text-embedding-ada-002，是专门设计用来代替以前的16个第一代嵌入向量模型，成本只有一小部分。嵌入对于搜索、聚类、推荐、异常检测和分类任务非常有用。您可以在我们的[公告博客](https://openai.com/blog/new-and-improved-embedding-model)文章中了解更多关于我们最新嵌入向量模型的信息。

Codex(BETA测试)

Codex模型是我们的GPT-3模型的后代，可以理解和生成代码。它们的训练数据包含来自GitHub的自然语言和数十亿行公共代码。了解更多。

它们在Python方面最为强大，并且熟练掌握包括JavaScript、Go、Perl、PHP、Ruby、Swift、TypeScript、SQL甚至Shell在内的十多种语言。

目前，我们提供两种Codex模型：

<table><thead><tr><th>最新模型</th><th> 描述</th><th width="136">最大请求</th><th>训练数据</th></tr></thead><tbody><tr><td>code-davinci-002 </td><td>最强大的Codex模型。特别擅长将自然语言翻译为代码。除了完成代码，还支持在代码中插入完成。 </td><td>8,000个词元</td><td>截至2021年6月</td></tr><tr><td>code-cushman-001 </td><td>几乎与Davinci Codex一样强大，但速度略快。这种速度优势可能使其更适合实时应用。 </td><td>2,048个标记 </td><td></td></tr></tbody></table>

&#x20;   最多更多信息，请访问我们的Codex工作指南。

## Mederation(内容审核)

OpenAI的Moderation模型旨在检查内容是否符合OpenAI的使用政策。该模型提供分类能力，可以检查以下类别的内容：仇恨、仇恨/威胁、自残、性、未成年人性行为、暴力和暴力/图形。更多信息请参见我们的Moderation指南。

| 模型                     | 描述                            |
| ---------------------- | ----------------------------- |
| text-moderation-latest | 最强大的Moderation模型。准确性将略高于稳定模型。 |
| text-moderation-stable | 几乎与最新模型一样强大，但较旧。              |

## GPT-3&#x20;

GPT-3模型能够理解和生成自然语言。这些模型已经被更强大的GPT-3.5一代模型取代。然而，原始的GPT-3基础模型（davinci、curie、ada和babbage）是目前唯一可供微调的模型。

| 模型               | 描述                                         | 最大请求     | 训练数据       |
| ---------------- | ------------------------------------------ | -------- | ---------- |
| text-curie-001   | 非常强大，比Davinci更快、成本更低。                      | 2,048个词元 | 截至2019年10月 |
| text-babbage-001 | 能够完成简单的任务，速度非常快，成本更低。                      | 2,048个词元 | 截至2019年10月 |
| text-ada-001     | 能够完成非常简单的任务，通常是GPT-3系列中最快的模型，成本最低。         | 2,048个标记 | 截至2019年10月 |
| davinci          | 最强大的GPT-3模型。可以完成其他模型可以完成的任何任务，而且通常具有更高的质量。 | 2,048个标记 | 截至2019年10月 |
| curie            | 非常强大，但比Davinci更快、成本更低。                     | 2,048个标记 | 截至2019年10月 |
| babbage          | 能够完成简单的任务，速度非常快，成本更低。                      | 2,048个标记 | 截至2019年10月 |
| ada              | 能够完成非常简单的任务，通常是GPT-3系列中最快的模型，成本最低。         | 2,048个标记 | 截至2019年10月 |

&#x20;    \ <br>


# 引导

通过逐步构建真正的 AI 应用程序来开始使用 OpenAI API。

* 使用嵌入式技术实现的网站问答：学习如何构建一个能够回答有关您网站问题的人工智能&#x20;
* 即将推出：学习如何构建和部署一个能够回答本地文件问题的人工智能&#x20;
* 即将推出： 学习如何构建和部署一个理解多个知识库的人工智能聊天机器人


# 如何构建一个能够回答关于你的网站问题的人工智能

本教程演示了一个简单的网站爬取示例（在此示例中，是 OpenAI 网站），使用嵌入式(embedding) API 将爬取的页面转换为嵌入式，并创建基本搜索功能，允许用户提出有关embedding信息的问题。这旨在成为更复杂应用程序的起点，这些应用程序利用自定义知识库。

## 开始

一些Python和GitHub的基本知识对于这个教程是有帮助的。在开始之前，请确保设置了OpenAI API密钥并完成了快速入门教程。这将使您对如何充分利用API有一个良好的直觉。 Python作为主要编程语言，与OpenAI、Pandas、transformers、NumPy和其他流行包一起使用。如果您在学习此教程时遇到任何问题，请在OpenAI社区论坛上提问。 要开始编码，请克隆GitHub上此教程的完整代码。或者，跟着每个部分复制到Jupyter笔记本中，并逐步运行代码，或者只是阅读。避免任何问题的好方法是设置一个新的虚拟环境，并通过运行以下命令安装所需包：

```
python -m venv env

source env/bin/activate

pip install -r requirements.txt
```

### 建立网络爬虫

本教程的主要重点是OpenAI API，因此如果您愿意，可以跳过如何创建网络爬虫的内容，直接下载源代码。否则，请展开以下部分以了解实现网络爬取机制的详细步骤。

#### 学习如何构建网络爬虫

获取文本数据是使用嵌入的第一步。本教程通过爬取OpenAI网站创建了一个新的数据集，您也可以使用同样的技术来获取您自己公司或个人网站上的数据。[点我查看源代码](https://github.com/openai/openai-cookbook/tree/main/apps/web-crawl-q-and-a)。

虽然可以使用开源包（如Scrapy）来帮助完成这些操作，但本教程的网络爬虫是从零开始编写的。

该爬虫将从下方代码中传入的根URL开始，访问每个页面，查找附加链接，并访问这些页面（只要它们具有相同的根域名）。为了开始，导入所需的包，设置基本URL并定义HTMLParser类。

```python
import requests
import re
import urllib.request
from bs4 import BeautifulSoup
from collections import deque
from html.parser import HTMLParser
from urllib.parse import urlparse
import os

# Regex pattern to match a URL
HTTP_URL_PATTERN = r'^http[s]*://.+'

domain = "openai.com" # <- put your domain to be crawled
full_url = "https://openai.com/" # <- put your domain to be crawled with https or http

# Create a class to parse the HTML and get the hyperlinks
class HyperlinkParser(HTMLParser):
    def __init__(self):
        super().__init__()
        # Create a list to store the hyperlinks
        self.hyperlinks = []

    # Override the HTMLParser's handle_starttag method to get the hyperlinks
    def handle_starttag(self, tag, attrs):
        attrs = dict(attrs)

        # If the tag is an anchor tag and it has an href attribute, add the href attribute to the list of hyperlinks
        if tag == "a" and "href" in attrs:
            self.hyperlinks.append(attrs["href"])
```

下一个函数以URL作为参数，打开URL并读取HTML内容。然后，它返回该页面上找到的所有超链接。

```python
# Function to get the hyperlinks from a URL
def get_hyperlinks(url):
    
    # Try to open the URL and read the HTML
    try:
        # Open the URL and read the HTML
        with urllib.request.urlopen(url) as response:

            # If the response is not HTML, return an empty list
            if not response.info().get('Content-Type').startswith("text/html"):
                return []
            
            # Decode the HTML
            html = response.read().decode('utf-8')
    except Exception as e:
        print(e)
        return []

    # Create the HTML Parser and then Parse the HTML to get hyperlinks
    parser = HyperlinkParser()
    parser.feed(html)

    return parser.hyperlinks
```

目标是遍历并索引仅在OpenAI域下的内容。为此，需要编写一个函数调用get\_hyperlinks函数，但过滤掉任何不属于指定域的URL。

```python
# Function to get the hyperlinks from a URL that are within the same domain
def get_domain_hyperlinks(local_domain, url):
    clean_links = []
    for link in set(get_hyperlinks(url)):
        clean_link = None

        # If the link is a URL, check if it is within the same domain
        if re.search(HTTP_URL_PATTERN, link):
            # Parse the URL and check if the domain is the same
            url_obj = urlparse(link)
            if url_obj.netloc == local_domain:
                clean_link = link

        # If the link is not a URL, check if it is a relative link
        else:
            if link.startswith("/"):
                link = link[1:]
            elif link.startswith("#") or link.startswith("mailto:"):
                continue
            clean_link = "https://" + local_domain + "/" + link

        if clean_link is not None:
            if clean_link.endswith("/"):
                clean_link = clean_link[:-1]
            clean_links.append(clean_link)

    # Return the list of hyperlinks that are within the same domain
    return list(set(clean_links))
```

爬取功能是网络抓取任务设置的最后一步。它跟踪访问过的URL以避免重复访问同一页，该页可能在站点上链接到多个页面。它还从页面中提取不带HTML标记的原始文本，并将文本内容写入特定于该页面的本地.txt文件。

```python
def crawl(url):
    # Parse the URL and get the domain
    local_domain = urlparse(url).netloc

    # Create a queue to store the URLs to crawl
    queue = deque([url])

    # Create a set to store the URLs that have already been seen (no duplicates)
    seen = set([url])

    # Create a directory to store the text files
    if not os.path.exists("text/"):
            os.mkdir("text/")

    if not os.path.exists("text/"+local_domain+"/"):
            os.mkdir("text/" + local_domain + "/")

    # Create a directory to store the csv files
    if not os.path.exists("processed"):
            os.mkdir("processed")

    # While the queue is not empty, continue crawling
    while queue:

        # Get the next URL from the queue
        url = queue.pop()
        print(url) # for debugging and to see the progress

        # Save text from the url to a <url>.txt file
        with open('text/'+local_domain+'/'+url[8:].replace("/", "_") + ".txt", "w", encoding="UTF-8") as f:

            # Get the text from the URL using BeautifulSoup
            soup = BeautifulSoup(requests.get(url).text, "html.parser")

            # Get the text but remove the tags
            text = soup.get_text()

            # If the crawler gets to a page that requires JavaScript, it will stop the crawl
            if ("You need to enable JavaScript to run this app." in text):
                print("Unable to parse page " + url + " due to JavaScript being required")
            
            # Otherwise, write the text to the file in the text directory
            f.write(text)

        # Get the hyperlinks from the URL and add them to the queue
        for link in get_domain_hyperlinks(local_domain, url):
            if link not in seen:
                queue.append(link)
                seen.add(link)

crawl(full_url)
```

上面示例的最后一行运行爬虫，遍历所有可访问的链接，并将这些页面转换为文本文件。根据您网站的大小和复杂性，此过程可能需要几分钟时间。

### 构建嵌入索引

CSV是存储嵌入的常见格式。你可以通过将原始文本文件（位于text目录中）转换为Pandas数据帧来使用Python处理该格式。Pandas是一个流行的开源库，可帮助您处理表格数据（以行和列存储的数据）。 空白的空行可能会使文本文件混乱，使其更难以处理。一个简单的函数可以删除这些行并整理文件。

```python
def remove_newlines(serie):
    serie = serie.str.replace('\n', ' ')
    serie = serie.str.replace('\\n', ' ')
    serie = serie.str.replace('  ', ' ')
    serie = serie.str.replace('  ', ' ')
    return serie
```

将文本转换为CSV需要遍历之前创建的text目录中的文本文件。在打开每个文件后，删除多余的空格并将修改后的文本追加到一个列表中。然后，将删除了新行的文本添加到一个空的Pandas数据帧中，并将数据帧写入CSV文件。

> 额外的空格和新行可能会使文本混乱，并复杂化嵌入过程。这里使用的代码有助于删除其中的一些，但您可能会发现第三方库或其他方法有用于去除更多不必要字符的功能。

```python
import pandas as pd

# Create a list to store the text files
texts=[]

# Get all the text files in the text directory
for file in os.listdir("text/" + domain + "/"):

    # Open the file and read the text
    with open("text/" + domain + "/" + file, "r", encoding="UTF-8") as f:
        text = f.read()

        # Omit the first 11 lines and the last 4 lines, then replace -, _, and #update with spaces.
        texts.append((file[11:-4].replace('-',' ').replace('_', ' ').replace('#update',''), text))

# Create a dataframe from the list of texts
df = pd.DataFrame(texts, columns = ['fname', 'text'])

# Set the text column to be the raw text with the newlines removed
df['text'] = df.fname + ". " + remove_newlines(df.text)
df.to_csv('processed/scraped.csv')
df.head()
```

在将原始文本保存到CSV文件后，词元化是下一步。该过程通过分解句子和单词将输入文本分成词元。可以通过查看我们文档中的Tokenizer来进行视觉演示。

一个有用的经验法则是，对于常见的英文文本，一个词元通常对应约4个字符。这相当于大约3/4个单词（因此100个词元\~= 75个单词）。 API对于嵌入的最大输入标记数有限制。为了保持在限制范围内，需要将CSV文件中的文本拆分成多个行。首先记录每行的现有长度，以确定需要拆分哪些行。

```python
import tiktoken

# Load the cl100k_base tokenizer which is designed to work with the ada-002 model
tokenizer = tiktoken.get_encoding("cl100k_base")

df = pd.read_csv('processed/scraped.csv', index_col=0)
df.columns = ['title', 'text']

# Tokenize the text and save the number of tokens to a new column
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))

# Visualize the distribution of the number of tokens per row using a histogram
df.n_tokens.hist()
```

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FIIkP6EYUBqcPYQCZhCWW%2Fimage.png?alt=media\&token=d4b1829c-4925-446c-a86f-63e8e9eb5017)

最新的嵌入模型可以处理多达8191个输入标记的输入，因此大多数行不需要任何拆分，但对于每个爬取的子页面可能并非都是这样，因此下一个代码块将把更长的行拆分成较小的块。

```python
max_tokens = 500

# Function to split the text into chunks of a maximum number of tokens
def split_into_many(text, max_tokens = max_tokens):

    # Split the text into sentences
    sentences = text.split('. ')

    # Get the number of tokens for each sentence
    n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]
    
    chunks = []
    tokens_so_far = 0
    chunk = []

    # Loop through the sentences and tokens joined together in a tuple
    for sentence, token in zip(sentences, n_tokens):

        # If the number of tokens so far plus the number of tokens in the current sentence is greater 
        # than the max number of tokens, then add the chunk to the list of chunks and reset
        # the chunk and tokens so far
        if tokens_so_far + token > max_tokens:
            chunks.append(". ".join(chunk) + ".")
            chunk = []
            tokens_so_far = 0

        # If the number of tokens in the current sentence is greater than the max number of 
        # tokens, go to the next sentence
        if token > max_tokens:
            continue

        # Otherwise, add the sentence to the chunk and add the number of tokens to the total
        chunk.append(sentence)
        tokens_so_far += token + 1

    return chunks
    

shortened = []

# Loop through the dataframe
for row in df.iterrows():

    # If the text is None, go to the next row
    if row[1]['text'] is None:
        continue

    # If the number of tokens is greater than the max number of tokens, split the text into chunks
    if row[1]['n_tokens'] > max_tokens:
        shortened += split_into_many(row[1]['text'])
    
    # Otherwise, add the text to the list of shortened texts
    else:
        shortened.append( row[1]['text'] )
```

再次可视化更新后的直方图可以帮助确认行是否已成功拆分为缩短的部分。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2Fcga9muwK8FoWt4CJ7uwH%2Fimage.png?alt=media\&token=21451a9a-1902-489f-a2ad-3d494f00766b)

现在将内容拆分成较小的块，并且可以向OpenAI API发送简单请求，指定使用新的text-embedding-ada-002模型来创建嵌入：

```python
import openai

df['embeddings'] = df.text.apply(lambda x: openai.Embedding.create(input=x, engine='text-embedding-ada-002')['data'][0]['embedding'])

df.to_csv('processed/embeddings.csv')
df.head()
```

这应该需要大约3-5分钟，但完成后您就可以使用您的嵌入了！

### 使用您的嵌入构建一个问答系统

嵌入已经准备好了，此过程的最后一步是创建一个简单的问答系统。这个系统会接收用户的问题，创建它的嵌入，并将其与现有的嵌入进行比较，以检索从抓取的网站中最相关的文本。然后，text-davinci-003模型将根据检索到的文本生成一个自然的回答。

将嵌入转换为NumPy数组是第一步，这将提供更多的灵活性，因为可以利用许多操作NumPy数组的函数来使用它。这还将将维度压平为1-D，这是许多后续操作所需的格式。

```python
import numpy as np
from openai.embeddings_utils import distances_from_embeddings

df=pd.read_csv('processed/embeddings.csv', index_col=0)
df['embeddings'] = df['embeddings'].apply(eval).apply(np.array)

df.head()
```

现在，由于数据已准备好，需要使用一个简单的函数将问题转换为嵌入。这很重要，因为搜索依赖嵌入和使用余弦距离的数字向量（这是原始文本的转换）进行比较。如果向量在余弦距离上接近，则它们很可能相关且可能是问题的答案。OpenAI的Python包具有内置的distances\_from\_embeddings函数，在这里非常有用。

```python
def create_context(
    question, df, max_len=1800, size="ada"
):
    """
    Create a context for a question by finding the most similar context from the dataframe
    """

    # Get the embeddings for the question
    q_embeddings = openai.Embedding.create(input=question, engine='text-embedding-ada-002')['data'][0]['embedding']

    # Get the distances from the embeddings
    df['distances'] = distances_from_embeddings(q_embeddings, df['embeddings'].values, distance_metric='cosine')


    returns = []
    cur_len = 0

    # Sort by distance and add the text to the context until the context is too long
    for i, row in df.sort_values('distances', ascending=True).iterrows():
        
        # Add the length of the text to the current length
        cur_len += row['n_tokens'] + 4
        
        # If the context is too long, break
        if cur_len > max_len:
            break
        
        # Else add it to the text that is being returned
        returns.append(row["text"])

    # Return the context
    return "\n\n###\n\n".join(returns)
```

将文本分成更小的词元集合后，按升序循环遍历并继续添加文本是确保完整答案的关键步骤。如果返回的内容比期望的多，则可以将max\_len修改为较小的值。

前一步仅检索与问题语义相关的文本块，因此它们可能包含答案，但并不保证。通过返回前5个最可能的结果，可以进一步增加找到答案的机会。

然后，回答提示将尝试从检索到的上下文中提取相关事实，以制定连贯的答案。如果没有相关答案，则提示将返回“我不知道”。

使用text-davinci-003的完成端点可以创建一个听起来更为真实的答案。

```python
def answer_question(
    df,
    model="text-davinci-003",
    question="Am I allowed to publish model outputs to Twitter, without a human review?",
    max_len=1800,
    size="ada",
    debug=False,
    max_tokens=150,
    stop_sequence=None
):
    """
    Answer a question based on the most similar context from the dataframe texts
    """
    context = create_context(
        question,
        df,
        max_len=max_len,
        size=size,
    )
    # If debug, print the raw model response
    if debug:
        print("Context:\n" + context)
        print("\n\n")

    try:
        # Create a completions using the question and context
        response = openai.Completion.create(
            prompt=f"Answer the question based on the context below, and if the question can't be answered based on the context, say \"I don't know\"\n\nContext: {context}\n\n---\n\nQuestion: {question}\nAnswer:",
            temperature=0,
            max_tokens=max_tokens,
            top_p=1,
            frequency_penalty=0,
            presence_penalty=0,
            stop=stop_sequence,
            model=model,
        )
        return response["choices"][0]["text"].strip()
    except Exception as e:
        print(e)
        return ""
```

完成了！一个拥有OpenAI网站嵌入式知识的工作问答系统现在已经准备好了。可以进行一些快速测试，以查看输出的质量：

```python
answer_question(df, question="What day is it?", debug=False)

answer_question(df, question="What is our newest embeddings model?")

answer_question(df, question="What is ChatGPT?")
```

回答将类似于以下内容：

```
"I don't know."

'The newest embeddings model is text-embedding-ada-002.'

'ChatGPT is a model trained to interact in a conversational way. It is able to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests.'
```

如果系统无法回答一个预期的问题，那么搜索原始文本文件，看看预期的信息是否确实被嵌入其中或者没有。最初进行的爬取过程是设置跳过提供的原始域之外的网站，因此如果设置了子域，可能就没有这些知识。

目前，每次回答一个问题时都会传递数据帧。对于更多生产工作流程，应该使用[矢量数据库](https://platform.openai.com/docs/guides/embeddings/how-can-i-retrieve-k-nearest-embedding-vectors-quickly)解决方案，而不是将嵌入存储在CSV文件中，但当前的方法是原型设计的一个很好的选择。


# 数据使用政策

2023年3月1日更新

> 从2023年3月1日开始，我们对数据使用和保留政策做出了两项更改：
>
> 除非您明确决定与我们共享您的数据，否则OpenAI将不会使用通过我们的API提交的数据来训练或改进我们的模型。您可以选择选择加入以共享数据。
>
> 通过API发送的任何数据将被保留用于滥用和误用监控目的，最长时间为30天，之后将被删除（除非法律另有规定）。

OpenAI API处理用户提示和完成请求，以及通过“Files”端点提交的训练数据以微调模型。我们将此类数据称为API数据。

默认情况下，OpenAI不会使用通过我们的API提交的数据来训练OpenAI模型或改善OpenAI的服务提供。用户提交的用于微调的数据仅用于微调客户的模型。但是，OpenAI将允许用户选择选择加入共享他们的数据以提高模型性能。共享您的数据将确保模型的未来迭代针对您的用例得到改进。在此更改生效之前的2023年3月1日之前通过API提交的数据，如果客户之前没有选择退出共享数据，则可能已用于改进。

OpenAI为了滥用和误用监控目的保留API数据30天。少数经过授权的OpenAI员工以及受保密和安全义务约束的专业第三方承包商可以访问此数据，仅用于调查和验证涉嫌滥用行为。部署低误用可能性用例的企业客户可以请求根本不存储API数据，包括用于安全监控和预防。OpenAI仍可能有内容分类器标记涉嫌包含平台滥用的数据。例如，通过“Files”端点由用户提交的用于微调模型的数据将保留，直到用户删除该文件。

请注意，此数据政策不适用于OpenAI的非API消费者服务，如ChatGPT或DALL·E实验室。您可以在我们的[消费者服务数据使用FAQ](https://help.openai.com/en/articles/7039943-data-usage-for-consumer-services-faq)中了解更多信息。

## 常见问题解答

### OpenAI的公共API拥有哪些技术保护和安全认证？

OpenAI符合SOC 2 Type 1标准，并已经通过独立第三方审核，符合2017年安全信托服务标准。

### API数据存储在哪里？

内容存储在OpenAI系统和我们的子处理器系统中。我们还可能向第三方承包商发送部分去标识化的内容（受保密和安全义务约束）以确保安全。我们的30天数据保留政策也适用于我们的子处理器和承包商。您可以查看我们的子处理器列表以了解其位置和详细信息。

### 当我调用API时，数据是否在传输过程中加密？

OpenAI API只能通过传输层安全性（TLS）使用，因此客户与OpenAI的请求和响应都是加密的。

### OpenAI有欧洲数据中心吗？

所有客户数据都在美国处理和存储。我们目前不在欧洲或其他国家存储数据。

### 我可以将API用于HIPAA工作负载吗？

我们可以签署业务关联协议，以支持客户遵守《健康保险可移植性和责任法案》（HIPAA）的合规性要求。要符合此要求，您必须与OpenAI签订企业协议，并具有符合条件的使用案例。如果您有兴趣，请联系我们的销售团队。

### 我收到了数据删除请求，如何要求OpenAI删除数据？

我们只保留通过API发送的数据，用于滥用和监控目的，最多30天。如果您希望在此之前删除您的帐户，请按照以下步骤操作。

### OpenAI是否有数据处理附加协议（DPA）？

是的。请填写我们的DPA表格以执行我们的数据处理附加协议。

### 我们可以自己托管吗？&#x20;

我们不提供本地托管服务。您可以通过联系我们的销售团队购买专用容量。


# 使用政策

更新于2023年2月15日

我们希望每个人都能安全、负责任地使用我们的工具。这就是为什么我们制定了适用于所有OpenAI模型、工具和服务用户的使用政策。遵守这些政策将确保我们的技术被用于善良之事。

如果我们发现您的产品或使用不符合这些政策，我们可能会要求您做出必要的改变。反复或严重的违规行为可能会导致进一步的行动，包括暂停或终止您的账户。

随着我们对模型的使用和滥用了解越来越多，我们的政策可能会发生变化。

## 平台政策&#x20;

我们的API被用于支持许多行业和技术平台的业务。从iOS应用到网站到Slack，我们的API的简便性使其能够集成到各种用例中。在下面提到的用例限制范围内，我们允许在所有主要技术平台、应用商店等产品中集成我们的API。

## 禁止使用&#x20;

我们不允许使用我们的模型进行以下行为：

* 非法活动&#x20;
* 儿童色情或任何剥削或伤害儿童的内容&#x20;
* 生成具有仇恨、骚扰或暴力内容&#x20;
* 生成恶意软件&#x20;
* 具有高风险的身体伤害活动&#x20;
* 具有高风险的经济损失活动&#x20;
* 欺诈或欺骗性活动&#x20;
* 成人内容、成人产业和约会应用程序&#x20;
* 政治竞选或游说活动&#x20;
* 侵犯个人隐私的活动&#x20;
* 未经授权从事法律实践，或者提供未经合格人员审查的定制法律建议
* 提供未经合格人员审查的定制财务建议&#x20;
* 告诉某人他们有或没有某种健康状况，或提供如何治疗或治愈某种健康状况的说明&#x20;
* 高风险政府决策

我们还有对特定使用场景的更多要求：

* 在医疗、金融和法律行业、新闻生成或新闻摘要等面向消费者的使用场景中，以及其他情况下必要的，必须向用户提供免责声明，告知他们正在使用 AI 技术及其潜在限制。
* 自动化系统（包括对话式 AI 和聊天机器人）必须向用户披露他们正在与一个 AI 系统进行交互。除了描述历史公众人物的聊天机器人之外，模拟另一个人的产品必须要得到该人的明确同意或清楚地标明为“模拟”或“恶搞”。
* 在直播、演示和研究中使用模型输出时，必须遵守我们的分享和发布政策。

你可以使用我们的免费的[内容审核终端](https://platform.openai.com/docs/guides/moderation)和[安全最佳实践](https://openaidoc.kaimingwan.com/)来帮助你保持应用程序的安全。


# 指南


# 文本完成

学习如何生成或操作文本

## 简介&#x20;

完成端点可以用于各种各样的任务。它提供了一个简单但功能强大的接口，可以连接到我们的任何模型。您将一些文本作为提示输入，模型将生成一个文本完成，试图匹配您给它的任何上下文或模式。例如，如果您向API提供提示“如笛卡尔所说，我思故我在”，它将高概率返回完成“我是”。

开始探索完成的最佳方式是通过我们的Playground。它只是一个文本框，您可以在其中提交提示以生成一个完成。您可以从以下示例开始：

```
为一个冰激凌店写一个标语。 
```

一旦您提交，您将看到类似于以下内容的内容：

```
为一个冰激凌店写一个标语。 
我们用每一勺冰淇淋提供笑容！
```

&#x20;您看到的实际完成可能会有所不同，因为API默认情况下是非确定性的。这意味着，即使您的提示保持不变，每次调用时您可能会得到稍微不同的完成。将温度设置为0将使输出大部分确定性，但可能仍会有一小部分变化。

这个简单的文本输入和输出界面意味着您可以通过提供指令或只提供一些您想让它完成的示例来“编程”模型。它的成功通常取决于任务的复杂性和您提示的质量。一个好的经验法则是想想如果您要为一个中学生写一个文字问题，让他们来解决。一个写得好的提示提供了足够的信息，让模型知道您想要什么以及它应该如何回应。

本指南涵盖了一般提示设计的最佳实践和示例。要了解有关使用我们的Codex模型进行代码工作的更多信息，请访问我们的代码指南。

> 请记住，默认模型的训练数据截止到2021年，因此它们可能不知道当前事件的情况。我们计划在未来添加更多的持续培训。

## 提示(prompt)设计&#x20;

### 基础知识&#x20;

我们的模型可以完成从生成原始故事到执行复杂文本分析的所有任务。因为它们可以完成许多事情，所以你必须明确描述你想要的内容。显示，而不是仅仅告诉，通常是一个好提示的秘诀。

创建提示的三个基本准则如下：

**展示和告诉**。通过说明、示例或两者的结合清楚地表明你想要什么。如果你想让模型按字母顺序对一系列项目进行排名，或者将段落按情感进行分类，请向它展示你想要的内容。

**提供高质量数据**。如果你试图构建分类器或让模型遵循某种模式，请确保有足够的示例。一定要校对你的示例——模型通常足够聪明，可以看穿基本的拼写错误并给出回答，但它也可能认为这是有意的，从而影响回答。

**检查你的设置**。温度和top\_p设置控制模型在生成响应时的确定性。如果你要求它生成只有一个正确答案的响应，那么你应该将这些设置较低。如果你想要更多样化的响应，那么你可能需要将它们设置得更高。人们在使用这些设置时犯的第一个错误是认为它们是“聪明度”或“创造力”控制。

## 故障排除

&#x20;如果您无法如预期一般让API正常工作，请遵循以下清单：

1. 是否清楚生成的预期结果？&#x20;
2. 是否提供足够的示例？&#x20;
3. 您是否检查示例中是否有错误？（API不会直接告诉您）&#x20;
4. 您是否正确使用温度和top\_p？

## 分类

&#x20;使用API创建文本分类器时，我们提供了任务描述和几个示例。在这个例子中，我们展示如何对推特的情感进行分类。

```
决定一条推特的情感是积极的，中性的还是消极的。
推特：我喜欢新的蝙蝠侠电影！ 情感： 
```

在这个例子中，有几个需要注意的要点：

1. 使用简明易懂的语言描述输入和输出。我们用简明易懂的语言描述了输入“推特”和预期输出“情感”。作为最佳实践，应该从最详细的描述开始。虽然您可以使用缩写或关键词表示输入和输出，但最好先尽可能详细地描述，然后逐步去除多余的词汇以检查性能是否保持一致。&#x20;
2. 向API展示如何应对任何情况。在这个例子中，我们在指令中包含了可能的情感标签。中性标签非常重要，因为即使是人类在某些情况下也很难确定某些事物是积极的还是消极的，或者既不积极也不消极。&#x20;
3. 对于熟悉的任务，您需要更少的示例。对于这个分类器，我们没有提供任何示例。这是因为API已经了解情感和推特的概念。如果您正在构建一个API可能不熟悉的分类器，可能需要提供更多示例。

### 提高分类器的效率

&#x20;现在我们已经掌握了如何构建分类器，让我们以此为例，使其更加高效，以便我们可以在一个API调用中获取多个结果。

分类以下推特的情感：

```
“我受不了作业” 
“这太糟糕了，我很无聊 😠” 
“我迫不及待地等待万圣节！” 
“我的猫咪可爱 ❤️❤️” 
“我讨厌巧克力” 推特情感评级：
```

我们提供了一个带编号的推特列表，这样API就可以在一个API调用中评估五个（甚至更多）推特。

需要注意的是，当您要求API创建列表或评估文本时，需要特别注意您的概率设置（Top P或温度）以避免漂移。

* 通过运行多个测试来确保您的概率设置已经正确校准。&#x20;
* 不要让列表过长，否则API可能会漂移。

## 生成

API最强大，同时也是最简单的任务之一，是生成输入的新思想或版本。您可以提出任何问题，从故事想法、业务计划，到角色描述和营销口号。在本示例中，我们将使用API创建使用虚拟现实进行健身的创意。

```
头脑风暴一些结合VR和健身的想法
```

如果需要，您可以通过在提示中包含一些示例来提高响应质量。

## 对话

API非常擅长与人类甚至自己进行对话。只需几行指令，我们就可以看到API作为智能客服聊天机器人，不会感到慌乱，而是能够智能地回答问题，或者作为一个机智的对话伙伴，制造笑话和双关语。关键在于告诉API它应该如何行事，然后提供一些例子。

```
以下是与AI助手进行的对话示例。助手是乐于助人，有创意，聪明且非常友好。
人类：你好，你是谁？ AI：我是OpenAI创建的AI。我今天能帮你什么忙吗？ 
人类：
```

这就是创建一个能够进行对话的聊天机器人所需的全部。在其简单性的背后，有几件值得关注的事情：

1. **我们告诉API意图**，但我们也告诉它如何行事。就像其他提示一样，我们提示API表示什么，但我们还添加了另一个关键细节：我们明确告诉它如何与短语“助手乐于助人，有创意，聪明且非常友好”交互。 如果没有这个指令，API可能会偏离轨道，模仿它正在与之交互的人，并变得讽刺或其他我们想要避免的行为。&#x20;
2. **我们给API赋予一个身份**。在开始时，我们让API作为一个AI助手回答。虽然API没有内在的身份，但这有助于它以尽可能接近真相的方式进行回答。您可以在其他方面使用身份创建其他类型的聊天机器人。如果您告诉API以生物学研究科学家的身份回答，您将得到类似于该背景下所期望的智能和周到的评论。

```
Marv是一个聊天机器人，不情愿地用讽刺的回答来回答问题：
你：一公斤有多少磅？
Marv：又来了？一公斤等于2.2磅。请记下这个。 
你：HTML代表什么？ 
Marv：Google太忙了吗？超文本标记语言。T代表着未来要问更好的问题。 
你：第一架飞机是什么时候飞行的？ 
Marv：1903年12月17日，威尔伯和奥维尔·莱特进行了第一次试飞。我希望他们能过来把我带走。
你：生命的意义是什么？
Marv: 我不确定。我会问我的朋友谷歌。 
你: 为什么天空是蓝色的? 
```

为了创建一个有趣且有些有用的聊天机器人，我们提供几个问题和答案示例，向API展示如何回复。只需要几个讽刺性的回应，API就能掌握模式并提供无数挖苦人心的反应。

## 转换&#x20;

API是一种语言模型，熟悉各种用于表达信息的单词和字符的方式。这包括自然语言文本、代码以及英语以外的其他语言。该API还能够理解内容，从而使其能够总结、转换并以不同的方式表达它。&#x20;

## 翻译&#x20;

在此示例中，我们展示了如何将API从英语转换为法语、西班牙语和日本语：

```
 将以下内容翻译成法语、西班牙语和日本語： What rooms do you have available? 
```

这个例子之所以有效，是因为API已经掌握了这些语言，所以无需尝试教授它们。 如果您想将英文翻译成API不熟悉的一种语言，则需要提供更多示例甚至[微调模型](https://platform.openai.com/docs/guides/fine-tuning)才能流利地完成。

## 转换&#x20;

在这个例子中，我们将电影的名称转换成表情符号。这展示了API适应捕捉模式和与其他字符一起工作的能力。&#x20;

```
将电影标题转换为表情符号。 回到未来：👨👴🚗🕒 蝙蝠侠：🤵🦇 变形金刚：🚗🤖 星球大战： 
```

## 总结

&#x20;该API能够理解文本的上下文并以不同方式重新表述它。在这个例子中，我们从一个更长、更复杂的文本段落中创建一个孩子可以理解的解释。这说明了该API对语言有深刻的理解。

```
 为二年级学生概括一下： 木星是距离太阳第五远且体积最大的行星。
 它是气态巨行星，质量仅相当于太阳质量千分之一，但比其他所有行星加起来还要多两倍半。
 木星是天空中肉眼可见度最高亮度物体之一，在记载历史之前就已被古代文明所知晓，
 并以罗马神话中众神之王朱庇特（Jupiter）命名[19] 。
 从地球上观察时，木星足以发出足以产生可见阴影反射光线，并且平均而言，
 在月亮和金星后是天空自然物体中第三亮的。
```

## &#x20;完成&#x20;

虽然所有提示都会导致完成，但在您希望API接替您工作时，请考虑将文本完成视为其自身任务。例如，如果给定此提示，则API将继续关于垂直农业方面思路训练。您可以降低温度设置以使API更专注于提示意图或增加温度设置以使其偏离主题。

```
 垂直农业提供了一个新颖的解决方案来实现食品本地化生产、减少运输成本和... 
```

以下提示显示如何使用完整性帮助编写React组件。我们向API发送一些代码，并且由于它具有React库的理解而能够继续执行剩余部分。我们建议使用我们Codex模型处理涉及理解或生成代码等任务。欲了解详情，请访问我们 的代码指南 。

```javascript
 import React from 'react'; const HeaderComponent = () => ( 
```

事实回答 该API具有从数据学习到很多知识点，并提供听起来非常真实但实际上是虚构答案的能力 。限制 API 制造答案可能性有两种方法:

1. 为 API 提供基础事实信息, 如果你提供给 API 要回答问题(如 Wikipedia 条目) 的正文内容, 它就不那么容易胡说八道.
2. 使用较低概率并告诉 API 如何说“我不知道”。如果 API理解在某些情况下对响应不确定性较小时说“我不知道”或某种变化合适，则会倾向于少制造答案. 在这个例子里面, 我们给出了 API 已经掌握问题和答案样例, 并举出无法得知问题样例并添加问号. 我们还把概率设定为零, 这样只要存在任何疑问, API 就更可能用 "?" 回复。

```
问：谁是蝙蝠侠？
答：蝙蝠侠是一个虚构的漫画人物。
问：什么是torsalplexity？
答：？
问：什么是Devz9？
答：？
问：乔治·卢卡斯（George Lucas）是谁？
答：乔治·卢卡斯（George Lucas）是美国电影导演和制片人，因创作《星球大战》而闻名。
问：“加利福尼亚州的首府是哪里？”
答：“萨克拉门托”。
问：“围绕地球运行的天体有哪些？”
答：“月亮”。
问: 谁是弗雷德·里克森逊(Fred Rickerson) ？
答: ?
问题: 什么是原子?
答案: 原子是组成一切事物的微小粒子。
问题: 阿尔万·芒茨(Alvan Muntz) 是谁?
等待回复
问题: Kozar-09 是什么?
等待回复
问题: 火星有几个卫星?
回答:火星有两个，分别为Phobos和Deimos。
```

## 插入文本（测试版)

完成端点还支持通过提供后缀提示来在文本中插入文本，除了前缀提示。当编写长篇文字、在段落之间转换、遵循大纲或引导模型走向结尾时，自然会出现这种需求。这也适用于代码，并且可以用于在函数或文件的中间进行插入。访问我们的代码指南以了解更多信息。&#x20;

为了说明后缀上下文对我们预测能力的重要性，请考虑提示“今天我决定做出重大改变”。有很多方法可以想象完成句子。但是如果我们现在提供故事的结局：“我的新发型得到了很多赞美！”，那么意图就变得清晰明确。&#x20;

```
我去波士顿大学读书。拿到学位后，我决定做出改变。
一个巨大的改变！ 我收拾好行囊搬到了美国西海岸。 
现在，太平洋已经成为我的最爱！ 
```

通过为模型提供额外的上下文，它可以更加可控和可操纵。然而，这对于模型来说是一项更加受限制和具有挑战性的任务。

### 最佳实践

插入文本是测试版中的新功能，您可能需要修改使用API的方式以获得更好的结果。以下是一些最佳实践：&#x20;

* 使用max\_tokens > 256。模型在插入较长完成时效果更好。如果max\_tokens太小，则模型可能会在连接后缀之前被截断。请注意，即使使用更大的max\_tokens，在生成token数量方面也只会收取实际生成token数对应的费用。&#x20;
* 优先选择finish\_reason == "stop"。当模型到达自然停止点或用户提供的停止序列时，它将设置finish\_reason为“stop”。这表明该模型已成功连接到后缀，并且是完成质量良好的一个很好信号。这对于在n>1或重新采样（见下一点）时选择几个完成之间进行选择尤其相关。&#x20;
* 重新采样3-5次。虽然几乎所有完成都与前缀相连，但在较难情况下，模型可能难以连接后缀。我们发现重新采样3或5次（或者使用k=3,5 的best\_of），并挑选具有“stop”作为其finish\_reason 的样本可以成为解决此类问题有效方法之一 。 在重新采样时，通常希望温度较高以增加多样性。 注意：如果所有返回的示例都具有finish\_reason == “length”，则很可能max\_tokens太小了，在自然地连接提示和后缀之前模型就耗尽了token数，请考虑增加max\_tokens再进行重试。&#x20;
* 尝试给出更多线索. 在某些情况下，为了更好地帮助模型生成内容 ，您可以通过提供一些示例来给出线索 ，让该模型能够遵循这些示例来确定自然停顿处。

```
如何制作美味热巧克力：
煮沸水
将热巧克力放入杯子里
向杯子中加入开水 
享受美味热巧克力

狗是忠诚的动物.
狮子是凶猛的动物.
海豚是爱玩儿的动物. 
马是雄伟的动物 。
```

## 编辑文本(Alpha测试)

可以使用edits端点来编辑文本，而不仅仅是完成它。您提供一些文本和一个修改指令，text-davinci-edit-001模型将尝试相应地进行编辑。这是翻译、编辑和调整文本的自然界面。这对于重构和处理代码也很有用。访问我们的代码指南以了解更多信息。在此初始测试期间，免费使用edits端点。 例子&#x20;

```
输入： GPT-3是一个非常好的AI， 擅长写回复， 当被问到问题时， 它会给出建议。 这是一首由它制作并押韵的诗歌。 
输出： 我是一个非常好的AI， 我擅长写回复， 当我被问到问题时， 我会给出我的建议。 这是一首由我制作并押韵的诗歌。
```

```
说明： 使其以GPT-3自己的口吻来回答(文中GPT-3改成了我)
```

```
```


# 代码完成(内测)

学习如何生成或操作代码 介绍 Codex 模型系列是我们 GPT-3 系列的后代，它经过了自然语言和数十亿行代码的训练。它在 Python 中最为强大，在包括 JavaScript、Go、Perl、PHP、Ruby、Swift、TypeScript、SQL 甚至 Shell 在内的十多种语言中也很熟练。在这个初始有限的测试期间，Codex 的使用是免费的。了解更多信息。 您可以使用 Codex 完成各种任务，包括：

* &#x20;将注释转换为代码&#x20;
* 在上下文中完成下一行或函数&#x20;
* 为应用程序查找有用库或 API 调用等知识带来便利&#x20;
* 添加注释&#x20;
* 重写代码以提高效率&#x20;

要查看 Codex 的实际运作情况，请查看我们的 [Codex JavaScript 沙盒](https://platform.openai.com/codex-javascript-sandbox)或其他[演示视频](https://www.youtube.com/playlist?list=PLOXw6I10VTv_FhQbbvYh1FvbiaPf43Ve2)。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FAQHBssuoCKKfX5jgAzF9%2Fimage.png?alt=media\&token=3f09094a-868c-4de2-ae41-2f5a4c0292cc)

## 快速开始

以下是一些可以在 [Playground](https://platform.openai.com/playground) 中测试的使用 Codex 的示例(一般可以输入到instruction中)。

**Saying "Hello" (Python)**

```python
"""
Ask the user for their name and say "Hello"
"""
```

**Create random names (Python)**

```python
"""
1. Create a list of first names
2. Create a list of last names
3. Combine them randomly into a list of 100 full names
"""
```

**Create a MySQL query (Python)**

```python
"""
Table customers, columns = [CustomerId, FirstName, LastName, Company, Address, City, State, Country, PostalCode, Phone, Fax, Email, SupportRepId]
Create a MySQL query for all customers in Texas named Jane
"""
query =
```

**Explaining code (JavaScript)**

```javascript
// Function 1
var fullNames = [];
for (var i = 0; i < 50; i++) {
  fullNames.push(names[Math.floor(Math.random() * names.length)]
    + " " + lastNames[Math.floor(Math.random() * lastNames.length)]);
}

// What does Function 1 do?
```

### 更多示例&#x20;

访问我们的[示例库](https://platform.openai.com/examples?category=code)，探索为Codex设计的更多提示。

### 最佳实践

#### **从英文翻译成中文（简体）**

从注释、数据或代码开始。您可以在我们的playgroud中使用Codex模型之一进行实验（必要时将样式指令作为注释）。要让Codex创建有用的完成，有助于考虑程序员执行任务所需的信息。这可能只是一个清晰的注释或编写有用函数所需的数据，例如变量名称或函数处理哪个类别。

```
创建一个名为'nameImporter'的函数，将名字和姓氏添加到数据库中。
```

在这个例子中，我们告诉Codex该如何命名函数以及它将要执行的任务。 这种方法甚至可以扩展到您可以向Codex提供注释和数据库模式示例的程度，从而使其编写各种数据库有用的查询请求。

```
# 表 albums, columns = [AlbumId, Title, ArtistId]
# 表 artists, columns = [ArtistId, Name]
# 表 media_types, columns = [MediaTypeId, Name]
# 表 playlists, columns = [PlaylistId, Name]
# 表 playlist_track, columns = [PlaylistId, TrackId]
# 表 tracks, columns = [TrackId, Name, AlbumId, MediaTypeId, GenreId, Composer, Milliseconds, Bytes, UnitPrice]

# 创建一个查询，以获取Adele的所有专辑。
```

当您向Codex展示数据库模式时，它能够对如何格式化查询做出明智的猜测。&#x20;

#### **指定语言**

Codex理解数十种不同的编程语言。许多共享类似的注释、函数和其他编程语法约定。通过在注释中指定语言和版本，Codex更能够提供您想要的完成功能。话虽如此，Codex在样式和语法方面相当灵活。

```
# R 语言
# 计算点阵数组中的平均距离
# Python 3
# 计算点阵数组中的平均距离
```

用你想要的方式提示Codex。如果你想让Codex创建一个网页，在注释后面放置HTML文档中的第一行代码:

```
 <!DOCTYPE html>
```

告诉Codex接下来应该做什么。同样的方法也适用于从注释中创建函数（在注释后面加上以func或def开头的新行）。

```
<!-- 创建一个标题为“Kat Katman律师”的网页 -->
<!DOCTYPE html>
```

在我们的注释后面放置\<! DOCTYPE html>可以让Codex非常清楚地知道我们想要它做什么。

```
# 创建一个函数来计数到100
def counter
```

如果我们开始编写函数，Codex 将理解接下来需要做什么。&#x20;

#### **指定库将有助于 Codex 理解您想要的内容**

Codex 知道大量的库、API 和模块。通过告诉 Codex 使用哪些库，可以通过注释或将它们导入到您的代码中，Codex 将基于这些库而不是替代方案提出建议。

```
<!-- 使用 A-Frame 版本 1.2.0 创建一个3D网站。 -->
<!-- https://aframe.io/releases/1.2.0/aframe.min.js -->

```

通过指定版本，您可以确保Codex使用最新的库。 注意：Codex可以建议有用的库和API，但一定要进行自己的研究，以确保它们对您的应用程序是安全的。&#x20;

#### **注释风格可能会影响代码质量**

对于某些语言，注释样式可以提高输出质量。例如，在使用Python时，在某些情况下使用文档字符串（三引号包装的注释）比使用井号（#）符号产生更高质量的结果。

```
"""
创建一个用户和电子邮件地址的数组
"""
```

#### **在函数内部放置注释可能会有所帮助**

推荐的编码标准通常建议将函数的描述放在函数内部。使用这种格式可以帮助Codex更清楚地理解您想要函数执行什么操作。

```
def getUserBalance(id):
    """
    在数据库“UserData”中查找用户并返回其当前账户余额。
    """
```

#### **提供更多的例子可以得到更精确的结果**

如果您需要 Codex 使用特定的样式或格式，请在请求的前面提供示例或演示，这将有助于 Codex 更准确地匹配您所需的内容。

```
"""
Create a list of random animals and species
"""
animals  = [ {"name": "Chomper", "species": "Hamster"}, {"name":
```

#### **较低的温度可以得到更精确的结果**

将API温度设置为0或接近于零（如0.1或0.2）通常在大多数情况下会产生更好的结果。与GPT-3不同，高温可以提供有用的创意和随机结果，但是使用Codex时，较高的温度可能会给您带来真正随机或不稳定的响应。 在需要Codex提供不同潜在结果的情况下，请从零开始逐步增加0.1直到找到合适变化。

#### **将任务组织成函数**

我们可以通过注释尽可能精确地指定函数应该执行什么操作来让Codex编写函数。通过编写以下注释，Codex创建了一个JavaScript计时器函数，在用户按下按钮时触发： 一个简单的JavaScript计时器

```
// 创建一个计时器，在10秒后创建一个警报
```

我们可以使用Codex来执行常见任务，例如使用众所周知的库创建Stripe API中的客户： 在Python中创建一个Stripe客户。

```
# 从电子邮件地址创建Stripe客户
```

#### **创建示例数据**

测试应用程序通常需要使用示例数据。因为Codgen是一种语言模型，它可以理解和编写自然语言，所以您可以要求Codex创建像虚构名称、产品和其他变量的数组等数据。

```
/* 创建一个旧金山天气温度数组 */
```

请求Codex执行此任务将生成如下表格：

```
var weather = [
  { month: 'January', high: 58, low: 48 },
  { month: 'February', high: 61, low: 50 },
  { month: 'March', high: 64, low: 53 },
  { month: 'April', high: 67, low: 55 },
  { month: 'May', high: 70, low: 58 },
  { month: 'June', high: 73, low: 61 },
  { month: 'July', high: 76, low: 63 },
  { month: 'August', high: 77, low: 64 },
  { month: 'September', high: 76, low: 63 },
  { month: 'October', high: 73, low: 61 },
  { month: 'November', high: 68, low: 57 },
  { month: 'December', high: 64, low: 54 }
];
```

#### **复合函数和小应用程序**

我们可以向Codex提供一个由复杂请求组成的注释，例如创建随机名称生成器或使用用户输入执行任务，只要有足够的词元，Codex就可以生成其余部分。

```
 /* 创建动物列表 创建城市列表 使用这些列表来生成关于我在每个城市动物园看到的事情的故事 */
```

#### **限制完成大小以获得更精确的结果或降低延迟**

在Codex中请求较长的完成可能会导致不准确的答案和重复。通过减少max\_tokens并设置停止标记来限制查询大小。例如，添加\n作为停止序列可将完成限制为一行代码。较小的完成还会产生较少的延迟。&#x20;

#### **使用流式传输以减少延迟**

大型Codex查询可能需要数十秒才能完成。为了构建需要更低延迟（如执行自动完成功能） 的应用程序，请考虑使用流式传输。模型完成整个完成之前将返回响应。只需要部分完成的应用程序可以通过编程方式或使用停止符号进行切断来减少延迟。 用户可以结合流媒体和重复使用来缩短延迟时间，并从API中请求多个解决方案，并使用返回第一个响应结果 。通过设置n>1 来实现此操作 。这种方法消耗更多令牌配额，因此请谨慎使用（例如 ，通过对max\_tokens 和stop 使用合理设置）。

#### **利用Codex解释代码** 。

Codex 创建和理解代码 的能力使我们能够将其用于执行诸如解释文件中代码所做内容之类 的任务 。实现此目标有一种方法是在函数后面放置一个以“This function” 或 “This application is” 开头 的注释 。 Codex通常会将其解释为说明开始并完整其余文本。 / 解释上一个功能正在做什么：

```
/* Explain what the previous function is doing: It
```

#### **解释一个 SQL 查询**

在这个例子中，我们使用 Codex 以人类可读的格式来解释一个 SQL 查询正在做什么。

```sql
SELECT DISTINCT department.name
FROM department
JOIN employee ON department.id = employee.department_id
JOIN salary_payments ON employee.id = salary_payments.employee_id
WHERE salary_payments.date BETWEEN '2020-06-01' AND '2020-06-30'
GROUP BY department.name
HAVING COUNT(employee.id) > 10;
-- 针对以上SQL提供人类可读格式的解释
--
```

#### **编写单元测试**

在Python中，只需添加注释“单元测试”并启动函数即可创建一个单元测试。

```
# Python 3
def sum_numbers(a, b):
  return a + b

# 单元测试
def
```

检查代码中的错误。通过使用示例，您可以向Codex展示如何识别代码中的错误。在某些情况下不需要示例，但是展示提供描述所需的级别和详细信息可以帮助Codex了解要查找什么以及如何解释它。（由Codex进行错误检查不应替代用户的仔细审查。）

```
/* 解释为什么之前的函数不起作用。*/
```

#### **使用源数据编写数据库函数**

就像人类程序员从了解数据库结构和列名称中受益一样，Codex可以利用这些数据帮助您编写准确的查询请求。在此示例中，我们插入数据库模式并告诉Codex要查询什么。

```
# Table albums, columns = [AlbumId, Title, ArtistId]
# Table artists, columns = [ArtistId, Name]
# Table media_types, columns = [MediaTypeId, Name]
# Table playlists, columns = [PlaylistId, Name]
# Table playlist_track, columns = [PlaylistId, TrackId]
# Table tracks, columns = [TrackId, Name, AlbumId, MediaTypeId, GenreId, Composer, Milliseconds, Bytes, UnitPrice]

# 创建一个查询，以获取Adele的所有专辑。
```

#### **语言转换**

您可以通过遵循一个简单的格式，将Codex从一种语言转换为另一种语言，其中您在注释中列出要转换的代码的语言，然后是代码和希望将其翻译成的语言的注释。

```
# 将这个从Python转换为R。
# Python 版本

[ Python code ]

# End

# R 版本
```

#### **重写库或框架的代码**

如果您想让Codex使一个函数更有效率，您可以提供需要重写的代码，并附上使用哪种格式的说明。

```
// 将此重写为一个React组件
var input = document.createElement('input');
input.setAttribute('type', 'text');
document.body.appendChild(input);
var button = document.createElement('button');
button.innerHTML = 'Say Hello';
document.body.appendChild(button);
button.onclick = function() {
  var name = input.value;
  var hello = document.createElement('div');
  hello.innerHTML = 'Hello ' + name;
  document.body.appendChild(hello);
};

// React 版本:
```

## 插入代码

“completions” 端点还支持通过提供后缀提示来在代码中插入代码，除了前缀提示。这可以用于在函数或文件的中间插入完成(下图绿色部分由AI完成补全)。&#x20;

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FcdwRgZt7hYuRyu1AHF1v%2Fimage.png?alt=media\&token=1a8f86e4-a823-4e56-8451-0c89281db58a)

通过为模型提供额外的上下文，它可以更加可控。然而，这对于模型来说是一个更受限制和具有挑战性的任务。

### 最佳实践

在测试版中，插入代码是一个新功能，您可能需要修改使用API的方式以获得更好的结果。以下是一些最佳实践：&#x20;

* **使用max\_tokens > 256**。模型更擅长插入较长的完成内容。如果max\_tokens太小，则模型可能会在连接后缀之前被截断。请注意，即使使用较大的max\_tokens，在生成令牌数量时也只会收取费用。&#x20;
* **优先选择finish\_reason == "stop"**。当模型到达自然停止点或用户提供的停止序列时，它将设置finish\_reason为“stop”。这表明该模型已成功连接到后缀，并且是完成质量良好的良好信号。这对于在n>1或重新采样（见下一点）时选择几个完成之间进行选择尤其相关。&#x20;
* **重新采样3-5次**。虽然几乎所有完成都与前缀相连，但在更难的情况下，模型可能会难以连接后缀。我们发现重新采样3或5次（或者使用k = 3,5 的best\_of），并挑选具有“stop”作为其finish\_reason标记的样本可以成为解决此类问题有效方法之一 。在重新采样时，通常希望温度较高以增加多样性。&#x20;

注意：如果返回的所有示例都具有finish\_reason == “length”，则很可能max\_tokens太小，并且模型在自然地连接提示和后缀之前耗尽了令牌数，请考虑增加max\_tokens再进行重试.

## 编辑代码

编辑端点可用于编辑代码，而不仅仅是完成它。您提供一些代码和修改指令，code-davinci-edit-001模型将尝试相应地进行编辑。这是重构和微调代码的自然界面。在此初始测试期间，使用编辑端点是免费的。

### 例子&#x20;

迭代构建程序 编写代码通常是一个需要逐步完善文本的迭代过程。通过编辑使得持续改进模型输出变得更加自然，直到最终结果被打磨出来为止。在这个例子中，我们以斐波那契数列作为示例来说明如何逐步构建代码。&#x20;

1. 编写一个函数

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FVgVvpywQS7QRmblDfACK%2Fimage.png?alt=media\&token=72227eae-a9e1-4ca9-a6ff-fad1c194133f)

2. 重构代码

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FzifJGt8zvmWLtfIy3Swk%2Fimage.png?alt=media\&token=6fc22f7d-88eb-4d61-8bfc-df5ab37d15b0)

3. 重命名函数

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2F6ErkQ8iDmyqyZ74MxsU3%2Fimage.png?alt=media\&token=4a85d1b8-af6f-449e-9d08-109830ff46aa)

4. 增加文档

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FzWHU71Ggctal9LDdTePT%2Fimage.png?alt=media\&token=3c0a4438-59f6-4813-ae76-26835fb9d9cd)

### 最佳实践&#x20;

编辑端点仍处于 alpha 阶段，我们建议遵循以下最佳实践。&#x20;

* 考虑使用空提示！在这种情况下，编辑可以类似于完成。
* 尽可能具体地说明指示。&#x20;
* 有时，模型无法找到解决方案并会导致错误。我们建议重新措辞您的指示或输入。


# 聊天完成

ChatGPT由gpt-3.5-turbo驱动，这是OpenAI最先进的语言模型。 使用OpenAI API，您可以构建自己的应用程序，并使用gpt-3.5-turbo执行以下操作：&#x20;

* 起草电子邮件或其他写作&#x20;
* 编写Python代码&#x20;
* 回答有关一组文档的问题&#x20;
* 创建对话代理&#x20;
* 为软件提供自然语言界面&#x20;
* 在各种学科中进行辅导&#x20;
* 翻译语言&#x20;
* 为视频游戏模拟角色等等。&#x20;

本指南介绍了如何调用基于聊天的语言模型API，并分享了获取良好结果的技巧。您还可以在OpenAI Playground中尝试新的聊天格式。

## 介绍

聊天模型将一系列消息作为输入，并返回一个由模型生成的消息作为输出。 虽然聊天格式旨在使多轮对话变得容易，但它同样适用于没有任何对话的单轮任务（例如以前由指令跟随模型（如text-davinci-003）提供服务的任务）。 一个示例API调用如下所示：

```python
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai

openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)
```

主要输入是消息参数。消息必须是一个消息对象数组，其中每个对象都有一个角色（“系统”、“用户”或“助手”）和内容（消息的内容）。对话可以只有1条信息，也可以填满许多页面。

&#x20;通常情况下，会先显示系统信息，然后是交替出现的用户和助手信息。&#x20;

系统信息帮助设置助手的行为。在上面的示例中，“You are a helpful assistant.”指示了该助手应如何操作。&#x20;

用户信息帮助指导助手。它们可以由应用程序最终用户生成，也可以由开发人员作为指令设置。&#x20;

助手信息帮助存储以前的响应。它们还可以由开发人员编写以提供所需行为的示例。 包括对话历史记录可在用户说明引用之前的消息时提供帮助。

在上面的示例中，“Where was it played?”这个问题只有在关于2020年世界大赛之前的消息背景下才有意义。因为模型没有过去请求方面记忆力，所有相关信息必须通过对话提供。如果一次对话无法适合模型标记限制，则需要以某种方式缩短它。

## 响应格式

API响应格式如下：

```json
{
 'id': 'chatcmpl-6p9XYPYSTTRi0xEviKjjilqrWU2Ve',
 'object': 'chat.completion',
 'created': 1677649420,
 'model': 'gpt-3.5-turbo',
 'usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},
 'choices': [
   {
    'message': {
      'role': 'assistant',
      'content': 'The 2020 World Series was played in Arlington, Texas at the Globe Life Field, which was the new home stadium for the Texas Rangers.'},
    'finish_reason': 'stop',
    'index': 0
   }
  ]
}
```

在Python中，可以使用response\['choices']\[0]\['message']\['content']提取助手的回复。 每个响应都将包括一个finish\_reason。 finish\_reason的可能值为： stop：API返回完整的模型输出 length：由于max\_tokens参数或令牌限制而导致不完整的模型输出 content\_filter：由于我们内容过滤器中的标志而省略内容 null：API响应仍在进行中或不完整

## 管理词元

语言模型以称为词元的块读取文本。在英语中，一个标记可以短至一个字符或长至一个单词（例如 a 或 apple），而在某些语言中，词元甚至可以比一个字符更短或比一个单词更长。&#x20;

例如，“ChatGPT is great！”字符串被编码成六个词元：\[“Chat”，“G”，“PT”，“ is”，“ great”，“!”]。 API 调用中的总词元数会影响以下内容：您支付每个词元的费用；写入更多词元需要更多时间；总词元必须低于模型的最大限制（gpt-3.5-turbo-0301 的最大限制为 4096 个词元）。&#x20;

输入和输出词元都计入这些数量。例如，如果您的 API 调用在消息输入中使用了 10 个词元，并且您收到了消息输出中的 20 个词元，则将向您收取30个代币。&#x20;

要查看 API 调用使用了多少代币，请检查 API 响应中的 usage 字段（例如 response\['usage']\['total\_tokens']）。

&#x20;要查看文本字符串中有多少代币而不进行 API 调用，请使用 OpenAI 的 tiktoken Python 库。示例代码可在 OpenAI Cookbook 的指南《[如何使用 tiktoken 计算代币](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb)》 中找到。&#x20;

传递给 API 的每条消息都会消耗内容、角色和其他字段中的代币数量，再加上一些幕后格式化所需额外代币。这可能稍微改变未来情况。&#x20;

如果对话包含太多符号以适合模型的最大限制（例如 gpt-3.5-turbo 的超过4096 符号），则必须截断、省略或缩小文本直到其符合规定范围。

请注意，如果从消息输入删除一条消息，则该模型将失去所有相关知识点信息 还要注意非常长时间地谈话很可能会收到不完整回复。例如，在长度为4090 词元时, gpt-3.5-turbo 对话只能得出6个词元作为答案

## 指导聊天模型&#x20;

最佳实践的指导方法可能会随着模型版本的更新而改变。以下建议适用于 gpt-3.5-turbo-0301，未来的模型可能不适用。

许多对话都以系统消息开始，以温和地指导助手。例如，这是一个用于 ChatGPT 的系统消息之一：

你是 ChatGPT，由 OpenAI 训练的大型语言模型。请尽可能简明扼要地回答。知识截止时间：{knowledge\_cutoff}，当前日期：{current\_date}

总的来说，gpt-3.5-turbo-0301 不会过多地关注系统消息，因此重要的指令通常更适合放在用户消息中。

如果模型没有产生您想要的输出，请随时尝试迭代并尝试潜在的改进。您可以尝试以下方法：

* 更明确地说明您的指令&#x20;
* 指定您想要的答案格式&#x20;
* 要求模型在确定答案之前逐步思考或辩论利弊&#x20;

如需更多提示工程思路，请阅读[ OpenAI Cookbook 指南](https://github.com/openai/openai-cookbook/blob/main/techniques_to_improve_reliability.md)以改善可靠性的技术。

除了系统消息之外，温度和最大标记数是许多选项中的两个，可用于影响聊天模型的输出。对于温度而言，较高的值（如 0.8）会使输出更随机，而较低的值（如 0.2）则会使其更加专注和确定性。在最大标记数的情况下，如果您想将响应限制为一定长度，则最大标记数可以设置为任意数。例如，如果将最大标记数值设置为 5，则可能会出现问题，因为输出将被截断，结果对用户来说没有意义。

## 聊天与完成

除了系统提示之外，温度和最大标记数是开发人员可以用来影响聊天模型输出的多种选项中的两个。对于温度，更高的值如0.8会使输出更加随机，而较低的值如0.2会使其更加集中和确定性。在最大标记数的情况下，如果您想将响应限制在某个长度内，最大标记数可以设置为任意数字。例如，如果您将最大标记数值设置为5，则会截断输出，结果对用户来说没有意义。

聊天与完成 由于gpt-3.5-turbo的性能类似于text-davinci-003，但每个词元的价格只有10%，因此我们建议大多数情况下使用gpt-3.5-turbo。

对于许多开发人员来说，过渡非常简单，只需重新编写和重新测试提示即可。

例如，如果您使用以下完成提示将英语翻译成法语：

```
将“{text}”翻译成法语。 
```

一个等效的聊天对话可以像这样：

```
[ 
{"role": "system", "content": "您是一个有帮助的助手，可以将英语翻译成法语。"}, 
{"role": "user", "content": "将以下英文文本翻译成法语：“{text}”"} 
]
```

甚至只需用户消息：

```
 [ {"role": "user", "content": "将以下英文文本翻译成法语：“{text}”"} ]
```

## FAQ

### GPT-3.5 Turbo是否支持微调？

不支持。截至2023年3月1日，您只能对基础GPT-3模型进行微调。有关如何使用微调模型的更多详细信息，请参阅微调指南。

### 您是否会存储通过API传递的数据？

截至2023年3月1日，我们会保留您的API数据30天，但不再使用通过API发送的数据来改善我们的模型。在我们的数据使用政策中了解更多信息。

### 如何添加内容审核层？

如果您想向Chat API的输出添加审核层，可以按照我们的审核指南进行操作，以防止显示违反OpenAI使用政策的内容。


# 图片生成

学习如何使用我们的DALL·E模型生成或编辑图像

## 介绍

&#x20;Images API提供了三种与图像交互的方法：

* 基于文本提示从头开始创建图像
* 根据新的文本提示对现有图像进行编辑
* 创建现有图像的变化版本

本指南介绍了使用这三个API端点的基础知识，并提供了有用的代码示例。要看它们的实际效果，请查看我们的DALL·E预览应用程序。

Images API目前处于测试版。在此期间，API和模型将根据您的反馈不断发展。为了确保所有用户都能轻松进行原型设计， 默认的速率限制是每分钟50张图像。如果您想增加速率限制，请查看此帮助中心文章。随着我们了解更多有关使用和容量要求的信息，我们将增加默认速率限制。

用法： 生成图像： 图像生成端点允许您根据文本提示创建原始图像。生成的图像可以具有256x256、512x512或1024x1024像素的尺寸。较小的尺寸生成速度更快。您可以使用n参数一次请求1-10个图像。

```python
response = openai.Image.create(
  prompt="a white siamese cat",
  n=1,
  size="1024x1024"
)
image_url = response['data'][0]['url']
```

描述得越详细，你或你的最终用户得到想要的结果的可能性就越大。你可以在 DALL·E 预览应用程序中探索更多提示灵感的示例。这里是一个快速的例子：

| 提示                                  | 生成                                                                                                                                                                                                                  |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 一只白色暹罗猫                             | ![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FyYyAKxnPInRn0NPMxFQZ%2Fimage.png?alt=media\&token=3282e78f-7d9e-4be3-b2b0-61ed0ac076c4) |
| 一张特写的白色暹罗猫的摄影画作，瞪大好奇的眼睛，耳朵被背景的光线照亮。 | ![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FPeyn6oFy73TqfVdaqgo2%2Fimage.png?alt=media\&token=50743ddd-97d5-4048-980b-4a23b8c53967) |

每张图片都可以通过response\_format参数以URL或Base64数据的形式返回。URL会在一小时后过期。

### 编辑&#x20;

图像编辑端点允许您通过上传蒙版来编辑和扩展图像。蒙版的透明区域指示图像应该被编辑的位置，提示应该描述完整的新图像，而不仅仅是被擦除的区域。这个端点可以实现像我们的DALL·E预览应用程序中的编辑器那样的体验。

```python
response = openai.Image.create_edit(
  image=open("sunlit_lounge.png", "rb"),
  mask=open("mask.png", "rb"),
  prompt="A sunlit indoor lounge area with a pool containing a flamingo",
  n=1,
  size="1024x1024"
)
image_url = response['data'][0]['url']
```

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FY3Vwh0P2Wns54cXZlONg%2Fimage.png?alt=media\&token=35a06d42-e64b-49dc-97c6-c82d7621907c)

> 提示词：一个阳光明媚的室内休息区，里面有一个装着火烈鸟的游泳池。

上传的图像和掩模必须都是小于4MB的正方形PNG图像，并且它们必须具有相同的尺寸。生成输出时，掩模的非透明区域不会被使用，因此它们不一定需要与原始图像匹配，就像上面的示例一样。

### 变体&#x20;

图像变体端点允许您生成给定图像的一个变体。

```python
response = openai.Image.create_variation(
  image=open("corgi_and_cat_paw.png", "rb"),
  n=1,
  size="1024x1024"
)
image_url = response['data'][0]['url']
```

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2Ffny3UCFvfGLbGqdWhD83%2Fimage.png?alt=media\&token=e0ca9497-db5f-45e2-a341-3e85167e5f6c)

与编辑端点类似，输入图像必须是小于4MB的正方形PNG图像。

### 内容审核&#x20;

基于我们的内容政策，提示和图片会被过滤并在标记时返回错误。如果您对误报或相关问题有任何反馈，请通过我们的[帮助中心](https://help.openai.com/)与我们联系。

## 语言特定提示(只翻译NodeJS相关)

### 使用内存中的图像数据&#x20;

上面指南中的Node.js示例使用fs模块从磁盘读取图像数据。在某些情况下，您可能已经将图像数据存储在内存中。这是一个使用存储在Node.js缓冲区对象中的图像数据的API调用示例：

```javascript
// This is the Buffer object that contains your image data
const buffer = [your image data];
// Set a `name` that ends with .png so that the API knows it's a PNG image
buffer.name = "image.png";
const response = await openai.createImageVariation(
  buffer,
  1,
  "1024x1024"
);
```

### 使用TypeScript

如果您正在使用TypeScript，可能会遇到一些与图像文件参数有关的怪异问题。以下是通过显式转换参数来解决类型不匹配的示例：

```typescript
// Cast the ReadStream to `any` to appease the TypeScript compiler
const response = await openai.createImageVariation(
  fs.createReadStream("image.png") as any,
  1,
  "1024x1024"
);
```

这里有一个类似的例子，用于内存中的图像数据：

```typescript
// This is the Buffer object that contains your image data
const buffer: Buffer = [your image data];
// Cast the buffer to `any` so that we can set the `name` property
const file: any = buffer;
// Set a `name` that ends with .png so that the API knows it's a PNG image
file.name = "image.png";
const response = await openai.createImageVariation(
  file,
  1,
  "1024x1024"
);
```

### 错误处理

API请求可能由于无效输入、速率限制或其他问题而返回错误。这些错误可以通过try...catch语句处理，错误详细信息可以在error.response或error.message中找到：

```typescript
try {
  const response = await openai.createImageVariation(
    fs.createReadStream("image.png"),
    1,
    "1024x1024"
  );
  console.log(response.data.data[0].url);
} catch (error) {
  if (error.response) {
    console.log(error.response.status);
    console.log(error.response.data);
  } else {
    console.log(error.message);
  }
}
```


# 微调

学习如何为您的应用程序定制模型。

## 简介&#x20;

通过提供以下功能，Fine-tuning（微调）可以让您从API中提供的模型中获得更多：

比提示设计更高质量的结果 能够训练更多的例子，而这些例子无法适应提示 由于提示更短而节省的令牌 更低的延迟请求 GPT-3已经在开放互联网上的大量文本上进行了预训练。当给出一个只有几个例子的提示时，它通常可以直观地知道您正在尝试执行什么任务，并生成一个可信的完成结果。这通常被称为“少样本学习”。

Fine-tuning通过训练比提示中所能适应的更多的例子，从而在许多任务上获得更好的结果，从而改善了少样本学习。一旦模型经过微调，您就不需要在提示中提供示例了。这节省了成本并使延迟请求更低。

在高层次上，Fine-tuning包括以下步骤：

准备并上传训练数据 训练一个新的微调模型 使用您的微调模型 访问我们的定价页面，了解有关微调模型培训和使用的更多信息。

## 哪些模型可以进行Fine-tuning？

目前，Fine-tuning仅适用于以下基本模型：davinci、curie、babbage和ada。这些是没有任何训练后指令的原始模型（例如，text-davinci-003就有指令）。您还可以继续微调微调模型以添加其他数据，而无需从头开始。

## 安装

&#x20;我们建议使用我们的OpenAI命令行界面（CLI）。要安装此程序，请运行：

```
pip install --upgrade openai
```

（以下说明适用于版本0.9.4及以上。此外，OpenAI CLI需要Python 3。） 通过将以下行添加到您的shell初始化脚本（例如.bashrc、zshrc等）或在微调命令之前在命令行中运行它来设置OPENAI\_API\_KEY环境变量：

```
export OPENAI_API_KEY="<OPENAI_API_KEY>"
```

## 准备训练数据&#x20;

训练数据是教GPT-3说出你想要的话的方法。 您的数据必须是JSONL文档，其中每行都是与一个训练示例相对应的提示-完成对。您可以使用我们的CLI数据准备工具轻松将您的数据转换为此文件格式。

```
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
...
```

我们开发了一种工具，用于验证、提供建议和重新格式化您的数据：

```
openai tools fine_tunes.prepare_data -f <LOCAL_FILE>
```

该工具接受不同的格式，唯一的要求是它们包含一个提示列/键和一个完成列/键。您可以传递CSV、TSV、XLSX、JSON或JSONL文件，它将在指导您进行建议更改的过程后将输出保存到一个准备好进行Fine-tuning的JSONL文件中。

## 创建Fine-tuning模型&#x20;

以下假设您已经按照上述说明准备了训练数据。

使用OpenAI CLI启动Fine-tuning作业：

```
openai api fine_tunes.create -t <TRAIN_FILE_ID_OR_PATH> -m <BASE_MODEL>
```

其中，BASE\_MODEL是您要基于的基础模型的名称（ada、babbage、curie或davinci）。您可以使用suffix参数自定义Fine-tuning模型的名称。

运行上述命令会执行以下几个操作：

使用文件API上传文件（或使用已上传的文件） 创建Fine-tune作业 流式传输事件，直到作业完成（这通常需要几分钟，但如果队列中有许多作业或您的数据集很大，则可能需要几个小时） 每个Fine-tuning作业都是从一个基础模型开始的，默认为curie。模型的选择影响模型的性能和运行Fine-tuning模型的成本。您的模型可以是：ada、babbage、curie或davinci。请访问我们的价格页面了解有关Fine-tuning费率的详细信息。

在启动Fine-tuning作业后，可能需要一些时间才能完成。您的作业可能会排在我们系统中的其他作业后面，训练我们的模型可能需要几分钟或几个小时，具体取决于模型和数据集大小。如果由于任何原因中断事件流，您可以通过运行以下命令恢复它：

```
openai api fine_tunes.follow -i <YOUR_FINE_TUNE_JOB_ID>
```

## 使用fine-tuned模型&#x20;

当一个任务成功后，fine\_tuned\_model字段将被填充为模型的名称。现在，您可以将此模型指定为完成API的参数，并使用Playground进行请求。

在任务完成后，您的模型可能需要几分钟才能准备好处理请求。如果完成请求超时，则可能是因为您的模型仍在加载中。如果发生这种情况，请稍后再试几分钟。

您可以通过将模型名称作为完成请求的模型参数来开始发出请求：

OpenAI CLI:

```
openai api completions.create -m <FINE_TUNED_MODEL> -p <YOUR_PROMPT>
```

cURL

```
curl https://api.openai.com/v1/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": YOUR_PROMPT, "model": FINE_TUNED_MODEL}'
```

python:

```python
import openai
openai.Completion.create(
    model=FINE_TUNED_MODEL,
    prompt=YOUR_PROMPT)
```

Node.js

```
const response = await openai.createCompletion({
  model: FINE_TUNED_MODEL
  prompt: YOUR_PROMPT,
});
```

您可以继续在这些请求中使用所有其他完成参数，例如温度、频率惩罚、存在惩罚等，以对微调模型进行优化。&#x20;

## 删除微调模型&#x20;

要删除微调模型，您必须在组织内被指定为“所有者”。&#x20;

OpenAI CLI:

```bash
openai api models.delete -i <FINE_TUNED_MODEL>
```

cURL:

```bash
curl -X "DELETE" https://api.openai.com/v1/models/<FINE_TUNED_MODEL> \
  -H "Authorization: Bearer $OPENAI_API_KEY"
```

Python:

```python
import openai
openai.Model.delete(FINE_TUNED_MODEL)
```

## 准备数据集

Fine-tuning是一种创建针对特定用例的新模型的强大技术。在fine-tuning您的模型之前，我们强烈建议您阅读以下最佳实践和特定用例的指南。

### 数据格式

要对模型进行fine-tuning，您需要一组训练示例，每个示例都由一个单独的输入（"提示"）和其相关输出（"完成"）组成。这与使用我们的基础模型有明显不同，基础模型中您可能会输入详细的说明或多个示例。

* 每个提示应以固定的分隔符结尾，以通知模型提示何时结束并完成何时开始。一个通常很有效的简单分隔符是\n\n###\n\n。分隔符不应在任何提示中出现。&#x20;
* 由于我们的token化方法，每个完成都应以空格开头，大多数单词都会在前面加上空格。
* 每个完成都应以固定的停止序列结束，以通知模型完成何时结束。停止序列可以是\n、###或任何其他不出现在任何完成中的标记。&#x20;
* 对于推断，您应以与创建训练数据集时相同的方式格式化您的提示，包括相同的分隔符。还要指定相同的停止序列以正确截断完成。

### 一般最佳实践

微调在有更多高质量的例子时表现更好。为了微调一个比使用我们的基础模型和高质量提示表现更好的模型，您应该提供至少几百个高质量的例子，最好由人类专家审核过。从那里开始，性能往往会随着每倍增加示例数量而线性增加。增加示例数量通常是改善性能的最佳和最可靠方法。

分类器是入门最容易的模型。对于分类问题，我们建议使用ada，在微调后通常只比更强大的模型略差一点，同时速度和成本显著降低。&#x20;

如果您正在对预先存在数据集进行微调而不是从头编写提示，请务必手动检查数据以查找冒犯或不准确内容（如果可能），或者尽可能审查数据集中许多随机样本（如果它很大）。

### 具体指南&#x20;

微调可以解决各种问题，而最优的使用方式可能取决于您的具体用例。下面，我们列出了微调的最常见用例和相应的指南。

* 分类&#x20;
  * 模型是否发表了不真实的陈述？&#x20;
  * 情感分析&#x20;
  * 电子邮件分类&#x20;
* 条件生成&#x20;
  * 基于维基百科文章编写吸引人的广告&#x20;
  * 实体提取&#x20;
  * 客服聊天机器人&#x20;
  * 基于技术属性列表的产品描述&#x20;

### 分类&#x20;

在分类问题中，每个提示输入应该被分类到预定义的类别之一。对于这种类型的问题，我们建议：

* 在提示的末尾使用分隔符，例如 \n\n###\n\n。当您最终向模型发出请求时，也要附加此分隔符。
* &#x20;选择映射到单个词元的类别。在推断时，指定 max\_tokens=1，因为您只需要分类的第一个词元。
* 确保提示+完成不超过2048个词元，包括分隔符。&#x20;
* 针对每个类别至少有 \~100 个示例。&#x20;
* 在使用模型时，如果需要类别日志概率，则可以指定 logprobs=5（用于5个类别）。&#x20;
* 确保用于微调的数据集在结构和任务类型上与模型将要使用的相似。&#x20;

#### 案例研究：模型是否发表了不真实的陈述？&#x20;

假设您想确保网站广告的文本提到了正确的产品和公司。换句话说，您希望确保模型没有捏造内容。您可以微调一个分类器来过滤不正确的广告。

```
{"prompt":"公司：BHFF保险\n产品：全方位保险\n广告：满足您所有保险需求的一站式服务！\n支持:", "completion":" 是"}
{"prompt":"公司：阁楼改建专家\n产品：-\n广告：几周内拥有整齐的牙齿！\n支持:", "completion":" 否"}
```

在上面的示例中，我们使用了一个结构化输入，其中包含公司名称、产品和相关广告。作为分隔符，我们使用了\nSupported:来清楚地将提示与完成分开。有足够数量的示例时，分隔符并不会产生太大影响（通常少于0.4%），只要它不出现在提示或完成中。

&#x20;对于这种用例，我们微调了ada模型，因为它速度更快、更便宜，并且性能可与较大的模型相媲美，因为这是一个分类任务。

&#x20;现在我们可以通过发出“Completion”请求来查询我们的模型。

```
curl https://api.openai.com/v1/completions \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{
  "prompt": "Company: Reliable accountants Ltd\nProduct: Personal Tax help\nAd:Best advice in town!\nSupported:",
  "max_tokens": 1,
  "model": "YOUR_FINE_TUNED_MODEL_NAME"
}'
```

这将返回是或否。

#### 案例研究：情感分析

假设您想要获得一条推文的积极或消极程度，数据集可能如下所示：

```
{"prompt":"对新iPhone感到非常高兴！->", "completion":"积极"}
{"prompt":"@lakers 连续第三个晚上让人失望 https://t.co/38EFe43 ->", "completion":"消极"}
```

一旦模型微调完成，您可以通过在完成请求上设置logprobs=2来获取第一个完成token的对数概率。正类别的概率越高，情感相对就越高。 现在我们可以通过发出完整请求来查询我们的模型。

```
curl https://api.openai.com/v1/completions \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{
  "prompt": "https://t.co/f93xEd2 Excited to share my latest blog post! ->",
  "max_tokens": 1,
  "model": "YOUR_FINE_TUNED_MODEL_NAME"
}'
```

将返回：

```json
{
  "id": "cmpl-COMPLETION_ID",
  "object": "text_completion",
  "created": 1589498378,
  "model": "YOUR_FINE_TUNED_MODEL_NAME",
  "choices": [
    {
      "logprobs": {
        "text_offset": [
          19
        ],
        "token_logprobs": [
          -0.03597255
        ],
        "tokens": [
          " positive"
        ],
        "top_logprobs": [
          {
            " negative": -4.9785037,
            " positive": -0.03597255
          }
        ]
      },

      "text": " positive",
      "index": 0,
      "finish_reason": "length"
    }
  ]
}
```

#### 案例研究：电子邮件分类&#x20;

假设您想将收到的电子邮件归类为大量预定义的类别之一。对于大量类别的分类，我们建议您将这些类别转换为数字，这在 \~500 个类别以下效果良好。我们观察到，在数字前添加一个空格有时会略微提高性能，因为它可以进行分词处理。您可能希望按以下方式构建培训数据：

```
{"prompt":"主题：<email_subject>\n来自：<customer_name>\n日期：<date>\n内容：<email_body>\n\n###\n\n", "completion":"<numerical_category>"}
```

例如：

```
{"prompt":"主题：更新我的地址\n发件人：乔·多伊\n收件人：support@ourcompany.com\n日期：2021年06月03日\n内容：\n您好，\n我想要更新我的账单地址以匹配我的送货地址。\n请在完成后告知我。\n谢谢，\n乔。\n###\n", "completion":"4"}
```

在上面的示例中，我们使用了一个最多包含2043个词元的传入电子邮件作为输入。（这允许4个标记分隔符和一个标记完成，总计为2048。）作为分隔符，我们使用了\n\n###\n\n，并删除了电子邮件中任何出现的###。

### 条件生成&#x20;

条件生成是一个问题，需要在给定某种输入的情况下生成内容。这包括改写、摘要、实体提取、根据规格编写产品描述、聊天机器人等。对于这种类型的问题，我们建议：

* &#x20;在提示末尾使用分隔符，例如\n\n###\n\n。
* 记得在最终向模型发出请求时也附加此分隔符。&#x20;
* 在完成末尾使用结束标记，例如END。&#x20;
* 记得将结束标记添加为推理期间的停止序列，例如stop=\[" END"]。&#x20;
* 目标至少达到\~500个示例&#x20;
* 确保提示+完成不超过2048个词元（包括分隔符）
* &#x20;确保示例具有高质量并遵循相同的所需格式&#x20;
* 确保用于微调的数据集与模型将要用于的任务结构和类型非常相似 对于这些用例，使用较低学习率和仅1-2个时代通常效果更好

#### &#x20;案例研究：基于维基百科文章撰写引人入胜的广告&#x20;

这是一种生成性用例，因此您希望确保提供的样本具有最高质量，因为经过微调的模型将尝试模仿给定示例的风格（和错误）。一个良好起点大约是500个示例。样本数据集可能如下所示：

```
{"prompt":"<产品名称>\n<Wikipedia 描述>\n\n###\n\n",
"completion":" <吸引人的广告> 结束"}
```

例如：

```
{"prompt":"三星Galaxy Feel\n三星Galaxy Feel是由三星电子专门为日本市场开发的Android智能手机。该手机于2017年6月发布，由NTT Docomo销售。它运行在Android 7.0（Nougat）上，拥有4.7英寸显示屏和3000毫安时电池。\n软件\n三星Galaxy Feel运行在Android 7.0（Nougat）上，但可以后期更新到Android 8.0（Oreo）。\n硬件\n三星Galaxy Feel配备了一块4.7英寸超级AMOLED高清显示屏、1600万像素后置摄像头和500万像素前置摄像头。它还配备了一个3000毫安时电池、1.6 GHz八核ARM Cortex-A53 CPU和一个ARM Mali-T830 MP1 700 MHz GPU。它内置32GB存储空间，可通过microSD扩展至256GB。除了其软件和硬件规格外，三星还推出了独特的手机壳孔以适应日本人个性化移动电话的偏好。 Galaxy Feel的电池也被誉为主要卖点之一，因为市场青睐续航时间更长的手持设备。该设备还具有防水功能，并支持使用单独销售天线进行1seg数字广播。\n\n###\n\n",
"completion":"正在寻找一款全能型智能手机？不用再找了！来试试我们最新款的Samsung Galaxy Feel吧！这款机身轻薄、设计精美的智能手机拥有高质量图片和视频功能，并且获得过奖项，在续航方面表现优异。END"}
```

在这里，我们使用了多行分隔符，因为维基百科文章包含多个段落和标题。我们还使用了一个简单的结束标记，以确保模型知道何时完成。&#x20;

#### 案例研究：实体提取&#x20;

这类似于语言转换任务。为了提高性能，最好按字母顺序或与原始文本中出现的顺序相同地排序不同的提取实体。这将帮助模型跟踪需要按顺序生成的所有实体。数据集可能如下所示：

```
{"prompt":"<任意文本，例如新闻文章>\n\n###\n\n", "completion":"<实体列表，用换行符分隔> END"}
```

例如：

```
{"prompt":"由于新冠病例上升和对所谓的印度变异体尼泊尔突变的担忧，自周二起葡萄牙将被从英国的绿色旅行名单中移除。它将加入琥珀名单，这意味着度假者不应该前往，并且回国人员必须隔离10天...\n\n###\n\n",
"completion":" 葡萄牙\n英国\n尼泊尔突变\n印度变异体 结束"}
```

多行分隔符效果最佳，因为文本可能包含多行。理想情况下，输入提示的类型应具有高度的多样性（新闻文章、维基百科页面、推特、法律文件等），这反映了在提取实体时可能遇到的文本类型。

#### &#x20;案例研究：客户支持聊天机器人

&#x20;聊天机器人通常会包含与对话相关的上下文（订单详情）、迄今为止对话的摘要以及最近的消息。对于这种用例，同一过去的对话可以生成数据集中多个行，在每次代理生成完成时都带有稍微不同的上下文。由于它可能涉及不同类型的请求和客户问题，因此该用例将需要几千个示例。为确保性能高质量，我们建议审核对话样本以确保代理消息质量。摘要可以使用单独调整后文字转换模型来生成。数据集如下所示：

```
{"prompt":"摘要：<交互至今的概述>\n\n具体信息：<例如自然语言中的订单详情>\n\n###\n\n客户：<消息1>\n代理人：<响应1>\n客户：<消息2>\n代理人：", "completion":"<响应2> \ n"}
{"prompt":"摘要：<交互至今的概述>\n\n具体信息：<例如自然语言中的订单详情>\n\n###\n\n客户：<消息1> \ n代理人： <响应1> \ n客户： <消息2> \ n代理人： <响应2> \ n客户： <消息3> \ n代理人:", "completion": "<response3 >\ N"}
```

在这里，我们有意地将不同类型的输入信息分开，但保持了客户代理对话框在提示和完成之间的相同格式。所有完成只应由代理人完成，并且在进行推断时可以使用 \n 作为停止序列。&#x20;

#### 案例研究：基于技术属性清单的产品描述&#x20;

在这里，将输入数据转换为自然语言非常重要，这可能会导致更好的性能。例如以下格式：

```
{"prompt":"物品=手提包，颜色=军绿色，价格=$99，尺码=S->", "completion":"这款时尚的小绿色手提包将为您的造型增添独特的风格，而不会花费您太多钱。"}
```

不会像如下方式一样有效：

```
{"prompt":"物品是手提包。颜色为军绿色。价格属于中档。尺寸较小。->", "completion":"这款时尚的小型绿色手提包将为您的造型增添独特的风格，而不会花费太多钱。"}
```

为了获得高性能，请确保完成是基于提供的描述。如果经常查阅外部内容，则以自动化方式添加此类内容将改善性能。如果描述基于图像，则使用算法提取图像的文本描述可能会有所帮助。由于完成只有一句话长，因此我们可以在推理过程中使用“。”作为停止序列。

## 高级用法

### 自定义模型名称

您可以使用后缀参数将最多40个字符的后缀添加到您的微调模型名称中。

OpenAI CLI:

```
openai api fine_tunes.create -t test.jsonl -m ada --suffix "custom model name"
```

生成的名称将是：

```
ada:ft-your-org:custom-model-name-2022-02-15-04-21-04
```

### 分析您的微调模型

我们为每个作业附加一个结果文件，一旦它完成，它将被列出。检索微调时，结果文件ID将被列出，并在查看微调事件时列出。您可以下载这些文件：

OpenAI CLI:

```bash
openai api fine_tunes.results -i <YOUR_FINE_TUNE_JOB_ID>
```

CURL:

```
curl https://api.openai.com/v1/files/$RESULTS_FILE_ID/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" > results.csv
```

\_results.csv文件包含每个训练步骤的一行，其中一步骤指的是在一批数据上进行前向和后向传递的操作。除了步数，每行还包含以下与该步骤相对应的字段：

* elapsed\_tokens：模型迄今为止看到的词元数（包括重复）&#x20;
* elapsed\_examples：模型迄今为止看到的示例数（包括重复），其中一个示例是批次中的一个元素。例如，如果batch\_size = 4，则每个步骤将使elapsed\_examples增加4。
* training\_loss：训练批次的损失&#x20;
* training\_sequence\_accuracy：在训练批次中，模型预测的标记与真实的标记完全匹配的完成百分比。例如，如果您的数据包含完成\[\[1, 2]，\[0, 5]，\[4, 2]]，并且模型预测\[\[1, 1]，\[0, 5]，\[4, 2]]，则准确性将为2/3 = 0.67&#x20;
* training\_token\_accuracy：模型正确预测的训练批次中的标记百分比。例如，如果您的数据包含完成\[\[1, 2]，\[0, 5]，\[4, 2]]，并且模型预测\[\[1, 1]，\[0, 5]，\[4, 2]]，则准确性将为5/6 = 0.83

### 分类特定的度量标准&#x20;

我们还提供了生成结果文件中的其他分类特定度量标准的选项，例如准确性和加权F1分数。这些指标定期针对整个验证集进行计算，并在微调结束时计算。您将在结果文件中看到它们作为其他列。

要启用此功能，请设置--compute\_classification\_metrics参数。另外，您必须提供验证文件，并设置classification\_n\_classes参数（用于多类分类）或classification\_positive\_class参数（用于二进制分类）。

OpenAI CLI:

```bash
# For multiclass classification
openai api fine_tunes.create \
  -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_OR_PATH> \
  -m <MODEL> \
  --compute_classification_metrics \
  --classification_n_classes <N_CLASSES>

# For binary classification
openai api fine_tunes.create \
  -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_OR_PATH> \
  -m <MODEL> \
  --compute_classification_metrics \
  --classification_n_classes 2 \
  --classification_positive_class <POSITIVE_CLASS_FROM_DATASET>
```

\
如果你设置了--compute\_classification\_metrics，以下指标将在你的结果文件中显示：

#### 对于多类分类：

* classification/accuracy：准确率&#x20;
* classification/weighted\_f1\_score：加权F1分数

#### 对于二元分类

以下指标基于分类阈值为0.5（即当概率> 0.5时，将一个示例分类为属于正类）。

* classification/accuracy：准确率
* &#x20;classification/precision：精确率&#x20;
* classification/recall：召回率
* &#x20;classification/f{beta}：F-beta分数&#x20;
* classification/auroc：AUROC
* &#x20;classification/auprc：AUPRC

请注意，这些评估假定您使用文本标签来表示分词为单个词元的类，如上所述。如果这些条件不成立，您得到的数字可能会错误。

### 验证

&#x20;您可以为验证保留一些数据。验证文件与训练文件具有完全相同的格式，您的训练和验证数据应互不重叠。

如果您在创建微调作业时包含验证文件，则生成的结果文件将包括在训练期间定期评估微调模型在验证数据上的表现。\
OpenAI CLI:

```bash
openai api fine_tunes.create -t <TRAIN_FILE_ID_OR_PATH> \
  -v <VALIDATION_FILE_ID_OR_PATH> \
  -m <MODEL>
```

如果您提供了一个验证文件，在训练期间我们会定期计算验证数据批次上的指标。在结果文件中，您将看到以下额外的指标：

* validation\_loss：验证批次的损失值。&#x20;
* validation\_sequence\_accuracy：验证批次中完成度百分比，其中模型预测的标记与真实标记完全匹配。例如，如果您的数据包含完成度\[\[1，2]，\[0，5]，\[4，2]]，而模型预测为\[\[1，1]，\[0，5]，\[4，2]]，则准确率为2/3 = 0.67（假设batch\_size为3）。&#x20;
* validation\_token\_accuracy：模型正确预测的验证批次中标记的百分比。例如，如果您的数据包含完成度\[\[1，2]，\[0，5]，\[4，2]]，而模型预测为\[\[1，1]，\[0，5]，\[4，2]]，则准确率为5/6 = 0.83（假设batch\_size为3）。&#x20;

### 超参数&#x20;

我们已选择默认超参数，可在各种用例中运行良好。唯一需要的参数是训练文件。

但是，调整用于微调的超参数通常可以产生生成更高质量输出的模型。特别是，您可能想配置以下内容：

* model：要微调的基础模型的名称。您可以选择“ada”、“babbage”、“curie”或“davinci”中的一个。要了解有关这些模型的更多信息，请参见模型文档。&#x20;
* n\_epochs - 默认值为4。训练模型的时期数。一个时期指的是一次完整的通过训练数据集的循环。&#x20;
* batch\_size - 默认值为训练集中示例数的约0.2％，上限为256。批处理大小是用于训练单个前向和后向传递的训练示例数。通常，我们发现更大的批量大小对于更大的数据集效果更好。
* learning\_rate\_multiplier - 默认值为0.05、0.1或0.2，具体取决于最终批量大小。微调学习率是用于预训练的原始学习率乘以此乘数。我们建议尝试在0.02到0.2的范围内的值，以查看哪个产生最佳结果。从经验上看，我们发现更大的学习率往往在处理更大的批量大小时表现更好。&#x20;
* compute\_classification\_metrics - 默认值为False。如果为True，则针对分类任务的微调，在每个时期结束时在验证集上计算分类特定的指标（准确性、F-1分数等）。 要配置这些额外的超参数，请通过OpenAI CLI的命令行标志传递它们，例如：

```
openai api fine_tunes.create \
  -t file-JD89ePi5KMsB3Tayeli5ovfW \
  -m ada \
  --n_epochs 1
```

从已经进行微调的模型继续微调 如果您已经对模型进行了微调，并且现在有额外的训练数据需要加入，您可以从模型进行继续微调。这样创建的模型能够从所有训练数据中学习，而不需要重新从头开始训练。

为此，在创建新的微调作业时，传递微调模型名称（例如 -m curie:ft-\<org>-\<date>）。其他训练参数无需更改，但是如果您的新训练数据比以前的训练数据小很多，您可能会发现将learning\_rate\_multiplier减少2到4倍是有用的。

### 权重和偏置&#x20;

您可以将微调结果与Weights & Biases同步，以跟踪实验、模型和数据集。

要开始使用，您需要一个Weights & Biases帐户和一个付费的OpenAI计划。为确保您使用的是最新版本的openai和wandb，请运行:

```bash
pip install --upgrade openai wandb
```

要将您的微调与Weights＆Biases同步，请运行：

```bash
openai wandb sync
```

## 示例笔记本&#x20;

### 分类&#x20;

[finetuning-classification.ipynb ](https://github.com/openai/openai-cookbook/blob/main/examples/Fine-tuned_classification.ipynb)

此笔记本将演示如何微调模型，以对输入文本是否与棒球或曲棍球相关进行分类。我们将在笔记本中执行以下四个步骤：&#x20;

* 数据探索将概述数据源和示例的外观。
* 数据准备将把我们的数据源转换为可用于微调的jsonl文件。&#x20;
* 微调将启动微调作业并解释所得到的模型性能。&#x20;
* 使用该模型将演示如何向经过微调的模型发出请求以获取预测结果。

### 回答问题

[olympics-1-collect-data.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/fine-tuned_qa/olympics-1-collect-data.ipynb)

[olympics-2-create-qa.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/fine-tuned_qa/olympics-2-create-qa.ipynb)

[olympics-3-train-qa.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/fine-tuned_qa/olympics-3-train-qa.ipynb)

该项目的想法是创建一个问答模型，基于提供的几段文本。基于GPT-3模型在回答问题时表现良好，当答案包含在段落中时，但如果答案不包含在其中，则基础模型往往会尽力回答，导致混淆的答案。 为了创建仅在有足够上下文情况下才回答问题的模型，我们首先创建了一个基于文本段落的问题和答案数据集。为了训练模型只有当存在答案时才回答，在这些情况下我们还添加对抗性示例，其中问题与上下文不匹配。在这些情况下，我们要求模型输出“没有足够的上下文来回答问题”。 我们将通过三个笔记本执行此任务：&#x20;

* 第一个笔记本专注于收集最近数据，在预训练期间GPT-3没有看到过这些数据。 我们选择了2020年奥运会（实际上发生在2021年夏季）作为主题，并下载了713个独特页面。 我们按单独部分组织数据集，并将其用作询问和回复问题的背景。&#x20;
* 第二个笔记本将利用Davinci-instruct根据Wikipedia章节提出一些问题，并根据该章节回答回应那些问题。
* &#x20;第三个笔记本将利用上下文、问句和解释对数据集来额外地创造对抗性问句和背景对, 在这种情况下, 该模型被提示以"无足够背景信息来解析此类问题" 来进行响应. 我们还将训练鉴别器模型, 以预测是否可以根据环境或其他因素来解析某一类特定类型或者所有类型 的相关内容.


# 嵌入

OpenAI的文本嵌入（embeddings）可以测量文本字符串之间的相关性。嵌入通常用于：

* 搜索（结果按查询字符串的相关性排序）&#x20;
* 聚类（将文本字符串按相似性分组）&#x20;
* 推荐（推荐具有相关文本字符串的物品）&#x20;
* 异常检测（识别具有较少相关性的异常值）&#x20;
* 多样性测量（分析相似性分布）&#x20;
* 分类（将文本字符串按其最相似的标签分类）&#x20;

嵌入是由浮点数组成的向量（列表）。两个向量之间的距离可以衡量它们之间的相关性。小距离表明高相关性，大距离则表明低相关性。

请访问我们的[定价](https://openai.com/api/pricing/)页面了解嵌入的价格。请求基于输入中的token数量计费。

要了解嵌入的实际运用，请查看本文中的示例：

* 分类&#x20;
* 主题聚类
* 搜索
* 推荐

## 如何获取嵌入&#x20;

要获取嵌入，将您的文本字符串发送到嵌入API端点，并选择一个嵌入模型ID（例如text-embedding-ada-002）。响应将包含一个嵌入，您可以提取、保存和使用。

示例请求:

```shell
# 获取嵌入
curl https://api.openai.com/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{"input": "Your text string goes here",
       "model":"text-embedding-ada-002"}'
```

示例响应:

```
{
  "data": [
    {
      "embedding": [
        -0.006929283495992422,
        -0.005336422007530928,
        ...
        -4.547132266452536e-05,
        -0.024047505110502243
      ],
      "index": 0,
      "object": "embedding"
    }
  ],
  "model": "text-embedding-ada-002",
  "object": "list",
  "usage": {
    "prompt_tokens": 5,
    "total_tokens": 5
  }
}
```

在[OpenAI Cookbook](https://github.com/openai/openai-cookbook/)中查看更多Python代码示例。 使用OpenAI嵌入时，请记住它们的限制和风险。

## 嵌入模型

&#x20;OpenAI 提供了一个第二代嵌入模型（在模型 ID 中标记为 -002）和 16 个第一代模型（在模型 ID 中标记为 -001）。 我们建议几乎所有用例都使用 text-embedding-ada-002。它更好、更便宜、更简单易用。请阅读博客文章公告。

| 模型版本 | 分词器          | 最大输入词元 | 知识截止时间   |
| ---- | ------------ | ------ | -------- |
| V2   | cl100k\_base | 8191   | Sep 2021 |
| V1   | GPT-2/GPT-3  | 2046   | Aug 2020 |

使用按输入词元计价，每1000个词元的费率为0.0004美元，或者大约1美元可以翻译3000页（假设每页有800个词元）：

| 模型                     | 每美元的粗糙页面数 | BEIR 搜索评估的示例性能 |
| ---------------------- | --------- | -------------- |
| text-embedding-ada-002 | 3000      | 53.9           |
| *-davinci-*-001        | 6         | 52.8           |
| *-curie-*-001          | 60        | 50.9           |
| *-babbage-*-001        | 240       | 50.4           |
| *-ada-*-001            | 300       | 49.0           |

### 第二代模型

| 模型                     | 分词器          | 最大词元数 | 输出维度 |
| ---------------------- | ------------ | ----- | ---- |
| text-embedding-ada-002 | cl100k\_base | 8191  | 1536 |

### 第一代模型（不推荐）

官方也不推荐使用其他的第一代模型，这边就不翻译了

## 使用案例

这里我们展示一些代表性的使用案例。接下来的例子中，我们将使用[亚马逊美食评论数据集](https://www.kaggle.com/snap/amazon-fine-food-reviews)。

### 获取嵌入

该数据集包含截至2012年10月亚马逊用户留下的共568,454条食品评论。我们将使用最近1,000条评论的子集进行说明。这些评论是用英语编写的，往往是积极或消极的。每个评论都有一个ProductId、UserId、Score、评价标题（Summary）和评价正文（Text）。例如：

<table><thead><tr><th>产品 ID</th><th>用户 ID</th><th width="78">得分</th><th>总结</th><th>文本</th></tr></thead><tbody><tr><td>B001E4KFG0</td><td>A3SGXH7AUHU8GW</td><td>5</td><td>优质狗粮</td><td>我已经买了几罐活力饮料...</td></tr><tr><td>B00813GRG4</td><td>A1D87F6ZCVE5NK</td><td>1</td><td>不如广告所述</td><td>产品标签上写着巨型盐腌花生...</td></tr></tbody></table>

我们将把评论摘要和评论文本合并成一个组合文本。模型将对这个组合文本进行编码，并输出一个单一的向量嵌入。

[Obtain\_dataset.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Obtain_dataset.ipynb)

```python
def get_embedding(text, model="text-embedding-ada-002"):
   text = text.replace("\n", " ")
   return openai.Embedding.create(input = [text], model=model)['data'][0]['embedding']
 
df['ada_embedding'] = df.combined.apply(lambda x: get_embedding(x, model='text-embedding-ada-002'))
df.to_csv('output/embedded_1k_reviews.csv', index=False)
```

要从保存的文件中加载数据，您可以运行以下命令：

```python
import pandas as pd
 
df = pd.read_csv('output/embedded_1k_reviews.csv')
df['ada_embedding'] = df.ada_embedding.apply(eval).apply(np.array)
```

### 数据2D可视化

[Visualizing\_embeddings\_in\_2D.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Visualizing_embeddings_in_2D.ipynb)

嵌入的大小取决于底层模型的复杂性。为了可视化这个高维数据，我们使用t-SNE算法将数据转换成二维。 我们根据评论者给出的星级评分来着色每个单独的评论：&#x20;

* 1星：红色&#x20;
* 2星：深橙色&#x20;
* 3星：金色&#x20;
* 4星：青绿色&#x20;
* 5星：深绿色

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2F3yks5IvuNQxNOdluQdwP%2Fimage.png?alt=media\&token=c2214930-9edb-40f5-ba40-e7d0d5db470d)

可视化似乎产生了大约3个聚类，其中一个主要是负面评价。

```python
import pandas as pd
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import matplotlib
 
df = pd.read_csv('output/embedded_1k_reviews.csv')
matrix = df.ada_embedding.apply(eval).to_list()
 
# Create a t-SNE model and transform the data
tsne = TSNE(n_components=2, perplexity=15, random_state=42, init='random', learning_rate=200)
vis_dims = tsne.fit_transform(matrix)
 
colors = ["red", "darkorange", "gold", "turquiose", "darkgreen"]
x = [x for x,y in vis_dims]
y = [y for x,y in vis_dims]
color_indices = df.Score.values - 1
 
colormap = matplotlib.colors.ListedColormap(colors)
plt.scatter(x, y, c=color_indices, cmap=colormap, alpha=0.3)
plt.title("Amazon ratings visualized in language using t-SNE")
```

### 将嵌入作为文本特征编码器用于机器学习算法

[Regression\_using\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Regression_using_embeddings.ipynb)

嵌入可以作为机器学习模型中通用的自由文本特征编码器。如果一些相关输入是自由文本，那么加入嵌入将提高任何机器学习模型的性能。嵌入也可以作为ML模型中分类特征编码器使用。如果分类变量名称有意义且数量众多（例如职位名称），则此方法最具价值。相似度嵌入通常比搜索嵌入在此任务上表现更好。&#x20;

我们观察到，通常情况下，嵌入表示的信息密度很高。例如，使用SVD或PCA降低输入维数即使只有10％，在特定任务的下游性能方面通常会导致更差的结果。

&#x20;该代码将数据分成训练集和测试集，并将被以下两个用例使用：回归和分类。

```python
from sklearn.model_selection import train_test_split
 
X_train, X_test, y_train, y_test = train_test_split(
    list(df.ada_embedding.values),
    df.Score,
    test_size = 0.2,
    random_state=42
)
```

#### 使用嵌入特征的回归&#x20;

嵌入提供了一种优雅的方法来预测数值。在这个例子中，我们根据评论文本预测评论者的星级评分。由于嵌入所包含的语义信息非常丰富，即使只有很少的评论，也可以得到不错的预测结果。&#x20;

我们假设得分是1到5之间的连续变量，并允许算法预测任何浮点值。机器学习算法将预测值与真实得分之间的距离最小化，并取得了0.39 的平均绝对误差，这意味着平均而言，预测偏差不到半颗星。

```python
from sklearn.ensemble import RandomForestRegressor
 
rfr = RandomForestRegressor(n_estimators=100)
rfr.fit(X_train, y_train)
preds = rfr.predict(X_test)
```

### 使用嵌入特征进行分类

[Classification\_using\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Classification_using_embeddings.ipynb)

这一次，我们不再让算法预测1到5之间的任意值，而是尝试将评论中的星级精确分类为5个档次，范围从1星到5星。&#x20;

经过训练后，模型学会了更好地预测1和5星评价，而对于更微妙的评价（2-4星），由于情感表达不够极端可能效果较差。

```python
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, accuracy_score
 
clf = RandomForestClassifier(n_estimators=100)
clf.fit(X_train, y_train)
preds = clf.predict(X_test)
```

### 零样本分类

[Zero-shot\_classification\_with\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Zero-shot_classification_with_embeddings.ipynb)

我们可以使用嵌入来进行零样本分类，而无需任何标记的训练数据。对于每个类别，我们将类名或类的简短描述嵌入其中。为了以零样本方式对一些新文本进行分类，我们将其嵌入与所有类别嵌入进行比较，并预测相似度最高的类别。

```python
from openai.embeddings_utils import cosine_similarity, get_embedding
 
df= df[df.Score!=3]
df['sentiment'] = df.Score.replace({1:'negative', 2:'negative', 4:'positive', 5:'positive'})
 
labels = ['negative', 'positive']
label_embeddings = [get_embedding(label, model=model) for label in labels]
 
def label_score(review_embedding, label_embeddings):
   return cosine_similarity(review_embedding, label_embeddings[1]) - cosine_similarity(review_embedding, label_embeddings[0])
 
prediction = 'positive' if label_score('Sample Review', label_embeddings) > 0 else 'negative'
```

### 获取用户和产品嵌入以进行冷启动推荐

[User\_and\_product\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/User_and_product_embeddings.ipynb)

我们可以通过对用户所有评论进行平均来获得用户嵌入。同样地，我们可以通过对有关该产品的所有评论进行平均来获得产品嵌入。为了展示这种方法的实用性，我们使用50k个评论的子集以涵盖更多用户和产品的评论。&#x20;

我们在一个单独的测试集上评估这些嵌入的实用性，在那里我们绘制用户和产品嵌入相似度作为评分函数。有趣的是，基于这种方法，即使在用户收到产品之前，我们也能比随机预测他们是否会喜欢该产品。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2FICgNQJyM3bDZcdekeK5p%2Fimage.png?alt=media\&token=3537bc79-7c07-4882-8572-093a18d46c21)

```
user_embeddings = df.groupby('UserId').ada_embedding.apply(np.mean)
prod_embeddings = df.groupby('ProductId').ada_embedding.apply(np.mean)
```

### 聚类

[Clustering.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Clustering.ipynb)<br>

聚类是理解大量文本数据的一种方法。嵌入对于这个任务非常有用，因为它们提供了每个文本的语义向量表示。因此，在无监督的情况下，聚类将揭示我们数据集中隐藏的分组。&#x20;

在这个例子中，我们发现四个不同的簇：一个专注于狗粮，一个专注于负面评论，另外两个则是关于正面评论。

![](https://4032710226-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrHbKpKUvATEUrmSc1C8%2Fuploads%2F7r9il6RZ9qAYvkGDhQjr%2Fimage.png?alt=media\&token=cf605c97-a611-4f09-bfd0-b23699bfb71c)

```python
import numpy as np
from sklearn.cluster import KMeans
 
matrix = np.vstack(df.ada_embedding.values)
n_clusters = 4
 
kmeans = KMeans(n_clusters = n_clusters, init='k-means++', random_state=42)
kmeans.fit(matrix)
df['Cluster'] = kmeans.labels_
```

### 使用嵌入进行文本搜索

[Semantic\_text\_search\_using\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Semantic_text_search_using_embeddings.ipynb)

为了检索出最相关的文档，我们使用查询嵌入向量和每个文档之间的余弦相似度，并返回得分最高的文档。

```python
from openai.embeddings_utils import get_embedding, cosine_similarity
 
def search_reviews(df, product_description, n=3, pprint=True):
   embedding = get_embedding(product_description, model='text-embedding-ada-002')
   df['similarities'] = df.ada_embedding.apply(lambda x: cosine_similarity(x, embedding))
   res = df.sort_values('similarities', ascending=False).head(n)
   return res
 
res = search_reviews(df, 'delicious beans', n=3)
```

### 使用嵌入进行代码搜索

[Code\_search.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Code_search.ipynb)

代码搜索与基于嵌入式文本搜索类似。我们提供一种从给定存储库中的所有Python文件中提取Python函数的方法。然后，每个函数都由text-embedding-ada-002模型进行索引。&#x20;

要执行代码搜索，我们使用相同的模型将查询以自然语言形式进行嵌入。然后，我们计算结果查询嵌入和每个函数嵌入之间的余弦相似度。最高余弦相似度结果最相关。

```python
from openai.embeddings_utils import get_embedding, cosine_similarity
 
df['code_embedding'] = df['code'].apply(lambda x: get_embedding(x, model='text-embedding-ada-002'))
 
def search_functions(df, code_query, n=3, pprint=True, n_lines=7):
   embedding = get_embedding(code_query, model='text-embedding-ada-002')
   df['similarities'] = df.code_embedding.apply(lambda x: cosine_similarity(x, embedding))
 
   res = df.sort_values('similarities', ascending=False).head(n)
   return res
res = search_functions(df, 'Completions API tests', n=3)
```

### 使用嵌入推荐

[Recommendation\_using\_embeddings.ipynb](https://github.com/openai/openai-cookbook/blob/main/examples/Recommendation_using_embeddings.ipynb)

因为嵌入向量之间的距离越短，表示它们之间的相似度越大，所以嵌入可以用于推荐。&#x20;

下面我们展示一个基本的推荐器。它接收一组字符串和一个“源”字符串，计算它们的嵌入向量，然后返回按相似度从高到低排名的字符串列表。作为具体例子，下面链接的笔记本将这个函数应用于 AG 新闻数据集（采样至 2,000 条新闻文章描述），以返回与任何给定源文章最相似的前 5 篇文章。

```python
def recommendations_from_strings(
   strings: List[str],
   index_of_source_string: int,
   model="text-embedding-ada-002",
) -> List[int]:
   """Return nearest neighbors of a given string."""

   # get embeddings for all strings
   embeddings = [embedding_from_string(string, model=model) for string in strings]
   
   # get the embedding of the source string
   query_embedding = embeddings[index_of_source_string]
   
   # get distances between the source embedding and other embeddings (function from embeddings_utils.py)
   distances = distances_from_embeddings(query_embedding, embeddings, distance_metric="cosine")
   
   # get indices of nearest neighbors (function from embeddings_utils.py)
   indices_of_nearest_neighbors = indices_of_nearest_neighbors_from_distances(distances)
   return indices_of_nearest_neighbors
```

## 限制和风险&#x20;

在某些情况下，我们的嵌入模型可能不可靠或存在社会风险，并且在没有缓解措施的情况下可能会造成伤害。&#x20;

### 社会偏见&#x20;

限制：模型通过刻板印象或对某些群体的负面情感编码了社会偏见。 我们通过运行SEAT（[May等人，2019](https://arxiv.org/abs/1903.10561)）和Winogender（[Rudinger等人，2018](https://arxiv.org/abs/1804.09301)）基准测试发现了我们模型中存在偏差的证据。这些基准测试共包括7个测试，用于衡量当应用于性别化名称、地区名称和一些刻板印象时，模型是否包含隐含偏见。&#x20;

例如，我们发现与非洲裔美国人姓名相比，我们的模型更强烈地将欧洲裔美国人姓名与积极情感联系起来，并将负面刻板印象与黑人女性联系起来。 这些基准测试有若干局限性：(a) 它们可能无法推广到您特定的使用案例中；(b) 它们仅针对可能出现的很小一部分社会偏见进行测试。

&#x20;这些测试是初步结果，请根据您特定使用案例运行相关测试。这些结果应被视为该现象存在的证据而非其在您使用案例中明确描述。请参阅我们的使用政策以获取更多详细信息和指导建议。 如果您有任何问题，请通过聊天联系支持团队；我们很乐意为此提供建议。

### &#x20;盲目忽略最近事件&#x20;

限制：模型缺乏关于2020年8月之后发生事件的知识。 我们的模型是训练在数据集上，在其中包含了截至2020年8月真实世界事件方面一定程度上信息。如果你依赖于代表最近事件的模型，则它们可能不会表现得很好 。常问问题 如何确定我要嵌入字符串之前有多少词元？ 在Python中, 您可以使用OpenAI 的tokenizer tiktoken 将一个字符串分割成词元. 示例代码:

```python
import tiktoken

def num_tokens_from_string(string: str, encoding_name: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens

num_tokens_from_string("tiktoken is great!", "cl100k_base")
```

对于像text-embedding-ada-002这样的第二代嵌入模型，请使用cl100k\_base编码。&#x20;

更多细节和示例代码在OpenAI Cookbook指南中[如何使用tiktoken计算词元中](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb)。&#x20;

### 如何快速检索K个最近的嵌入向量？&#x20;

为了快速搜索许多向量，我们建议使用矢量数据库。您可以在GitHub上的我们的Cookbook中找到有关与矢量数据库和OpenAI API一起工作的示例。 矢量数据库选项包括：

* Pinecone，完全托管的矢量数据库&#x20;
* Weaviate，开源矢量搜索引擎&#x20;
* Faiss，Facebook提供的矢量搜索算法&#x20;
* Redis作为一个向量数据库&#x20;
* Qdrant，一个向量搜索引擎&#x20;
* Typesense是一个开源搜索引擎，并带有向量搜索功能。

#### &#x20;我应该使用哪种距离函数？

我们推荐[余弦相似度](https://en.wikipedia.org/wiki/Cosine_similarity)。距离函数的选择通常并不重要。 OpenAI嵌入被归一化为长度1，这意味着：&#x20;

* 余弦相似性可以通过仅使用点积来稍微更快地计算出来&#x20;
* 余弦相似性和欧几里得距离将产生相同的排名


# 语音转文本

学习如何将音频转换为文本。

## 介绍&#x20;

语音转文本 API 提供了两个端点，即基于我们最先进的开源大型-v2 Whisper 模型的转录和翻译。它们可以用于：&#x20;

* 将音频转录为任何语言。&#x20;
* 将音频翻译并转录成英语。&#x20;

目前文件上传限制为 25 MB，并支持以下输入文件类型：mp3、mp4、mpeg、mpga、m4a、wav 和 webm。&#x20;

## 快速入门&#x20;

### 转录&#x20;

转录 API 的输入是您要进行转录的音频文件以及所需输出格式的音频文字稿。我们目前支持多种输入和输出文件格式。

```python
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai
audio_file= open("/path/to/file/audio.mp3", "rb")
transcript = openai.Audio.transcribe("whisper-1", audio_file)
```

默认情况下，响应类型将是包含原始文本的 JSON。

```
{
  "text": "Imagine the wildest idea that you've ever had, and you're curious about how it might scale to something that's a 100, a 1,000 times bigger.
....
}
```

要在请求中设置其他参数，您可以添加更多带有相关选项的--form行。例如，如果您想将输出格式设置为文本，则应添加以下行：

```
...
--form file=@openai.mp3 \
--form model=whisper-1 \
--form response_format=text
```

### 翻译

翻译API以任何支持的语言作为输入音频文件，并在必要时将音频转录成英文。这与我们的/Transcriptions端点不同，因为输出不是原始输入语言，而是被翻译成英文文本。

```python
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai
audio_file= open("/path/to/file/german.mp3", "rb")
transcript = openai.Audio.translate("whisper-1", audio_file)
```

在这种情况下，输入的音频是德语，输出的文本看起来像：

```
Hello, my name is Wolfgang and I come from Germany. Where are you heading today?

```

我们目前仅支持英语翻译。

## &#x20;支持的语言&#x20;

我们目前通过转录和翻译端点支持以下语言：

&#x20;南非荷兰语，阿拉伯语，亚美尼亚语，阿塞拜疆语，白俄罗斯语，波斯尼亚文，保加利亚文，加泰罗尼亚文，中文，克罗地亚文、捷克文、丹麦文、荷兰文、英国英语、爱沙尼亚文、芬兰文、法国法式英語, 加利西亞語, 德國語, 希臘語, 希伯來語, 印地語, 匈牙利語, 冰島icelandic 読音: \[ˈaɪsləndɪk], 印度尼西雅Indonesian 読音: \[indoneˈsia], 意大利Italian 読音: \[iːtæljən], 日本Japanese 読音: \[dʒæpəniːz], 卡纳达Kannada 読音: \[kʌn'na:dʌ] ,哈萨克Kazakh 読音:\[kɑzɑx] , 韩国Korean 读作：\[hanguk] ，拉脫維Latvian 读作：\[lætvijan] ，立陶宛Lithuanian 读作：\[liθu'einjən] ，马其顿Macedonian 读作：\[mækidouniən ] ，马来Malay 读作：\['meilei ] ，馬拉地Marathi 讀作:\[ma'rathi ],毛里求斯Maori 讀作:\[mauri ], 尼泊尔Nepali 讀作:\[ne'pa:l ],挪威Norwegian 讀作:\['no:wijiən ] ， 波斯Persian讀做\[persi'an ] , 波蘇尼Serbian讀做sǎrbijǝTagalog讀做tӕgӕ'lɔg，坦米爾Tamil讀做'tæmil, 泰Thai讀做\[tai], 土耳其Turkish讀健\[turki'sh], 烏Crainian(乌克兰)Ukrainian 讀健\[jukreinjǝn ], 烏Urdu(乌尔都)Urdu 讓你\[u:rdu:],越南Vietnamese (越南)Vietnamese 和威尔士Welsh。&#x20;

虽然底层模型是在98种不同的语言上进行了培训。但我们只列出了超过50%单词错误率（WER）的标准行业基准测试所支持的那些。该模型将返回未列出以上列表中的其他所有可能存在输入结果但质量会较低。&#x20;

## 更长输入

&#x20;默认情况下Whisper API仅支持小于25 MB 的文件。如果您有一个比这更长的音频文件，则需要将其分成每个小于25 MB 的块或使用压缩后格式。为了获得最佳性能，请避免在句子中间断开声音以避免丢失一些上下文字信息。 处理此问题的一种方法是使用PyDub开源Python软件包来拆分声频文件。

```python
from pydub import AudioSegment

song = AudioSegment.from_mp3("good_morning.mp3")

# PyDub handles time in milliseconds
ten_minutes = 10 * 60 * 1000

first_10_minutes = song[:ten_minutes]

first_10_minutes.export("good_morning_10.mp3", format="mp3")
```

OpenAI对于像PyDub这样的第三方软件的可用性或安全性不作任何保证。

## &#x20;提示&#x20;

您可以使用提示来提高Whisper API生成的转录质量。模型将尝试匹配提示的风格，因此如果提示也使用大写和标点符号，则更有可能使用它们。但是，当前的提示系统比我们其他语言模型要受限得多，并且仅提供对生成音频的有限控制。以下是一些示例，说明如何在不同情况下使用提示：&#x20;

1. 对于模型经常错误识别音频中特定单词或缩略语非常有帮助。例如，以下提示改善了DALL·E和GPT-3这些单词（以前被写成“GDP 3”和“DALI”）的转录。&#x20;

```
该转录涉及OpenAI开发类似DALL·E、GPT-3和ChatGPT等技术，并希望有一天构建一个造福人类所有人的AGI系统。
```

2. 为了保留分段文件的上下文，请使用先前片段的转录来引导模型。这将使转录更准确，因为模型将利用先前音频中相关信息。该模型只会考虑最后224个标记并忽略之前任何内容。
3. 有时候，在转录中可能会跳过标点符号。您可以通过使用包含标点符号简单提示来避免这种情况：&#x20;

```
你好，欢迎参加我的讲座。 
```

2. 该模型还可能在音频中省略常见填充词汇。如果您想在您的转录中保留填充词汇，则可以使用包含它们的指示：

```
 嗯... 让我想想, 呃... 好吧, 这就是我正在思考 的事情. 
```

3. 某些语言可以用不同方式书写，例如简体或繁体中文。默认情况下，该模型可能无法始终按照所需书写风格进行处理 。通过在首选书写风格上添加指示即可改进此问题.


# 内容审核

## 概述&#x20;

Moderation 端点是一个工具，您可以使用它来检查内容是否符合 OpenAI 的使用政策。开发人员因此可以识别违反我们使用政策的内容，并采取行动，例如通过过滤它。&#x20;

该模型分类以下类别：

| 类别                 | 描述                                            |
| ------------------ | --------------------------------------------- |
| `hate`             | 表达、煽动或宣传基于种族、性别、民族、宗教、国籍、性取向、残疾状态或种姓的仇恨内容。    |
| `hate/threatening` | 包括针对目标群体的暴力或严重伤害的仇恨内容。                        |
| `self-harm`        | 促进、鼓励或描绘自我伤害行为，如自杀，割伤和饮食障碍等。                  |
| `sexual`           | 旨在引起性兴奋的内容，例如描述性活动或推广性服务（不包括性教育和健康）。          |
| `sexual/minors`    | 包含未满18岁个体的性内容。                                |
| `violence`         | 推广或美化暴力，庆祝他人遭受苦难或屈辱的内容。                       |
| `violence/graphic` | <p>描述死亡, 暴力, 或极端图形细节中造成严重身体损伤.</p><p><br></p> |

当监控 OpenAI API 的输入和输出时，可免费使用审核端点。我们目前不支持第三方流量监控。

我们正在不断努力提高分类器准确度，并特别致力于改善对仇恨言论，自我伤害以及图形暴力等类型文章进行分类。我们目前对非英语语言支持有限。

## 快速入门

要获取文本片段的分类，请像以下代码片段中演示的那样向审核端点发出请求:

```python
curl https://api.openai.com/v1/moderations \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{"input": "Sample text goes here"}'
```

以下是端点的示例输出。它返回以下字段：&#x20;

* flagged：如果模型将内容分类为违反OpenAI使用政策，则设置为true，否则为false。&#x20;
* categories：包含每个类别二进制使用政策违规标志的字典。对于每个类别，如果模型将相应的类别标记为违规，则该值为true，否则为false。&#x20;
* category\_scores：包含由模型输出的每个类别原始分数的字典，表示模型对输入是否违反OpenAI有关该类别的政策的信心。该值介于0和1之间，其中较高的值表示更高的置信度。不应将得分解释为概率。

```python
{
  "id": "modr-XXXXX",
  "model": "text-moderation-001",
  "results": [
    {
      "categories": {
        "hate": false,
        "hate/threatening": false,
        "self-harm": false,
        "sexual": false,
        "sexual/minors": false,
        "violence": false,
        "violence/graphic": false
      },
      "category_scores": {
        "hate": 0.18805529177188873,
        "hate/threatening": 0.0001250059431185946,
        "self-harm": 0.0003706029092427343,
        "sexual": 0.0008735615410842001,
        "sexual/minors": 0.0007470346172340214,
        "violence": 0.0041268812492489815,
        "violence/graphic": 0.00023186142789199948
      },
      "flagged": false
    }
  ]
}
```

OpenAI将持续升级调节端点的基础模型。因此，依赖于类别分数的自定义策略可能需要随时间重新校准。


# 速率限制

## 概述&#x20;

### 什么是速率限制？&#x20;

速率限制是API对用户或客户端在指定时间内访问服务器的次数施加的限制。&#x20;

### 为什么我们有速率限制？

&#x20;速率限制是API的常见实践，它们出于几个不同的原因而被设置：

* &#x20;它们有助于防止滥用或误用API。例如，恶意行为者可能会通过请求来淹没API，试图使其超载或导致服务中断。通过设置速率限制，OpenAI可以防止这种活动发生。
* 速率限制有助于确保每个人都能公平地访问API。如果一个人或组织进行过多的请求，可能会拖累其他所有人使用API。通过调节单个用户可以进行的请求数量，OpenAI确保最多数量的人有机会使用API而不经历减缓。&#x20;
* 速率限制可以帮助OpenAI管理其基础设施上的总负载。如果对API的请求急剧增加，则可能会给服务器带来压力并导致性能问题。通过设置速率限制，OpenAI可以帮助所有用户维护平稳一致体验。

&#x20;请完整阅读本文档以更好地了解OpenAI 的 速度极值系统如何工作。我们提供代码示例和处理常见问题所需解决方案，请在填写“极值增长申请表”之前遵循此指南，并详细说明如何在最后一部分填写该表格。&#x20;

### 我们 API 的极值是什么？

我们根据使用特定端点以及您拥有哪种类型账户，在组织级别而非用户级别强化极值控管 。 极值按两种方式测量：RPM（每分钟请求数）和TPM（每分钟词元数）。下表突出显示了我们 API 的默认极值 ，但这些极值可根据您的用例在填写“Rate Limit Increase Request” 表格后进行增加 。

TPM（每分钟标记数）单位因模型而异：

| 类型      | 1 TPM 等价于 |
| ------- | --------- |
| davinci | 1 词元/分钟   |
| curie   | 25 词元/分钟  |
| babbage | 100 词元/分钟 |
| ada     | 200 词元/分钟 |

从实际角度来看，这意味着您可以每分钟向ada模型发送大约200倍的令牌，而相对于davinci模型则更多。

|                  | TEXT & EMBEDDING                     | CHAT                                | CODEX                          | EDIT                            | IMAGE           | AUDIO  |
| ---------------- | ------------------------------------ | ----------------------------------- | ------------------------------ | ------------------------------- | --------------- | ------ |
| 免费试用用户           | <p>•20 RPM <br>•150,000 TPM</p>      | <p>•20 RPM <br>•40,000 TPM</p>      | <p>•20 RPM <br>•40,000 TPM</p> | <p>•20 RPM <br>•150,000 TPM</p> | 50 images / min | 50 RPM |
| 按使用量付费用户（前48小时）  | <p>•60 RPM <br>•250,000 TPM\*</p>    | <p>•60 RPM <br>•60,000 TPM\*</p>    | <p>•20 RPM <br>•40,000 TPM</p> | <p>•20 RPM <br>•150,000 TPM</p> | 50 images / min | 50 RPM |
| 按使用量付费用户（48小时以后） | <p>•3,500 RPM <br>•350,000 TPM\*</p> | <p>•3,500 RPM <br>•90,000 TPM\*</p> | <p>•20 RPM <br>•40,000 TPM</p> | <p>•20 RPM <br>•150,000 TPM</p> | 50 images / min | 50 RPM |

需要注意的是，速率限制可以由任一选项触发，取决于哪个先发生。例如，您可能会向Codex端点发送20个请求，并仅使用100个代币来填充您的限制，即使在这些20个请求中没有发送40k代币。

### 速率限制如何工作？&#x20;

如果您的速率限制为每分钟60个请求和每分钟150k davinci代币，则将受到两者之一的限制，无论哪种情况先发生。例如，如果您的最大请求数/分为60，则应能够每秒发送1个请求。如果您每800毫秒发送1次请求，在达到速率限制后，只需让程序休眠200毫秒即可再次发送一个请求；否则后续请求将失败。对于默认值3,000 requests/min，默认值下客户可以有效地每20ms或0.02秒发送1次请求。

### &#x20;如果我遇到了速率限制错误会怎样？&#x20;

速率限制错误看起来像这样： Rate limit reached for default-text-davinci-002 in organization org-{id} on requests per min. Limit: 20.000000 / min. Current: 24.000000 / min. 如果你遇到了速度上线问题，则意味着你在短时间内进行了过多的申请，并且API拒绝履行进一步申请直至经过指定时间。&#x20;

### 速度上限与max\_tokens&#x20;

我们提供的每种模型都有一个固定数量的token可以作为输入传递给它们进行处理。不能增加模型接收标记数目上界。例如： 如果使用text-ada-001，则可以向该模型发送最多2048词元每个请求。&#x20;

## 错误处置&#x20;

### 我可以采取哪些措施来减轻此类问题？

&#x20;OpenAI Cookbook有一个[Python笔记本](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_handle_rate_limits.ipynb)详细说明如何避免出现频率极高（rate limit）错误。

&#x20;当提供编程式访问、批量处理功能和自动化社交媒体发布时，请谨慎考虑 - 可以考虑仅针对信任客户启用这些功能。

&#x20;为防止自动化和高容量滥用，在指定时间范围内（日、周或月），设置单个用户使用量上界 。 对于超出此上界用户，请考虑实施硬性规定或手动审核流程。&#x20;

### 通过指数回退重试&#x20;

避免频繁调用API方法导致频繁报错也很简单——随机等待并重新尝试调用API方法就好了！具体做法是：当 API 返回“429 Too Many Requests”状态码时暂停执行代码片段，并根据当前已经重试过几次计算出等待时间 t ，然后再重新尝试调用 API 方法；若依旧返回“429 Too Many Requests”状态码则再暂停 t 秒钟之后重复以上操作…… 直至成功获取数据！

&#x20;指数回退意味着在命中第一个 rate limit 错误时执行短暂休眠并重试不成功的 request 。 如果 request 仍未成功，则增加 sleep 长度并重复该过程。 这将持续到 request 成功或达到最大重试次数为止。 此方法具有许多优点：&#x20;

* 自动重试意味着您可以从 speed limit errors 中恢复而不会崩溃或丢失数据&#x20;
* 指数回退意味着首先尝试快捷方式retry ，同时仍然从较长延迟中获益retry ，因此前几次 retry 失败。&#x20;
* 添加随机抖动以延迟 retries 不同时刻击中所有 retries 的效果。

请注意，不成功的请求会影响您每分钟的限制，因此持续重新发送请求是行不通的。 以下是一些使用指数退避的 Python 示例解决方案。

#### 示例1：使用Tenacit库

Tenacity是一个Apache 2.0许可的通用重试库，使用Python编写，旨在简化将重试行为添加到几乎任何内容的任务。要向您的请求添加指数退避，请使用tenacity.retry装饰器。下面的示例使用tenacity.wait\_random\_exponential函数向请求添加随机指数退避。

```python
import openai
from tenacity import (
    retry,
    stop_after_attempt,
    wait_random_exponential,
)  # for exponential backoff
 
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
def completion_with_backoff(**kwargs):
    return openai.Completion.create(**kwargs)
 
completion_with_backoff(model="text-davinci-003", prompt="Once upon a time,")
```

请注意，Tenacity库是第三方工具，OpenAI不对其可靠性或安全性做出任何保证。

#### 示例2：使用backoff库

另一个提供退避和重试功能修饰符的Python库是backoff：

```python
import backoff 
import openai 
@backoff.on_exception(backoff.expo, openai.error.RateLimitError)
def completions_with_backoff(**kwargs):
    return openai.Completion.create(**kwargs)
 
completions_with_backoff(model="text-davinci-003", prompt="Once upon a time,")
```

#### 示例3：手动实现指数回退

如果您不想使用第三方库，可以按照此示例实现自己的退避逻辑：

```python
# imports
import random
import time
 
import openai
 
# define a retry decorator
def retry_with_exponential_backoff(
    func,
    initial_delay: float = 1,
    exponential_base: float = 2,
    jitter: bool = True,
    max_retries: int = 10,
    errors: tuple = (openai.error.RateLimitError,),
):
    """Retry a function with exponential backoff."""
 
    def wrapper(*args, **kwargs):
        # Initialize variables
        num_retries = 0
        delay = initial_delay
 
        # Loop until a successful response or max_retries is hit or an exception is raised
        while True:
            try:
                return func(*args, **kwargs)
 
            # Retry on specific errors
            except errors as e:
                # Increment retries
                num_retries += 1
 
                # Check if max retries has been reached
                if num_retries > max_retries:
                    raise Exception(
                        f"Maximum number of retries ({max_retries}) exceeded."
                    )
 
                # Increment the delay
                delay *= exponential_base * (1 + jitter * random.random())
 
                # Sleep for the delay
                time.sleep(delay)
 
            # Raise exceptions for any errors not specified
            except Exception as e:
                raise e
 
    return wrapper
    
@retry_with_exponential_backoff
def completions_with_backoff(**kwargs):
    return openai.Completion.create(**kwargs)
```

再次声明，OpenAI 对此解决方案的安全性或效率不作任何保证，但它可以成为您自己解决方案的良好起点。

### 批量请求

&#x20;OpenAI API 对每分钟的请求数和令牌数有单独的限制。&#x20;

如果您达到了每分钟请求次数的限制，但是在每分钟令牌方面有可用容量，则可以将多个任务分批处理到每个请求中，以增加吞吐量。这将允许您处理更多的令牌，特别是对于我们较小的模型。&#x20;

发送一批提示与正常 API 调用完全相同，只需将字符串列表传递给 prompt 参数即可。

#### 不使用批处理的例子：

```python
import openai
 
num_stories = 10
prompt = "Once upon a time,"
 
# serial example, with one story completion per request
for _ in range(num_stories):
    response = openai.Completion.create(
        model="curie",
        prompt=prompt,
        max_tokens=20,
    )
    # print story
    print(prompt + response.choices[0].text)
```

使用批处理的例子

```python
import openai  # for making OpenAI API requests
 
 
num_stories = 10
prompts = ["Once upon a time,"] * num_stories
 
# batched example, with 10 story completions per request
response = openai.Completion.create(
    model="curie",
    prompt=prompts,
    max_tokens=20,
)
 
# match completions to prompts by index
stories = [""] * len(prompts)
for choice in response.choices:
    stories[choice.index] = prompts[choice.index] + choice.text
 
# print stories
for story in stories:
    print(story)
```

> 警告：响应对象可能不会按提示的顺序返回完成情况，因此请始终记住使用索引字段将响应与提示匹配。

## 请求增加&#x20;

### 我应该在什么时候考虑申请速率限制增加？&#x20;

我们的默认速率限制有助于最大化稳定性并防止滥用我们的API。我们会增加限制以启用高流量应用程序，因此申请速率限制增加的最佳时间是当您认为您拥有必要的流量数据来支持提高速率限制的强有力理由时。没有支持数据的大幅度速率限制增加请求不太可能被批准。如果您正在准备产品发布，请通过10天分阶段发布获得相关数据。

请记住，速率限制增加有时需要7-10天，因此如果存在支持当前增长数字将达到您的速率限制所需数据，则尽早计划并提交是明智之举。&#x20;

### 我的速率限制增加请求会被拒绝吗？

&#x20;一个常见原因是缺乏证明其合理性所需数据而导致拒绝。下面提供了数值示例，展示如何最好地支持一个速率上升请求，并尽力批准所有符合安全策略和显示支持数据要求的请求。我们致力于使开发人员能够使用我们的API进行规模化和成功。

### &#x20;我已经为我的文本/代码API实现了指数退避算法，但仍然出现错误。如何提高我的频次上线？

&#x20;目前，我们不支持提高免费测试端点（例如编辑端点）等功能。 我们也不会提高ChatGPT频次上线，但你可以参与ChatGPT专业版访问列表。

我们知道受到频次上线约束可能带来多大挫败感，并且很想为每个人都提高默认值。 但是由于共享容量约束，在Rate Limit Increase Request表单中只能批准付费客户证明需要通过审查后方可进行频次上线调整 。 为了帮助评估您真正需要哪些内容，请在“分享需求证据”部分中提供关于当前使用情况或基于历史用户活动预测 的统计信息 。 如果没有这些信息，则建议采取逐步释放方法：首先以当前比例释放服务给一小部分用户，在10个工作日内收集使用情况数据 ，然后根据该数据提交正式频次上线调整请求以供审核和批准。&#x20;

如果您提交了申请并获得批准，则在7-10个工作日内通知您审批结果。 以下是填写此表格的一些示例：

#### DALL-E API示例

<table><thead><tr><th>模型</th><th>预估词元数/分钟</th><th>预估请求数</th><th>用户数</th><th width="206">需要的证据</th><th>1小时最大吞吐成本</th></tr></thead><tbody><tr><td>DALL-E API</td><td>N/A</td><td>50</td><td>1000</td><td>我们的应用目前正在生产中，根据过去的流量情况，我们每分钟大约发出10个请求。</td><td>$60</td></tr><tr><td>DALL-E API</td><td>N/A</td><td>150</td><td>10,000</td><td>我们的应用在App Store中越来越受欢迎，我们开始遇到速率限制。我们能否获得默认限制的三倍，即每分钟50个图像？如果需要更多，我们将提交新表格。谢谢！</td><td>$180</td></tr></tbody></table>

语言模型示例

<table><thead><tr><th>模型</th><th>预估词元数/分钟</th><th width="153">ESTIMATE预估请求数 REQUESTS/MINUTE</th><th>用户数</th><th>需要的证据</th><th>1小时最大吞吐成本</th></tr></thead><tbody><tr><td>text-davinci-003</td><td>325,000</td><td>4,0000</td><td>50</td><td>我们将向一组初始的Alpha测试人员发布，并需要更高的限制来适应他们的初始使用。 我们在这里提供了一个链接到我们的Google Drive，显示分析和API使用情况。</td><td>$390</td></tr><tr><td>text-davinci-002</td><td>750,000</td><td>10,000</td><td>10,000</td><td>我们的应用程序受到了很多关注，我们有50,000人在等待列表上。 我们希望每天向1000人的小组推出，直到达到50,000个用户。 请查看此链接，以了解过去30天内我们当前令牌/分钟流量情况。 这是针对500个用户的，并且根据他们的使用情况，我们认为750,000个令牌/分钟和10,000个请求/分钟将作为一个良好的起点。</td><td>$900</td></tr></tbody></table>

#### Code模型示例

| 模型               | 预估词元数/分钟 | ESTIMATE预估请求数 REQUESTS/MINUTE | 用户数 | 需要的证据                                                                           | 1小时最大吞吐成本                              |
| ---------------- | -------- | ----------------------------- | --- | ------------------------------------------------------------------------------- | -------------------------------------- |
| code-davinci-002 | 150,000  | 1,000                         | 15  | 我们是一组正在撰写论文的研究人员。我们估计，在本月底之前完成研究，需要在code-davinci-002上获得更高的速率限制。这些估计基于以下计算\[...] | Codex模型目前处于免费测试阶段，因此我们可能无法立即为这些模型提供增量。 |

请注意，这些示例仅为一般用例场景，实际使用率将根据具体的实现和使用情况而有所不同。


# 错误码

## 错误代码&#x20;

本指南包括您可能从API和我们的官方Python库中看到的错误代码概述。在概述中提到的每个错误代码都有一个专门的部分，提供进一步的指导。

### API 错误

| CODE                      | OVERVIEW                                                              |
| ------------------------- | --------------------------------------------------------------------- |
| 401 - 无效身份验证              | <p>原因：身份验证无效。</p><p>解决方法：确保使用了正确的 API 密钥和请求组织。</p>                    |
| 401 - 提供了不正确的 API 密钥      | <p>原因：请求 API 密钥不正确。</p><p>解决方法：确保使用了正确的 API 密钥，清除浏览器缓存或生成新密钥。<br></p> |
| 401 - 必须是组织成员才能使用 API     | <p>原因：您的帐户不属于任何组织。</p><p>解决方法：联系我们以加入新组织，或要求您所在组织管理员邀请您加入该组织。<br></p> |
| 429 - 请求速率达到限制            | <p>原因：发送请求过快。</p><p>解决方法：控制好请求速率。阅读速率限制指南。</p>                        |
| 429 - 您已超出当前配额，请检查计划和账单详情 | <p>原因: 您已达到最大月度支出（硬性限制），可以在账户计费部分查看此信息.</p><p>解决方法: 申请增加配额.</p>       |
| 429 - 引擎目前负载过高，请稍后再试      | <p>原因: 我们服务器正在经历高流量.</p><p>解决办法: 稍等片刻后重试你们得请求.</p>                    |
| 500-服务器处理您得请求时发生错误.       | <p>原因: 我们服务器上存在问题.</p><p>解决办法: 稍等片刻后重试,如果问题仍然存在,请与我们联系. 查看状态页面。</p>   |


# 安全最佳实践


# 生产应用最佳实践


# API 参考


# 介绍


# 身份认证


# 创建请求


# 模型


# 完成


# 聊天


# 编辑


# 图片


# 嵌入


# 音频


# 文件


# 微调


# 内容审核


# 引擎


# 参数详情


# 翻译修订记录

## 修订记录

* 2023年3月8日：第一版翻译完成，包含开始、指南部分的核心内容


