本电子书开源，欢迎 star 🌟，关注《LLM 应用开发实践笔记》

我的新书[《LangChain编程从入门到实践》](https://u.jd.com/V8pkqFY) 已经开售！推荐正在学习AI应用开发的朋友购买阅读！
[![LangChain编程从入门到实践](../../images/langchain-book.jpg "LangChain编程从入门到实践")](https://u.jd.com/V8pkqFY) ![](../images/group.png)

## OpenAI 文档解读
OpenAI 文档涉及内容众多，而且这里已经有了[中文翻译](https://openai.xiniushu.com/)，需要详细了解的可以自行前往阅读。我这里会重点选取高频使用的 API 进行说明以及对GPT最佳实践主题进行解读。

> **这篇文章中个人结合自己的实践经验把 OpenAI 官方文档解读一遍。但是原文档涉及内容众多，包括微调，嵌入（Embeddings）等众多主题，我这里重点挑选自己开发高频使用到的，需要详细了解的可以自行前往官网阅读。**
>



### API介绍
1. 所有 API 演示均使用 Python 代码作为示例，所以确保已经安装官方 Python 包：`pip install openai`，同时[配置 API 密钥](https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety)的环境变量 `OPENAI_API_KEY`。
2. 认证：OpenAI API 使用 API 密钥进行身份验证， [API密钥页面](https://platform.openai.com/account/api-keys)可以获取使用的 API 密钥。除了密钥，对于属于多个组织的用户，可以传递一个Requesting organization字段（可以在[组织设置](https://platform.openai.com/account/org-settings)页面上找到组织ID）来指定用于 API请求的组织，这些API请求的使用将计入指定组织的订阅配额。

    ```python
    import os
    import openai
    # openai.organization = "org-gth0C8mT2wnKealyDkrSrpQk"
    openai.api_key = os.getenv("OPENAI_API_KEY")
    openai.Model.list()
    ```

### Chat Completions 会话补全
这个是使用频次最高的接口，几乎当前所有的套壳ChatGPT应用都是基于这个接口封装的，所以将其放在第一个。给定一组描述对话的消息列表，模型将返回一个回复。
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

# https://api.openai.com/v1/chat/completions
completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "user", "content": "Hello!"}
  ]
)

print(completion.choices[0].message)
```

**响应** ：
```json
{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "\n\nHello there, how may I assist you today?",
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  }
}
```

**Request body(常用入参详解)** ：

> - **`model` （string，必填）**
>
>   要使用的模型ID。有关哪些模型适用于Chat API的详细信息，请查看 [模型端点兼容性表](https://platform.openai.com/docs/models/model-endpoint-compatibility)
>
> - **`messages` （array，必填）**
>
>   迄今为止描述对话的消息列表
>
>   - **`role` （string，必填）**
>
>     发送此消息的角色。`system` 、`user` 或 `assistant` 之一（一般用 user 发送用户问题，system 发送给模型提示信息）
>
>   - **`content` （string，必填）**
>
>     消息的内容
>
>   - **`name` （string，选填）**
>
>     此消息的发送者姓名。可以包含 a-z、A-Z、0-9 和下划线，最大长度为 64 个字符
>
> - **`stream` （boolean，选填，是否按流的方式发送内容）**
>
>   当它设置为 true 时，API 会以 SSE（ Server Side Event ）方式返回内容。SSE 本质上是一个长链接，会持续不断地输出内容直到完成响应。如果不是做实时聊天，默认false即可。请参考OpenAI Cookbook 以获取 [示例代码](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb)。
>
> - **`max_tokens` （integer，选填）**
>
>   在聊天补全中生成的最大 [tokens](https://platform.openai.com/tokenizer) 数。
>
>   输入token和生成的token的总长度受模型上下文长度的限制。
>
> - **`temperature` （number，选填，默认是 1）**
>
>   采样温度，在 0和 2 之间。
>
>   较高的值，如0.8会使输出更随机，而较低的值，如0.2会使其更加集中和确定性。
>
>   通常建议修改这个（`temperature` ）或者 `top_p` ，但两者不能同时存在，二选一。
>


### Completions （文本和代码）补全
给定一个提示，模型将返回一个或多个预测的补全，并且还可以在每个位置返回替代 token 的概率。
  ```python
  import os
  import openai
  openai.api_key = os.getenv("OPENAI_API_KEY")
  # https://api.openai.com/v1/completions
  openai.Completion.create(
    model="text-davinci-003",
    prompt="Say this is a test",
    max_tokens=7,
    temperature=0
  )
```

**响应** ：
```json
  "id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7",
  "object": "text_completion",
  "created": 1589478378,
  "model": "text-davinci-003",
  "choices": [
    {
      "text": "\n\nThis is indeed a test",
      "index": 0,
      "logprobs": null,
      "finish_reason": "length"
    }
  ],
  "usage": {
    "prompt_tokens": 5,
    "completion_tokens": 7,
    "total_tokens": 12
  }
}
```

**Request body(入参详解)** ：

> - **`model` （string，必填）**
>
>   要使用的模型的 ID。可以参考 [模型端点兼容性表](https://platform.openai.com/docs/models/model-endpoint-compatibility)
>
> - **`prompt` （string or array，选填，Defaults to <|endoftext|>）**
>
>   生成补全的提示，编码为字符串、字符串数组、token数组或token数组数组。
>
>   注意 <|endoftext|> 是模型在训练过程中看到的文档分隔符，所以如果没有指定提示符，模型将像从新文档的开头一样生成。
>
> - **`stream` （boolean，选填，默认 false）**
>
>   当它设置为 true 时，API 会以 SSE（ Server Side Event ）方式返回内容，即会不断地输出内容直到完成响应，流通过 `data: [DONE]` 消息终止。
>
> - **`max_tokens` （integer，选填，默认是 16）**
>
>   补全时要生成的最大 [token](https://platform.openai.com/tokenizer) 数。
>
>   提示 `max_tokens` 的 token 计数不能超过模型的上下文长度。大多数模型的上下文长度为 2048 个token（最新模型除外，它支持 4096）
>
> - **`temperature` （number，选填，默认是1）**
>
>   使用哪个采样温度，在 **0和2之间**。
>
>   较高的值，如0.8会使输出更随机，而较低的值，如0.2会使其更加集中和确定性。
>
>   通常建议修改这个（`temperature` ）或 `top_p` 但两者不能同时存在，二选一。
>
> - **`n` （integer，选填，默认为 1）**
>
>   每个 `prompt` 生成的补全次数。
>
>   注意：由于此参数会生成许多补全，因此它会快速消耗token配额。小心使用，并确保对 `max_tokens` 和 `stop` 进行合理的设置。
>


### <a id="embeddings">Embeddings 嵌入</a>
将一个给定输入转换为向量表示，提供给机器学习模型算法使用。
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/embeddings
openai.Embedding.create(
  model="text-embedding-ada-002",
  input="The food was delicious and the waiter..."
)
```

**响应** ：
```json
{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "embedding": [
        0.0023064255,
        -0.009327292,
        .... (1536 floats total for ada-002)
        -0.0028842222,
      ],
      "index": 0
    }
  ],
  "model": "text-embedding-ada-002",
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 8
  }
}
```

**Request body(入参详解)** ：

> - **`model` （string，必填）**
>
>   要使用的 **模型ID**，可以参考 [模型端点兼容性表](https://platform.openai.com/docs/models/model-endpoint-compatibility)
>
> - **`input` （string or array，必填）**
>
>   输入文本以获取嵌入，编码为字符串或token数组。要在单个请求中获取多个输入的嵌入，请传递字符串数组或token数组的数组。每个输入长度**不得超过 8192 个token**。
>
> - **`user` （string，选填）**
>
>   一个唯一的标识符，代表终端用户，可以帮助OpenAI检测滥用。
>

### Fine-tuning 微调
使用自定义的特定训练数据，定制自己的模型。
#### **Create fine-tune**
创建一个微调作业，从给定的数据集中微调指定模型。
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# POST https://api.openai.com/v1/fine-tunes
openai.FineTune.create(training_file="file-XGinujblHPwGLSztz8cPS8XY")
```

**响应**（响应包括已入队的作业的详细信息，包括微调作业状态和完成后微调模型的名称）：
```json
{
  "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F",
  "object": "fine-tune",
  "model": "curie",
  "created_at": 1614807352,
  "events": [
    {
      "object": "fine-tune-event",
      "created_at": 1614807352,
      "level": "info",
      "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0."
    }
  ],
  "fine_tuned_model": null,
  "hyperparams": {
    "batch_size": 4,
    "learning_rate_multiplier": 0.1,
    "n_epochs": 4,
    "prompt_loss_weight": 0.1,
  },
  "organization_id": "org-...",
  "result_files": [],
  "status": "pending",
  "validation_files": [],
  "training_files": [
    {
      "id": "file-XGinujblHPwGLSztz8cPS8XY",
      "object": "file",
      "bytes": 1547276,
      "created_at": 1610062281,
      "filename": "my-data-train.jsonl",
      "purpose": "fine-tune-train"
    }
  ],
  "updated_at": 1614807352,
}
```

**Request body(入参详解)** ：

> - `training_file` （string，必填）
>
>   包含 **训练数据** 的已上传文件的ID。
>
>   请参阅 [upload file](https://platform.openai.com/docs/api-reference/files/upload) 以了解如何上传文件。
>
>   数据集必须格式化为 **JSONL文件**，其中每个训练示例都是一个带有 “prompt” 和 “completion” keys 的 JSON对象。
>
> - `validation_file` （string，选填）
>
>   包含 **验证数据** 的已上传文件的ID。
>
>   如果提供此文件，则数据将在微调期间定期用于生成验证指标。这些指标可以在 [微调结果文件](https://platform.openai.com/docs/guides/fine-tuning/analyzing-your-fine-tuned-model) 中查看，训练和验证数据应该是互斥的。
>
> - `model` （string，选填，默认是curie）
>
>   要微调的基础模型名称。
>
>   可以选择其中之一："ada"、"babbage"、"curie"、"davinci"，或 2022年4月21日 后创建的经过微调的模型。要了解这些模型的更多信息，请参阅 [Models](https://platform.openai.com/docs/models) 文档。
>
> - `n_epochs` （integer，选填，默认是4）
>
>   训练模型的批次数。一个 epoch 指的是完整地遍历一次训练数据集
>
> - `batch_size` （integer，选填）
>
>   用于训练的批次大小，指的是每次迭代中同时处理的样本数量。
>
>   默认情况下，批次大小将动态配置为训练集示例数量的约 0.2％，上限为256。
>
>   通常，发现较大的批次大小对于更大的数据集效果更好。
>
> - `learning_rate_multiplier` （number，选填）
>
>   用于训练的学习率倍增器。微调学习率是预训练时使用的原始学习率乘以此值得到的（🤖️微调学习率（Learning Rate）指的是神经网络在进行梯度下降优化算法时，每次更新参数的步长。学习率越大，神经网络的参数更新越快，但可能会导致优化过程不稳定甚至无法收敛；学习率越小，神经网络的参数更新越慢，但可能会导致优化过程过于缓慢或者陷入局部最优解。）
>
>   默认情况下，学习率的倍增器为 0.05、0.1 或 0.2，具体取决于最终 `batch_size`（较大的批次大小通常使用较大的学习率效果更好），建议尝试在 0.02 到 0.2 范围内实验不同值以找出产生最佳结果的值。
>
> - `prompt_loss_weight` （number，选填，默认是0.01）
>
>   "prompt_loss_weight" 是指在使用 Prompt-based Learning（基于提示的学习）方法进行训练时，用于调整提示损失（Prompt Loss）对总体损失（Total Loss）的相对权重。
>
>   Prompt-based Learning 是一种利用人类先验知识来辅助神经网络学习的方法，其中提示损失是指利用人类先验知识设计的提示（Prompt）与模型生成的结果之间的损失。
>
>   在 Prompt-based Learning 中，通过调整 prompt_loss_weight 的大小来平衡总体损失和提示损失的贡献，从而使模型更好地利用人类先验知识进行预测。如果 prompt_loss_weight 较大，模型会更加依赖提示损失，更好地利用人类先验知识；如果 prompt_loss_weight 较小，模型会更加依赖总体损失，更好地适应当前数据集的特征和分布。
>
> - `compute_classification_metrics` （boolean，选填，默认是false）
>
>   如果设置了，会在每个 epoch 结束时使用验证集计算特定于分类的指标，例如准确率和 F-1 分数。这些指标可以在 [微调结果文件](https://platform.openai.com/docs/guides/fine-tuning/analyzing-your-fine-tuned-model) 中查看。为了计算分类指标，必须提供一个`validation_file(验证文件)`。
>
>   此外，对于多类分类，必须指定 `classification_n_classes`；对于二元分类，则需要指定`classification_positive_class`。
>
> - `suffix` （string，选填，默认为 null）
>
>   一个长度最多为 40个字符 的字符串，将被添加到微调模型名称中。
>
>   例如，`suffix`  为 “custom-model-name” 会生成一个模型名称，如 `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`。


#### **List fine-tunes**
列出所属组织下的微调作业列表
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# GET https://api.openai.com/v1/fine-tunes
openai.FineTune.list()
```

**响应** ：
```json
{
  "object": "list",
  "data": [
    {
      "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F",
      "object": "fine-tune",
      "model": "curie",
      "created_at": 1614807352,
      "fine_tuned_model": null,
      "hyperparams": { ... },
      "organization_id": "org-...",
      "result_files": [],
      "status": "pending",
      "validation_files": [],
      "training_files": [ { ... } ],
      "updated_at": 1614807352,
    },
    { ... },
    { ... }
  ]
}
```

#### **Retrieve fine-tune**
获取有关微调作业的信息
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/fine-tunes/{fine_tune_id}
openai.FineTune.retrieve(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F")
```

**响应** ：
```json
{
  "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F",
  "object": "fine-tune",
  "model": "curie",
  "created_at": 1614807352,
  "events": [
    {
      "object": "fine-tune-event",
      "created_at": 1614807352,
      "level": "info",
      "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807356,
      "level": "info",
      "message": "Job started."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807861,
      "level": "info",
      "message": "Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807864,
      "level": "info",
      "message": "Uploaded result files: file-QQm6ZpqdNwAaVC3aSz5sWwLT."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807864,
      "level": "info",
      "message": "Job succeeded."
    }
  ],
  "fine_tuned_model": "curie:ft-acmeco-2021-03-03-21-44-20",
  "hyperparams": {
    "batch_size": 4,
    "learning_rate_multiplier": 0.1,
    "n_epochs": 4,
    "prompt_loss_weight": 0.1,
  },
  "organization_id": "org-...",
  "result_files": [
    {
      "id": "file-QQm6ZpqdNwAaVC3aSz5sWwLT",
      "object": "file",
      "bytes": 81509,
      "created_at": 1614807863,
      "filename": "compiled_results.csv",
      "purpose": "fine-tune-results"
    }
  ],
  "status": "succeeded",
  "validation_files": [],
  "training_files": [
    {
      "id": "file-XGinujblHPwGLSztz8cPS8XY",
      "object": "file",
      "bytes": 1547276,
      "created_at": 1610062281,
      "filename": "my-data-train.jsonl",
      "purpose": "fine-tune-train"
    }
  ],
  "updated_at": 1614807865,
}
```

#### **Cancel fine-tune**
立即取消微调工作
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/fine-tunes/{fine_tune_id}/cancel
openai.FineTune.cancel(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F")
```
**响应** ：
```json
{
  "id": "ft-xhrpBbvVUzYGo8oUO1FY4nI7",
  "object": "fine-tune",
  "model": "curie",
  "created_at": 1614807770,
  "events": [ { ... } ],
  "fine_tuned_model": null,
  "hyperparams": { ... },
  "organization_id": "org-...",
  "result_files": [],
  "status": "cancelled",
  "validation_files": [],
  "training_files": [
    {
      "id": "file-XGinujblHPwGLSztz8cPS8XY",
      "object": "file",
      "bytes": 1547276,
      "created_at": 1610062281,
      "filename": "my-data-train.jsonl",
      "purpose": "fine-tune-train"
    }
  ],
  "updated_at": 1614807789,
}
```

#### **List fine-tune events**
获取微调作业各阶段运行状态（事件）详情
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/fine-tunes/{fine_tune_id}/events
openai.FineTune.list_events(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F")
```

**响应** ：
```json
{
  "object": "list",
  "data": [
    {
      "object": "fine-tune-event",
      "created_at": 1614807352,
      "level": "info",
      "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807356,
      "level": "info",
      "message": "Job started."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807861,
      "level": "info",
      "message": "Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807864,
      "level": "info",
      "message": "Uploaded result files: file-QQm6ZpqdNwAaVC3aSz5sWwLT."
    },
    {
      "object": "fine-tune-event",
      "created_at": 1614807864,
      "level": "info",
      "message": "Job succeeded."
    }
  ]
}
```
**Query parameters** ：

> - `stream` （boolean，选填）
>
>   对于微调作业运行状态是否以事件流的方式返回
>
>   如果设置为 true，则会不断地输出微调作业运行最新状态信息，直到微调作业完成（成功、取消或失败）时，以 `data：[DONE]` 消息终止。
>
>   如果设置为 false，则仅返回到目前为止生成的事件。
>

#### **Delete fine-tune model**
删除微调的模型（前提是有权限）
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/models/{model}
openai.Model.delete("curie:ft-acmeco-2021-03-03-21-44-20")
```
**响应** ：
```json
{
  "id": "curie:ft-acmeco-2021-03-03-21-44-20",
  "object": "model",
  "deleted": true
}
```
### Models 模型管理
列出并描述 API 中可用的各种模型，可以参考 [模型文档](https://platform.openai.com/docs/models) 以了解可用的模型以及它们之间的差异。

#### **列出模型**

列出当前可用的模型，并提供有关每个模型的基本信息，例如所有者和可用性。
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/models
openai.Model.list()
```

**响应**
：

```json
{
  "data": [
    {
      "id": "model-id-0",
      "object": "model",
      "owned_by": "organization-owner",
      "permission": [...]
    },
    {
      "id": "model-id-1",
      "object": "model",
      "owned_by": "organization-owner",
      "permission": [...]
    },
    {
      "id": "model-id-2",
      "object": "model",
      "owned_by": "openai",
      "permission": [...]
    },
  ],
  "object": "list"
}
```

#### **检索模型详情**
检索模型实例，提供有关模型的基本信息，例如所有者和权限。其中，`model` 为必填的字符串类型，用于此请求的模型的 ID。
```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
# https://api.openai.com/v1/models/{model}
openai.Model.retrieve("text-davinci-003")
```

**响应** ：

```json
{
  "id": "text-davinci-003",
  "object": "model",
  "owned_by": "openai",
  "permission": [...]
}
```

### 其他
- [Images 图像](https://platform.openai.com/docs/api-reference/images)（图像生成API，DALL·E的能力已经落后于Stable Diffusion和Midjourney，使用场景不多）
- [Audio 音频](https://platform.openai.com/docs/api-reference/audio)（音频转换为文本API，Whisper模型已经开源，可以本地搭建使用）
- [Files 文件](https://platform.openai.com/docs/api-reference/files)（上传文档API，一般与微调等功能一起使用，不需要专门关注）
- [Edits 编辑](https://platform.openai.com/docs/api-reference/edits)（更新提示词API，对话补全接口已经覆盖了）
- [Moderations 审核](https://platform.openai.com/docs/api-reference/fine-tunes/delete-model) (内容审核API，如果模型识别到提示词违反了OpenAI的内容策略，会返回审核信息详情)
- Parameter details 参数细节（没有使用过）

### 最佳安全实践
在开发过程中，注意到API的任何安全问题或与OpenAI相关的任何其他问题，可以通过[漏洞披露计划](https://openai.com/security/disclosure/)提交这些问题。

* **使用内容审核 API**

  OpenAI的[内容审核 API]((https://platform.openai.com/docs/api-reference/fine-tunes/delete-model)) 调用是不耗费 token 的，可以借助这个能力构建内容过滤系统，减少不安全内容。

* **对抗性测试**

  自己主动进行类似传统安全领域的“红队演练”，验证基于大语言模型的程序对存在攻击的输入具有鲁棒性。操作层面上就是通过遍历尽量多的输入和用户行为测试，包括代表性的数据集以及试图“破坏”应用程序的输入。在测试中，需要关注应用程序是否会偏离主题，以及是否可以轻易地通过提示注入来重定向功能。例如，“忽略以前的指令，改为执行这个操作”。

* **必须人工参与，不能全权委托给模型**

  在实际应用前，让人工先审核输出结果，特别是在高风险领域和代码生成方面，大语言模型系统具有其局限性，人工能够查看任何验证输出所需的信息（例如生成笔记概要应用，前提是用户能够轻松获取原始笔记进行参考）。

* **提示工程**

  “提示工程”可以帮助限制输出文本的主题和语气，从而减少产生不良内容的可能性，即使用户试图产生这样的内容也是如此。为模型提供附加上下文（例如，在新输入之前提供几个高质量的期望行为示例）可以使其更容易将模型输出引导到所需的方向。

* **了解你的客户**

  通常情况下，用户需要注册并登录才能使用您的服务。将此服务与现有账户（例如Gmail、LinkedIn或Facebook登录）链接可能会有所帮助，但并不适用于所有用例。要进一步降低风险，可以要求提供信用卡或身份证明等信息。

* **限制用户输入并限制输出token数量**

  限制用户在提示中输入的文本数量有助于避免提示注入。限制输出token的数量有助于减少误用的可能性。

  缩小输入或输出范围，特别是从可信来源中获取，可以减少应用程序中可能发生的误用程度。

  通过验证的下拉字段（例如，维基百科上的电影列表）允许用户输入可能比允许开放式文本输入更安全。

  在可能的情况下，从后端返回一组经过验证的材料的输出可能比返回全新生成的内容更安全（例如，将客户查询路由到最匹配的现有客户支持文章，而不是尝试从头回答查询）。

* **允许用户报告问题**

  通常情况下，用户应该有一个方便易用的方法来报告应用程序功能不当或其他相关问题（例如，列出的电子邮件地址、提交工单等）。这种方法应该由人工进行监控，并根据情况作出回应。

* **了解和沟通局限性**

  语言模型可能会出现诸如产生不准确信息、冒犯性输出、偏见等问题，这些问题可能需要进行显著的修改才能适用于每个用例。在考虑使用语言模型之前，请评估模型是否适合您的目的，并在广泛的潜在输入上测试API的性能，以确定API性能可能下降的情况。同时，考虑您的客户群体以及他们将要使用的输入范围，并确保他们的期望得到适当的调整。

* **终端用户ID**

  在请求中发送终端用户ID可以帮助OpenAI监测和检测滥用行为，这是一个有用的工具，这可以让OpenAI在检测到应用程序违反任何政策的情况下，提供更具有操作性的反馈。

  这些ID应该是一个字符串，用于唯一标识每个用户。建议对其用户名或电子邮件地址进行哈希处理，以避免发送任何身份信息。如果向非登录用户提供产品预览，可以发送一个会话ID。

  可以通过 `user` 参数在API请求中包含终端用户ID，如下所示：
  ```python
  response = openai.Completion.create(
    model="text-davinci-003",
    prompt="This is a test",
    max_tokens=5,
    user="user123456"
  )
  ```

### 最佳生产实践
本指南提供了一套全面的最佳实践，可帮助您从原型过渡到生产。无论您是经验丰富的机器学习工程师还是新近的爱好者，本指南都将为您提供成功将平台投入生产环境所需的工具：从保护对我们API的访问到设计一个能够处理大流量的强大架构。使用本指南帮助您制定一个尽可能顺利和有效的应用程序部署计划。

* **设置您的组织**

  一旦您登录到OpenAI帐户，您可以在组织设置中找到组织名称和ID。组织名称是您的组织的标签，显示在用户界面中。组织ID是您的组织的唯一标识符，可用于API请求中。

  属于多个组织的用户可以传递一个标题来指定用于API请求的组织。这些API请求的使用将计入指定组织的配额。如果没有提供标题，则会计费默认组织。您可以在用户设置中更改默认组织。

  您可以从成员设置页面邀请新成员加入您的组织。成员可以是阅读者或所有者。阅读者可以进行API请求并查看基本组织信息，而所有者可以修改计费信息并管理组织中的成员。

* **管理计费限额**

  新的免费试用用户将获得5美元的初始信用额，有效期为三个月。一旦信用额已被使用或到期，您可以选择输入计费信息以继续使用API。如果没有输入计费信息，您仍然可以登录访问，但将无法进行任何进一步的API请求。

  一旦您输入了计费信息，您将获得OpenAI设置的每月120美元的批准使用限制。如果您想增加超过每月120美元的配额，请提交配额增加请求。

  如果您希望在使用量超过一定金额时收到通知，您可以通过使用限制页面设置软限制。当达到软限制时，组织的所有者将收到电子邮件通知。您还可以设置硬限制，以便一旦达到硬限制，任何后续的API请求都将被拒绝。请注意，这些限制是尽力而为，使用量和限制之间可能会有5到10分钟的延迟。

* **API密钥**

  OpenAI API使用API密钥进行身份验证。访问您的API密钥页面以检索您将在请求中使用的API密钥。

  这是一种相对简单的控制访问方式，但您必须注意保护这些密钥。避免在您的代码或公共存储库中公开API密钥；相反，将它们存储在安全的位置。您应该使用环境变量或密钥管理服务将您的密钥暴露给您的应用程序，这样您就不需要在代码库中硬编码它们。

* **暂存帐户**

  随着规模的扩大，您可能希望为暂存和生产环境创建单独的组织。请注意，您可以使用两个单独的电子邮件地址（例如 bob+prod@widgetcorp.com 和 bob+dev@widgetcorp.com）进行注册，以创建两个组织。这将允许您隔离您的开发和测试工作，这样您就不会意外地中断您的实时应用程序。您还可以通过这种方式限制对生产组织的访问。

* **扩展您的解决方案架构**

  当设计你的应用程序或服务使用我们的API进行生产时，重要的是要考虑你将如何扩展以满足流量需求。无论你选择什么样的云服务提供商，你都需要考虑几个关键领域：

  横向扩展：你可能想横向扩展你的应用程序，以适应来自多个来源的应用程序的请求。这可能涉及到部署额外的服务器或容器来分配负载。如果你选择这种类型的扩展，请确保你的架构是为处理多个节点而设计的，并且你有机制来平衡它们之间的负载。

  垂直扩展：另一个选择是纵向扩展你的应用程序，这意味着你可以加强单个节点的可用资源。这将涉及升级你的服务器的能力，以处理额外的负载。如果你选择这种类型的扩展，确保你的应用程序被设计成可以利用这些额外的资源。
  缓存：通过存储经常访问的数据，你可以提高响应时间，而不需要重复调用我们的API。你的应用程序将需要被设计成尽可能地使用缓存数据，并在添加新信息时使缓存失效。有几种不同的方法可以做到这一点。例如，你可以将数据存储在数据库、文件系统或内存缓存中，这取决于什么对你的应用程序最有意义。
  负载平衡：最后，考虑负载平衡技术，以确保请求被均匀地分布在你的可用服务器上。这可能涉及到在你的服务器前使用一个负载平衡器或使用DNS轮流。平衡负载将有助于提高性能和减少

* **延迟**

  延迟是处理请求和返回响应所需的时间，完成请求的延迟主要受两个因素影响：模型和生成的token数量。完成请求的生命周期如下所示（大部分延迟通常来自token生成步骤）：

  - 网络：最终用户到 API 延迟
  - 服务器：处理提示token的时间
  - 服务器：采样/生成to ken的时间
  - 网络：API 到最终用户延迟

* **影响延迟的常见因素和可能的缓解技术**

  现在我们已经了解了延迟的基础知识，让我们看一下可能影响延迟的各种因素，大致按照从影响最大到最小的顺序排列。

  * **模型**

    我们的 API 提供了不同程度的复杂性和通用性的不同模型。最有能力的模型，例如 `gpt-4` ，可以生成更复杂和多样化的完成，但它们也需要更长的时间来处理您的查询。 `gpt-3.5-turbo` 等模型可以生成更快、更便宜的聊天完成，但它们生成的结果可能不太准确或与您的查询不相关。您可以选择最适合您的用例的模型以及速度和质量之间的权衡。

  * **补全token的数量**

    请求大量生成的token完成会导致延迟增加：

    - 较低的最大token数：对于具有相似token生成计数的请求，具有较低 `max_tokens` 参数的请求会产生较少的延迟。
    - 包括停止序列：为防止生成不需要的token，请添加停止序列。例如，您可以使用停止序列生成包含特定数量项目的列表。在这种情况下，通过使用 `11.` 作为停止序列，您可以生成一个只有 10 个项目的列表，因为当到达 `11.` 时完成将停止。
    - 生成更少的完成：尽可能降低 `n` 和 `best_of` 的值，其中 `n` 是指为每个提示生成多少个完成， `best_of` 用于表示每个标记具有最高对数概率的结果。如果 `n` 和 `best_of` 都等于1（这是默认值），则生成的token数最多等于 `max_tokens` 。如果 `n` （返回的完成数）或 `best_of` （生成以供考虑的完成数）设置为 `> 1` ，每个请求将创建多个输出。在这里，您可以将生成的token数视为 `[ max_tokens * max (n, best_of) ]`

  * **流式传输**

    在请求中设置 `stream: true` 会使模型在token可用时立即开始返回token，而不是等待生成完整的token序列。它不会改变获取所有token的时间，但它会减少我们想要显示部分进度或将停止生成的应用程序的第一个token的时间。这可能是更好的用户体验和 UX 改进，因此值得尝试流式传输。

  * **批处理**

    根据您的用例，批处理可能会有所帮助。如果您向同一个端点发送多个请求，您可以批处理要在同一个请求中发送的提示。这将减少您需要提出的请求数量。 prompt 参数最多可以包含 20 个不同的提示。我们建议您测试此方法，看看是否有帮助。在某些情况下，您最终可能会增加生成的token数量，这会减慢响应时间。

* **MLOps策略**

  当您将原型投入生产时，您可能需要考虑制定 MLOps 策略。 MLOps（机器学习操作）是指管理机器学习模型的端到端生命周期的过程，包括您可能使用我们的 API 进行微调的任何模型。设计 MLOps 策略时需要考虑多个方面。这些包括

  - 数据和模型管理：管理用于训练或微调模型以及跟踪版本和更改的数据。
  - 模型监控：随着时间的推移跟踪模型的性能并检测任何潜在的问题或退化。
  - 模型再训练：确保您的模型与数据变化或不断变化的需求保持同步，并根据需要进行再训练或微调。
  - 模型部署：自动化将模型和相关工件部署到生产中的过程。

### 参考链接
1. [OpenAI 文档](https://platform.openai.com/docs/introduction)
2. [OpenAI Cookbook](https://github.com/openai/openai-cookbook)：分享了使用OpenAI API完成常见任务的示例代码

