OpenAI API 嵌入

2023-03-17 16:11 更新

什么是嵌入?

OpenAI 的文本嵌入衡量文本字符串的相關(guān)性。嵌入通常用于:

  • 搜索(結(jié)果按與查詢(xún)字符串的相關(guān)性排序)

  • 聚類(lèi)(其中文本字符串按相似性分組)

  • 推薦(推薦具有相關(guān)文本字符串的項(xiàng)目)

  • 異常檢測(cè)(識(shí)別出相關(guān)性很小的異常值)

  • 多樣性測(cè)量(分析相似性分布)

  • 分類(lèi)(其中文本字符串按其最相似的標(biāo)簽分類(lèi))

嵌入是浮點(diǎn)數(shù)的向量(列表)。兩個(gè)向量之間的距離衡量它們的相關(guān)性。小距離表示高相關(guān)性,大距離表示低相關(guān)性。

訪(fǎng)問(wèn)我們的定價(jià)頁(yè)面以了解嵌入定價(jià)。請(qǐng)求根據(jù)發(fā)送的輸入中的令牌數(shù)量計(jì)費(fèi)。

如何獲得嵌入

要獲得嵌入,請(qǐng)將您的文本字符串連同選擇的嵌入模型 ID(例如,text-embedding-ada-002)一起發(fā)送到嵌入 API 端點(diǎn)。響應(yīng)將包含一個(gè)嵌入,您可以提取、保存和使用它。

示例請(qǐng)求:

 python curl 
response = openai.Embedding.create(
    input="Your text string goes here",
    model="text-embedding-ada-002"
)
embeddings = response['data'][0]['embedding']
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"
  }'

示例響應(yīng):

{
  "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 提供了一個(gè)第二代嵌入模型(在模型 ID 中用 -002 表示)和 16 個(gè)第一代模型(在模型 ID 中用 -001 表示)。

我們建議對(duì)幾乎所有用例使用 text-embedding-ada-002。它更好、更便宜、更易于使用。

模型生成 分詞器 最大輸入token 數(shù)據(jù)來(lái)源截止至
V2 cl100k_base 8191 Sep 2021
V1 GPT-2/GPT-3 2046 Aug 2020

使用量按輸入令牌定價(jià),每 1000 個(gè)令牌 0.0004 美元,或每美元約 3,000 頁(yè)(假設(shè)每頁(yè)約 800 個(gè)令牌):

模型 每美元粗略頁(yè)數(shù) BEIR SEARCH EVAL 的性能示例
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

第二代模型

模型名稱(chēng) 分詞器 最大輸入token 輸出
text-embedding-ada-002 cl100k_base 8191 1536

第一代模型(不推薦)

所有第一代模型(以 -001 結(jié)尾的模型)都使用 GPT-3 分詞器,最大輸入為 2046 個(gè)分詞。

第一代嵌入由五個(gè)不同的模型系列生成,這些模型系列針對(duì)三個(gè)不同的任務(wù)進(jìn)行了調(diào)整:文本搜索、文本相似性和代碼搜索。搜索模型成對(duì)出現(xiàn):一個(gè)用于短查詢(xún),一個(gè)用于長(zhǎng)文檔。每個(gè)系列最多包括四種質(zhì)量和速度不同的型號(hào):

模型 輸出
Ada 1024
Babbage 2048
Curie 4096
Davinci 12288

Davinci 是最有能力的,但比其他型號(hào)更慢且更昂貴。 Ada 的能力最差,但速度更快,成本更低。

相似性嵌入

相似性模型最擅長(zhǎng)捕捉文本片段之間的語(yǔ)義相似性。

用例 可用模型
Clustering, regression, anomaly detection, visualization text-similarity-ada-001
text-similarity-babbage-001
text-similarity-curie-001
text-similarity-davinci-001

文本搜索嵌入

文本搜索模型有助于衡量哪些長(zhǎng)文檔與短搜索查詢(xún)最相關(guān)。使用了兩種模型:一種用于嵌入搜索查詢(xún),一種用于嵌入要排名的文檔。最接近查詢(xún)嵌入的文檔嵌入應(yīng)該是最相關(guān)的。

用例 可用模型
Search, context relevance, information retrieval 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

代碼搜索嵌入

與搜索嵌入類(lèi)似,有兩種類(lèi)型:一種用于嵌入自然語(yǔ)言搜索查詢(xún),一種用于嵌入要檢索的代碼片段。

用例 可用模型
Code search and relevance code-search-ada-code-001
code-search-ada-text-001
code-search-babbage-code-001
code-search-babbage-text-001

對(duì)于 -001 文本嵌入(不是 -002,也不是代碼嵌入),我們建議將輸入中的換行符 (\n) 替換為單個(gè)空格,因?yàn)楫?dāng)存在換行符時(shí)我們已經(jīng)看到更糟糕的結(jié)果。

用例

在這里,我們展示了一些有代表性的用例。我們將在以下示例中使用亞馬遜美食評(píng)論數(shù)據(jù)集。

獲取嵌入

該數(shù)據(jù)集包含截至 2012 年 10 月亞馬遜用戶(hù)留下的總共 568,454 條食品評(píng)論。我們將使用 1,000 條最新評(píng)論的子集用于說(shuō)明目的。評(píng)論是英文的,往往是正面的或負(fù)面的。每條評(píng)論都有一個(gè) ProductId、UserId、Score、評(píng)論標(biāo)題(Summary)和評(píng)論正文(Text)。例如:

PRODUCT ID USER ID SCORE SUMMARY TEXT
B001E4KFG0 A3SGXH7AUHU8GW 5 Good Quality Dog Food I have bought several of the Vitality canned...
B00813GRG4 A1D87F6ZCVE5NK 1 Not as Advertised Product arrived labeled as Jumbo Salted Peanut...

我們會(huì)將評(píng)論摘要和評(píng)論文本合并為一個(gè)組合文本。該模型將對(duì)該組合文本進(jìn)行編碼并輸出單個(gè)向量嵌入。

Obtain_dataset.ipynb

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)

要從保存的文件中加載數(shù)據(jù),您可以運(yùn)行以下命令:

import pandas as pd
 
df = pd.read_csv('output/embedded_1k_reviews.csv')
df['ada_embedding'] = df.ada_embedding.apply(eval).apply(np.array)
  • 二維數(shù)據(jù)可視化

  • Visualizing_embeddings_in_2D.ipynb

    嵌入的大小隨底層模型的復(fù)雜性而變化。為了可視化這種高維數(shù)據(jù),我們使用 t-SNE 算法將數(shù)據(jù)轉(zhuǎn)換為二維。

    我們根據(jù)評(píng)論者給出的星級(jí)評(píng)分為各個(gè)評(píng)論著色:

    • 1-star: 紅色
    • 2-star: 深橙色
    • 3-star: 金色
    • 4-star: 薄荷綠
    • 5-star: 深綠色

    Amazon ratings visualized in language using t-SNE

    可視化似乎產(chǎn)生了大約 3 個(gè)集群,其中一個(gè)集群的評(píng)論大多是負(fù)面的。

    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")
  • 嵌入作為 ML 算法的文本特征編碼器

  • Regression_using_embeddings.ipynb

    嵌入可以用作機(jī)器學(xué)習(xí)模型中的通用自由文本特征編碼器。如果一些相關(guān)輸入是自由文本,則合并嵌入將提高任何機(jī)器學(xué)習(xí)模型的性能。嵌入也可以用作 ML 模型中的分類(lèi)特征編碼器。如果分類(lèi)變量的名稱(chēng)有意義且數(shù)量眾多,例如職位名稱(chēng),那么這會(huì)增加最大的價(jià)值。對(duì)于此任務(wù),相似性嵌入通常比搜索嵌入表現(xiàn)更好。

    我們觀(guān)察到,通常嵌入表示非常豐富且信息密集。例如,使用 SVD 或 PCA 降低輸入的維度,即使降低 10%,通常也會(huì)導(dǎo)致特定任務(wù)的下游性能變差。

    此代碼將數(shù)據(jù)拆分為訓(xùn)練集和測(cè)試集,將由以下兩個(gè)用例使用,即回歸和分類(lèi)。

    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
    )

    使用嵌入特征進(jìn)行回歸

    嵌入提供了一種預(yù)測(cè)數(shù)值的優(yōu)雅方法。在這個(gè)例子中,我們根據(jù)評(píng)論的文本預(yù)測(cè)評(píng)論者的星級(jí)。因?yàn)榍度胫邪恼Z(yǔ)義信息很高,所以即使評(píng)論很少,預(yù)測(cè)也不錯(cuò)。

    我們假設(shè)分?jǐn)?shù)是 1 到 5 之間的連續(xù)變量,并允許算法預(yù)測(cè)任何浮點(diǎn)值。 ML 算法最小化預(yù)測(cè)值與真實(shí)分?jǐn)?shù)的距離,并實(shí)現(xiàn) 0.39 的平均絕對(duì)誤差,這意味著平均預(yù)測(cè)偏差不到半星。

    from sklearn.ensemble import RandomForestRegressor
     
    rfr = RandomForestRegressor(n_estimators=100)
    rfr.fit(X_train, y_train)
    preds = rfr.predict(X_test)
  • 使用嵌入特征進(jìn)行分類(lèi)

  • Classification_using_embeddings.ipynb

    這一次,我們不再讓算法預(yù)測(cè) 1 到 5 之間的任何值,而是嘗試將評(píng)論的確切星數(shù)分類(lèi)為 5 個(gè)桶,范圍從 1 到 5 星。

    訓(xùn)練后,該模型學(xué)習(xí)預(yù)測(cè) 1 星和 5 星評(píng)論比更細(xì)微的評(píng)論(2-4 星)更好,這可能是由于更極端的情緒表達(dá)。

    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)
  • 零樣本分類(lèi)

  • Zero-shot_classification_with_embeddings.ipynb

    我們可以在沒(méi)有任何標(biāo)記訓(xùn)練數(shù)據(jù)的情況下使用嵌入進(jìn)行零鏡頭分類(lèi)。對(duì)于每個(gè)類(lèi),我們嵌入類(lèi)名或類(lèi)的簡(jiǎn)短描述。為了以零樣本方式對(duì)一些新文本進(jìn)行分類(lèi),我們將其嵌入與所有類(lèi)嵌入進(jìn)行比較,并預(yù)測(cè)具有最高相似度的類(lèi)。

    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'
  • 獲取用于冷啟動(dòng)推薦的用戶(hù)和產(chǎn)品嵌入

  • User_and_product_embeddings.ipynb

    我們可以通過(guò)對(duì)他們的所有評(píng)論進(jìn)行平均來(lái)獲得用戶(hù)嵌入。同樣,我們可以通過(guò)對(duì)有關(guān)該產(chǎn)品的所有評(píng)論進(jìn)行平均來(lái)獲得產(chǎn)品嵌入。為了展示這種方法的實(shí)用性,我們使用 50k 評(píng)論的子集來(lái)覆蓋每個(gè)用戶(hù)和每個(gè)產(chǎn)品的更多評(píng)論。

    我們?cè)趩为?dú)的測(cè)試集上評(píng)估這些嵌入的有用性,我們將用戶(hù)和產(chǎn)品嵌入的相似性繪制為評(píng)分的函數(shù)。有趣的是,基于這種方法,甚至在用戶(hù)收到產(chǎn)品之前,我們就可以比隨機(jī)預(yù)測(cè)更好地預(yù)測(cè)他們是否喜歡該產(chǎn)品。

    Boxplot grouped by Score

    user_embeddings = df.groupby('UserId').ada_embedding.apply(np.mean)
    prod_embeddings = df.groupby('ProductId').ada_embedding.apply(np.mean)
  • 聚類(lèi)
  • Clustering.ipynb

    聚類(lèi)是理解大量文本數(shù)據(jù)的一種方式。嵌入對(duì)于這項(xiàng)任務(wù)很有用,因?yàn)樗鼈兲峁┝嗣總€(gè)文本的語(yǔ)義上有意義的向量表示。因此,以一種無(wú)監(jiān)督的方式,聚類(lèi)將揭示我們數(shù)據(jù)集中隱藏的分組。

    在這個(gè)例子中,我們發(fā)現(xiàn)了四個(gè)不同的集群:一個(gè)專(zhuān)注于狗食,一個(gè)專(zhuān)注于負(fù)面評(píng)論,兩個(gè)專(zhuān)注于正面評(píng)論。

    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.ipynb

    為了檢索最相關(guān)的文檔,我們使用查詢(xún)的嵌入向量與每個(gè)文檔之間的余弦相似度,并返回得分最高的文檔。

    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

    代碼搜索的工作方式類(lèi)似于基于嵌入的文本搜索。我們提供了一種從給定存儲(chǔ)庫(kù)中的所有 Python 文件中提取 Python 函數(shù)的方法。然后每個(gè)函數(shù)都由 text-embedding-ada-002 模型索引。

    為了執(zhí)行代碼搜索,我們使用相同的模型將查詢(xún)嵌入到自然語(yǔ)言中。然后我們計(jì)算結(jié)果查詢(xún)嵌入和每個(gè)函數(shù)嵌入之間的余弦相似度。最高的余弦相似度結(jié)果是最相關(guān)的。

    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

    因?yàn)榍度胂蛄恐g的距離越短表示相似度越高,嵌入可用于推薦。

    下面,我們說(shuō)明了一個(gè)基本的推薦系統(tǒng)。它接受一個(gè)字符串列表和一個(gè)“源”字符串,計(jì)算它們的嵌入,然后返回字符串的排名,從最相似到最不相似。作為一個(gè)具體示例,下面鏈接的筆記本將此函數(shù)的一個(gè)版本應(yīng)用于 AG 新聞數(shù)據(jù)集(采樣到 2,000 篇新聞文章描述)以返回與任何給定源文章最相似的前 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

局限性和風(fēng)險(xiǎn)

我們的嵌入模型可能不可靠或在某些情況下會(huì)帶來(lái)社會(huì)風(fēng)險(xiǎn),并且在沒(méi)有緩解措施的情況下可能會(huì)造成傷害。

社會(huì)偏見(jiàn)

局限性:模型對(duì)社會(huì)偏見(jiàn)進(jìn)行編碼,例如通過(guò)對(duì)某些群體的刻板印象或負(fù)面情緒。

我們通過(guò)運(yùn)行 SEAT(May 等人,2019 年)和 Winogender(Rudinger 等人,2018 年)基準(zhǔn)測(cè)試發(fā)現(xiàn)了模型中存在偏差的證據(jù)。這些基準(zhǔn)一起包含 7 個(gè)測(cè)試,用于衡量模型在應(yīng)用于性別名稱(chēng)、區(qū)域名稱(chēng)和某些刻板印象時(shí)是否包含隱性偏見(jiàn)。

例如,我們發(fā)現(xiàn),與非裔美國(guó)人的名字相比,我們的模型更強(qiáng)烈地將 (a) 歐裔美國(guó)人的名字與積極情緒聯(lián)系起來(lái),以及 (b) 對(duì)黑人女性的負(fù)面刻板印象。

這些基準(zhǔn)在幾個(gè)方面存在局限性:(a) 它們可能無(wú)法推廣到您的特定用例,以及 (b) 它們僅測(cè)試極小部分可能的社會(huì)偏見(jiàn)。

這些測(cè)試是初步的,我們建議針對(duì)您的特定用例運(yùn)行測(cè)試。這些結(jié)果應(yīng)被視為該現(xiàn)象存在的證據(jù),而不是對(duì)您的用例的明確描述。請(qǐng)參閱我們的使用政策以獲取更多詳細(xì)信息和指導(dǎo)。

如果您有任何問(wèn)題,請(qǐng)通過(guò)聊天聯(lián)系我們的支持團(tuán)隊(duì);我們很樂(lè)意就此提供建議。

對(duì)最近發(fā)生的事件視而不見(jiàn)

局限性:模型缺乏對(duì) 2020 年 8 月之后發(fā)生的事件的了解。

我們的模型在包含 8/2020 之前真實(shí)世界事件的一些信息的數(shù)據(jù)集上進(jìn)行訓(xùn)練。如果你依賴(lài)于代表最近事件的模型,那么它們可能表現(xiàn)不佳。

常見(jiàn)問(wèn)題

在嵌入字符串之前,如何知道它有多少個(gè)標(biāo)記?

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

對(duì)于像 text-embedding-ada-002 這樣的第二代嵌入模型,使用 cl100k_base 編碼。

更多詳細(xì)信息和示例代碼在 OpenAI Cookbook 指南中如何使用 tiktoken 計(jì)算令牌。

如何快速檢索 K 個(gè)最近的嵌入向量?

為了快速搜索多個(gè)矢量,我們建議使用矢量數(shù)據(jù)庫(kù)。您可以在 GitHub 上的 Cookbook 中找到使用矢量數(shù)據(jù)庫(kù)和 OpenAI API 的示例。

矢量數(shù)據(jù)庫(kù)選項(xiàng)包括:

  • Pinecone, 完全托管的矢量數(shù)據(jù)庫(kù)
  • Weaviate, 開(kāi)源矢量搜索引擎
  • Redis 作為矢量數(shù)據(jù)庫(kù)
  • Qdrant, 矢量搜索引擎
  • Milvus, 為可擴(kuò)展的相似性搜索而構(gòu)建的矢量數(shù)據(jù)庫(kù)

我應(yīng)該使用哪個(gè) distance 函數(shù)?

我們推薦余弦相似度。distance 函數(shù)的選擇通常無(wú)關(guān)緊要。

OpenAI 嵌入被歸一化為長(zhǎng)度 1,這意味著:

  • 僅使用點(diǎn)積可以稍微更快地計(jì)算余弦相似度

  • 余弦相似度和歐幾里德距離將導(dǎo)致相同的排名

我可以在線(xiàn)共享我的嵌入嗎?

客戶(hù)擁有我們模型的輸入和輸出,包括嵌入的情況。您有責(zé)任確保您輸入到我們 API 的內(nèi)容不違反任何適用法律或我們的使用條款


以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)