OpenAI文本嵌入测量文本字符串之间的相关性

什么是嵌入?

OpenAI的文本嵌入测量文本字符串之间的相关性。 嵌入通常用于:

  1. 搜索(结果按查询字符串相关性排序)
  2. 聚类(将文本字符串按相似性分组)
  3. 推荐(推荐具有相关文本字符串的项目)
  4. 异常检测(识别与其他内容关联度较小的离群值)
  5. 多样性测量(分析相似度分布情况)
  6. 分类(根据最相似标签对文本字符串进行分类)

-嵌入是一个浮点数向量列表。两个向量之间的距离衡量它们之间的相关性。小距离表示高相关性,大距离表示低相关性。

请访问我们的定价页面了解嵌入价格。请求基于发送输入中令牌数量计费。

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

分类
主题聚类
搜索
推荐
浏览示例

如何获取嵌入

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

示例请求:

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中查看更多Python代码示例。

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

嵌入模型

OpenAI 提供了一个第二代嵌入模型(在模型 ID 中标记为 -002)和 16 个第一代模型(在模型 ID 中标记为 -001)。

我们建议几乎所有用例都使用 text-embedding-ada-002。它更好、更便宜、更简单易用。请阅读博客文章公告。

模型生成器分词器最大输入标记数知识截断
V2cl100k_base81912021年9月
V1GPT-2/GPT-320462020年8月

使用按输入令牌计价,每1000个令牌的费率为$0.0004,或者大约每美元3000页(假设每页约800个令牌):

型号每美元粗略页面数在BEIR搜索评估中的示例性能
文本嵌入ada-002300053.9
-davinci--001652.8
-curie--0016050.9
-babbage--00124050.4
-ada--00130049.0

第二代模型

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

第一代模型(不建议使用)

用例

这里我们展示一些代表性的用例。以下示例将使用亚马逊美食评论数据集。

获取嵌入

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

产品ID用户ID得分摘要正文
B001E4KFG0A3SGXH7AUHU8GW5优质的狗粮我已经买了几罐活力罐头...
B00813GRG4A1D87F6ZCVE5NK1不如广告描述该产品标签上写着巨型盐腌花生...
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)

2D数据可视化

嵌入的大小取决于底层模型的复杂性。为了可视化这个高维数据,我们使用t-SNE算法将数据转换成二维。

我们根据评论者给出的星级评分对每篇评论进行着色:

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

这个可视化似乎产生了大约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")

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

这次,我们不再让算法预测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)

零样本分类

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

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'

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

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

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

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

聚类

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

在这个例子中,我们发现了四个不同的簇:一个关注狗粮,一个关注负面评论,两个关注正面评论。

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_

使用嵌入进行文本搜索

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

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)

使用嵌入进行代码搜索

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

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

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)

使用嵌入推荐

因为嵌入向量之间的距离越短,表示它们之间的相似度越高,所以嵌入可以用于推荐。

下面我们展示一个基本的推荐器。它接收一组字符串和一个“源”字符串,计算它们的嵌入,并返回按相似度从高到低排名的字符串列表。作为具体例子,下面链接中的笔记本应用了这个函数版本来处理AG新闻数据集(采样至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

限制和风险

我们的嵌入模型在某些情况下可能不可靠或存在社会风险,并且在缺乏减轻措施的情况下可能会造成伤害。

社会偏见

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

我们通过运行SEAT(May等人,2019)和Winogender(Rudinger等人,2018)基准测试发现我们的模型存在偏见证据。这些基准测试共包括7个测试,用于衡量模型在应用于性别化名称、地区名称和某些刻板印象时是否含有隐含偏见。

例如,我们发现我们的模型更强烈地将(a)欧洲裔美国人的名字与积极情感联系起来,而与非洲裔美国人的名字相比,则不是那么明显;以及(b)将负面刻板印象与黑女性联系起来。

这些基准测试在多个方面都有限制:(a)它们可能无法推广到您特定的使用案例中;(b)它们仅对可能存在社会偏见的一小部分进行了测试。

这些测试是初步结果,并且我们建议针对您特定的使用案例进行测试。这些结果应被视为该现象存在的证据,并非对您使用案例中该现象作出最终描述。请参阅我们的使用政策以获取更多详细信息和指导。

如果您有任何问题,请通过聊天联系我们支持团队; 我们很乐意为此提供建议。

对最近事件的无视

限制:模型缺乏对2020年8月之后发生事件的了解。

我们的模型是基于包含有关现实世界事件信息的数据集进行训练的,但仅限于2020年8月之前。如果您依赖这些模型来代表最近发生的事件,则它们可能表现不佳

常见问题

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

在Python中,您可以使用OpenAI的分词器tiktoken将字符串拆分为标记。

示例代码:

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编码。

更多细节和示例代码在OpenAI Cookbook指南中,介绍如何使用tiktoken计算标记。

如何快速检索K个最近的嵌入向量?

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

可用的向量数据库选项包括:

  • Pinecone,一个完全托管的向量数据库
  • Weaviate,一个开源矢量搜索引擎
  • Redis作为矢量数据库
  • Qdrant,一个矢量搜索引擎
  • Milvus,专为可伸缩相似性搜索而构建的矢量数据库
  • Chroma,一个开源嵌入存储库

我应该使用哪种距离函数?

我们推荐余弦相似度。通常,距离函数的选择并不重要。

OpenAI嵌入已经被归一化为长度1,这意味着:

可以仅使用点积更快地计算余弦相似度

余弦相似度和欧几里得距离将产生相同的排名

我可以在线分享我的嵌入向量吗?

客户拥有我们模型的输入和输出,包括嵌入向量。您需要确保您在使用我们的API时输入的内容不违反任何适用法律或我们的使用条款。

如果您也想体验原生ChatGPT 不妨试试  使用 API 随心用 

采用该方法就可以 使用 API 随心用 可以将各种主流 Al 的模型能力集成到您的应用程序或业务中 API 主要在代码中调用

还可以达到 OpenAI快捷注册 一键升级

可以满足不同需求用户 使用 API 随心用

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值