入门文档(docs)
指南(Guides)
嵌入指南(Embeddings Guide)

嵌入(Embeddings)(Embeddings)

什么是嵌入(Embeddings)?(What are embeddings?)

OpenAI的文本嵌入(Embeddings)(embeddings)可以测量文本字符串的相关性。嵌入(Embeddings)通常用于:

  • 搜索(根据与查询字符串的相关性对结果进行排名)
  • 聚类(按相似度对文本字符串进行分组)
  • 推荐(推荐与相关文本字符串相关的项目)
  • 异常检测(识别与相关度较低的异常值)
  • 多样性测量(分析相似度分布)
  • 分类(根据其最相似的标签对文本字符串进行分类)

嵌入(Embeddings)是一个浮点数向量(列表)。两个向量之间的距离测量它们之间的相关性。较小的距离表明高相关性,而较大的距离则表明低相关性。

访问我们的价格页面 (opens in a new tab)了解嵌入(Embeddings)的价格。

根据发送的input (opens in a new tab)中的token数量计费请求。

要查看嵌入(Embeddings)的实际应用,请查看我们的代码示例

  • 分类
  • 主题聚类
  • 搜索
  • 推荐

浏览用例

如何获取嵌入(Embeddings)(How to get embeddings)

要获取嵌入(Embeddings),将您的文本字符串与嵌入(Embeddings)模型ID(例如text-embedding-ada-002)一起发送到嵌入(Embeddings)API终端点(Completion) (opens in a new tab)

响应将包含一个嵌入(Embeddings),您可以提取、保存和使用。

示例请求:

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 (opens in a new tab)中查看更多Python代码示例。

使用OpenAI嵌入(Embeddings)时,请注意它们的限制和风险

嵌入(Embeddings)模型 Embedding models

OpenAI提供一个第二代嵌入(Embeddings)模型(模型ID中用-002表示),以及16个第一代模型(模型ID中用-001表示)。

我们建议在几乎所有情况下使用text-embedding-ada-002。它更好、更便宜、更简单易用。阅读博客文章公告 (opens in a new tab)

模型生成分词工具最大输入标记数知识截止时间
V2cl100k_base81912021 年 9 月份
V1GPT-2/GPT-320462020 年 8 月份

使用价格按输入令牌计价,每1000个令牌价格为$0.0004,或约为每美元约3,000页(假设每页约有800个令牌):

模型(Model)一美元页数(Rough pages per dollar)BEIR评分(Example performance on BEIR (opens in a new tab) search eval)
text-embedding-ada-002300053.9
-davinci--001652.8
-curie--0016050.9
-babbage--00124050.4
-ada--00130049.0

第二代模型

模型名称分词工具最大输入标记数输出维度
text-embedding-ada-002cl100k_base81911536

第一代嵌入(Embeddings) (不推荐not recommended)

所有第一代模型(以-001结尾的)使用GPT-3分词器 (opens in a new tab),最多可输入2046个令牌。

第一代嵌入(Embeddings)是由五个不同的模型家族生成,针对三种不同的任务进行了调整:文本搜索、文本相似度和代码搜索。

搜索模型以一对出现:一个用于短查询,一个用于长文档。(五个:文本搜索、文本相似度和代码搜索、短查询、长文档)

每个模型家族都包括高质量高速度等四个维度:

Modeloutput dimensions
Ada1024
Babbage2048
Curie4096
Davinci12288

Davinci 是最强大的,但比其他模型慢且更贵。Ada 是最不强大的,但速度和价格都比较快和便宜。

相似度嵌入(Embeddings) Similarity embeddings

相似度模型最擅长捕捉文本之间的语义相似性。

应用场景可用模型
聚类、回归、异常检测、可视化text-similarity-ada-001``text-similarity-babbage-001``text-similarity-curie-001 text-similarity-davinci-001

文本搜索嵌入(Embeddings) Text search embeddings

文本搜索模型有助于衡量哪些长文档与短搜索查询最相关。

使用两种模型:一个用于嵌入(Embeddings)搜索查询,一个用于嵌入(Embeddings)要排序的文档。

与搜索查询嵌入(Embeddings)最接近的文档嵌入(Embeddings)应该是最相关的。

应用场景可用模型
搜索、上下文相关性、信息检索text-search-ada-doc-001``text-search-ada-query-001``text-search-babbage-doc-001``text-search-babbage-query-001``text-search-curie-doc-001``text-search-curie-query-001``text-search-davinci-doc-001``text-search-davinci-query-001

检索的代码片段嵌入(Embeddings) Code search embeddings

与搜索嵌入(Embeddings)类似,有两种类型:一种用于嵌入(Embeddings)自然语言搜索查询,一种用于嵌入(Embeddings)要检索的代码片段。

应用场景可用模型
代码搜索和相关性code-search-ada-code-001``code-search-ada-text-001``code-search-babbage-code-001``code-search-babbage-text-001

对于-001文本嵌入(Embeddings)(不是-002和代码嵌入(Embeddings)),我们建议将输入中的换行符(\n)替换为单个空格,因为我们发现当存在换行符时结果更差。

综合使用案例

这里我们展示了一些代表性用例。我们将使用Amazon美食品论评论数据集 (opens in a new tab)作为以下示例。

数据集嵌入(Embeddings) Obtaining the embeddings

该数据集包含截至2012年10月为止,亚马逊用户留下的共计568,454条食品评论。我们将使用最近1,000篇评论的子集进行说明。评论是英语,往往是正面或负面的。每个评论都有一个产品ID、用户ID、得分、评论标题(摘要)和评论正文(文本)。例如:

产品编号Product IdUser IdScoreSummaryText
B001E4KFG0A3SGXH7AUHU8GW5Good Quality Dog FoodI have bought several of the Vitality canned...
B00813GRG4A1D87F6ZCVE5NK1Not as AdvertisedProduct arrived labeled as Jumbo Salted Peanut...

我们将把评论摘要和评论文本合并成单一的组合文本。模型将对这个组合文本进行编码,并输出一个单一的向量嵌入(Embeddings)Obtain_dataset (opens in a new tab)

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)

要从一个保存的文件中加载数据,你可以运行以下代码:

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

嵌入(Embeddings)数据二维可视化Visualizing_embeddings_in_2D (opens in a new tab)

嵌入(Embeddings)的维度会随着底层模型的复杂性而变化。

为了将这种高维数据可视化,我们使用t-SNE算法将数据转换成二维。

我们根据评论者所给的星级给个别评论着色:

  • 1星:红色
  • 2星:深橙色
  • 3星:金色
  • 4星:青绿色
  • 5星:深绿色

Amazon ratings visualized in language using t-SNE可视化似乎产生了大约3个聚类,其中一个聚类主要是负面评价。

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")

综合文本嵌入(Embeddings)

综合文本嵌入(Embeddings)用作ML机器学习算法的文本特征编码Regression_using_embeddings (opens in a new tab)

嵌入(Embeddings)可以作为机器学习模型中的一般自由文本特征编码器使用。

如果一些相关输入是自由文本,那么添加嵌入(Embeddings)将改善任何机器学习模型的性能。

嵌入(Embeddings)也可以用作ML模型中的分类特征编码器。

如果分类变量的名称是有意义而且众多的,比如职称,这将增加最大的价值。

对于这一任务,相似性嵌入(Embeddings)通常比搜索嵌入(Embeddings)的表现更好。

我们发现嵌入(Embeddings)表示通常非常丰富和信息密集。例如,使用SVD或PCA将输入的维度降低10%,通常会导致特定任务的下游性能变差。

此代码将数据分成一个训练集和一个测试集,这将作为以下两个用例(回归和分类)使用。

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
)

使用嵌入(Embeddings)特征进行回归 Regression using the embedding features

嵌入(Embeddings)可以优雅地预测数值。

在这个例子中,我们根据评论的文本预测评论者的评分。由于嵌入(Embeddings)所包含的语义信息很高,即使只有很少的评论,预测结果也很好。

我们假设评分是在1到5之间的连续变量,并允许算法预测任何浮点值。

机器学习算法将预测值与真实分数的距离最小化,并实现了平均绝对误差为0.39,这意味着平均预测偏差不到半颗星。

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

综合使用嵌入(Embeddings)特征进行分类Classification_using_embeddings (opens in a new tab)

这一次,我们将尝试将算法预测的值划分为5个级别,从1星到5星,而不是在1到5之间的任何位置。

在训练之后,模型学会了更好地预测1星和5星的评论,而对于更微妙的评价(2-4星),预测效果可能会差一些,这可能是因为情感表达更加极端。

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 (opens in a new tab)

我们可以使用嵌入(Embeddings)进行零样本分类,而无需任何标记的训练数据。对于每个类别,我们嵌入(Embeddings)类别名称或类别的简短描述。

要以零样本方式分类一些新的文本,我们将其嵌入(Embeddings)与所有类嵌入(Embeddings)进行比较,并预测相似度最高的类别。

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'

综合获取用户和产品嵌入(Embeddings)以进行冷启动推荐

案例:Collapse‍ Obtaining user and product embeddings for cold-start recommendationUser_and_product_embeddings (opens in a new tab)

我们可以通过对所有评论进行平均来获得用户嵌入(Embeddings)。(评论->用户嵌入)

同样,我们可以通过对关于该产品的所有评论进行平均来获得产品嵌入(Embeddings)。(评论->产品嵌入)

为了展示这种方法的有用性,我们使用了50000条评论的子集,以涵盖更多用户和产品的评论。

我们在单独的测试集上评估这些嵌入(Embeddings)的实用性,通过将用户和产品嵌入(Embeddings)的相似性作为评分的函数来进行绘制。

有趣的是,基于这种方法,即使在用户收到产品之前,我们也可以比随机更好地预测他们是否会喜欢该产品。

Boxplot grouped by Score

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

聚类Collapse‍ ClusteringClustering (opens in a new tab)

聚类是理解大量文本数据的一种方法。

嵌入(Embeddings)对于此任务非常有用,因为它们为每个文本提供语义上有意义的向量表示。

因此,以无监督的方式,聚类将揭示我们数据集中的隐藏分组。

在此示例中,我们发现了四个不同的聚类簇:一个聚焦于狗粮,一个聚焦于负面评论,两个聚焦于正面评论。

Clusters identified visualized in language 2d using t-SNE

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 (opens in a new tab)

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

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)

综合使用嵌入(Embeddings)进行代码搜索

尝试一下:Code_search (opens in a new tab)

代码搜索的工作原理类似于基于嵌入(Embeddings)的文本搜索。

我们提供了一种从给定的代码库中提取Python函数的方法。然后,每个函数都由text-embedding-ada-002模型进行索引。

为了进行代码搜索,我们使用相同的模型将查询嵌入(Embeddings)到自然语言中。

然后,我们计算查询嵌入(Embeddings)和每个函数嵌入(Embeddings)之间的余弦相似度。

得分最高的余弦相似度结果最相关。

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)

综合使用嵌入(Embeddings)进行推荐

尝试一下:(Recommendation_using_embeddings) (opens in a new tab)

因为嵌入(Embeddings)向量之间的距离较短表示更大的相似性,所以嵌入(Embeddings)向量可以用于推荐。

在下面,我们演示了一个基本的推荐程序。它接受一个字符串列表和一个“源”字符串,计算它们的嵌入(Embeddings),并返回一个字符串的排名,从最相似到最不相似的排名。

作为具体的例子,下面的链接将该函数的一个版本应用于AG新闻数据集 (opens in a new tab)(采样至2000个新闻文章描述),返回与任何给定源文章最相似的前5篇文章。

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
 

限制和风险Limitations & risks

我们的嵌入(Embeddings)模型在某些情况下可能不可靠或带有社会风险,并且在缺乏缓解措施的情况下可能会造成伤害。

社会偏见 Social bias

限制:模型通过刻板印象或对某些群体的负面情绪来编码社会偏见。

我们通过运行SEAT(May等人,2019年 (opens in a new tab))和Winogender(Rudinger等人, 2018年 (opens in a new tab))基准,发现了我们模型中的偏差证据。这些基准共包括7个测试,用于测定模型在应用于有性别名称、地域名称和某些刻板印象时是否包含隐含的偏差。

例如,我们发现我们的模型更强烈地将:

(a)欧洲裔美国人的名字与积极情感联系起来,而与非裔美国人的名字相比,

(b)将负面刻板印象与黑人女性联系起来。

这些基准在几个方面有限制:

(a)它们可能不适用于您的特定用例,

(b)它们仅测试了可能的社会偏见的非常小的一部分。

这些测试是初步的,我们建议针对您特定的用例运行测试。

这些结果应被视为现象存在的证据,而不是其对您的用例的确定性描述。

欲了解更多详情和指导,请查看我们的使用政策 (opens in a new tab)

如果您有任何问题,请通过聊天与我们的支持团队联系 (opens in a new tab),我们很乐意为您提供建议。

对最近事件的盲视

限制:模型缺乏2020年8月之后发生事件的知识。

我们的模型是在包含一些关于真实世界事件的信息的数据集上进行训练的,截至2020年8月。

如果您依赖于模型代表最近事件,则可能表现不佳。

常见问题

如何在嵌入(Embeddings)字符串之前确定它有多少标记?

在Python中,您可以使用OpenAI的分词器tiktoken (opens in a new tab)将一个字符串分成标记。

示例代码:

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")

对于第二代嵌入(Embeddings)模型(如text-embedding-ada-002),请使用cl100k_base编码。

更多详情和示例代码请参见 OpenAI Cookbook 指南如何使用tiktoken计算令牌数 (opens in a new tab)

怎么快速搜索多个向量? How can I retrieve K nearest embedding vectors quickly?

为了快速搜索多个向量,我们建议使用向量数据库。

您可以在GitHub上的Cookbook (opens in a new tab)中找到使用向量数据库和OpenAI API的示例。

向量数据库选项包括:

我该使用什么距离函数? Which distance function should I use?

我们推荐使用余弦相似度 (opens in a new tab)。距离函数的选择通常不太重要。

OpenAI的嵌入(Embeddings)是归一化到长度为1的,这意味着:

  • 使用点积可以更快地计算余弦相似度
  • 余弦相似度和欧几里得距离将得到相同的排名

我可以网上分享我的嵌入(Embeddings)吗? Can I share my embeddings online?

您作为用户,拥有我们模型中的输入和输出,包括嵌入(Embeddings)。

但是您有责任确保您输入到我们API中的内容不违反任何适用的法律或我们的使用条款 (opens in a new tab)