本系列我們主要關(guān)注以下兩個(gè)模型:

調(diào)用OpenAI API

API Key

在開(kāi)始使用 OpenAI API之前,首先需要前往 Azure 或 OpenAI 官網(wǎng)申請(qǐng) API 密鑰(不同的服務(wù)提供商申請(qǐng)流程略有不同)。但是由于&*%@的原因……,總之這個(gè)過(guò)程沒(méi)有統(tǒng)一完備的解法和攻略,需要大家各顯神通。

為了確保API密鑰的安全性,我們首先應(yīng)當(dāng)學(xué)會(huì)將其儲(chǔ)存在環(huán)境變量中,而不是直接寫入源代碼。將API密鑰直接硬編碼在代碼中是非常不安全的做法,會(huì)增加密鑰泄露的風(fēng)險(xiǎn)。

右鍵點(diǎn)擊”此電腦”,選擇”屬性”。在彈出窗口中,點(diǎn)擊”高級(jí)系統(tǒng)設(shè)置”。接著,在”系統(tǒng)屬性”對(duì)話框中,依次點(diǎn)擊”高級(jí)”→”環(huán)境變量”。在這里,我們可以為系統(tǒng)或當(dāng)前用戶新建”OPENAI_API_KEY”的環(huán)境變量,并將OpenAI API密鑰字符串作為變量值進(jìn)行存儲(chǔ)。

安裝 OpenAI Python 庫(kù)

OpenAI 提供了一個(gè)Python庫(kù)(https://github.com/openai/openai-python)。安裝之前,請(qǐng)確保你的 Python 版本是 3.7.1 或更高版本。

pip install openai

調(diào)用OpenAI’s (Python) API

下面我將以?GPT-3.5-turbo?模型為例,展示調(diào)用API的代碼。需要注意,不同的服務(wù)提供商(Azure和OpenAI)調(diào)用API的方式略有不同,下文會(huì)分別講解。調(diào)用OpenAI API的計(jì)費(fèi)取決于調(diào)用的模型類型以及消耗的Token數(shù)量,一般按照每百萬(wàn)或每千個(gè)Tokens進(jìn)行結(jié)算。作為參考,根據(jù)OpenAI官方文檔:對(duì)于英文文本,1 個(gè)Token大約為 4 個(gè)字符或 0.75 個(gè)單詞。

之前我們已經(jīng)將API KEY儲(chǔ)存在環(huán)境變量中,而dotenv是一個(gè)用于加載環(huán)境變量的Python庫(kù)。利用下面的代碼,我們從環(huán)境變量中獲取OpenAI API密鑰,并將其設(shè)置為全局變量,以便在后續(xù)的OpenAI API調(diào)用中安全使用。

import openai
import os

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

openai.api_key = os.getenv('OPENAI_API_KEY')

接下來(lái),我們定義一個(gè)函數(shù)get_completion_openai。

它有兩個(gè)參數(shù):prompt表示輸入文本,model表示要使用的模型,默認(rèn)為gpt-3.5-turbo。

import os
import openai
import json

def get_completion_openai(prompt, model="gpt-3.5-turbo"):
openai.api_key = os.getenv('OPENAI_API_KEY')

messages = [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": prompt
}
]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0
)
return response.choices[0].message['content']

在這段代碼中,messages 列表中的每個(gè)字典代表一個(gè)對(duì)話消息,其中包含兩個(gè)鍵值對(duì):

“system” 角色

“user” 角色

“assistant” 角色

response = openai.ChatCompletion.create(……)這一行使用 OpenAI API向指定的 GPT 模型發(fā)送請(qǐng)求。

openai.ChatCompletion.create(……)上述示例代碼中沒(méi)有列出,但也同樣常用的其他參數(shù)包括:

max_tokens

n

調(diào)用Azure OpenAI API

Azure 與 OpenAI 的調(diào)用 API 的方式略有不同。我們首先需要?jiǎng)?chuàng)建一個(gè) Azure 訂閱(Subscription),以及相應(yīng)的資源組(Resource Group)和部署(Deployments),三者缺一不可。在 Azure 門戶中創(chuàng)建上述資源后,你將獲得一個(gè)終結(jié)點(diǎn) URL(Endpoint) 和一個(gè)訪問(wèn)密鑰(API Key),這兩者是調(diào)用API的必備信息。

注意:Deployments雖然可以自定義,但最好不要亂起名,用什么模型起什么名,比如用gpt-35-turbo,就取gpt-35-turbo的部署名。不然部署的模型多了容易亂成一鍋粥。

在獲取了Endpoint和API Key之后,我們用以下代碼進(jìn)行調(diào)用。

首先,讓我們看一下Azure官方提供的使用Azure OpenAI API的示例代碼。類似地,我們需要在環(huán)境變量中設(shè)置并獲取”AZURE_OPENAI_API_KEY”和”AZURE_OPENAI_ENDPOINT”。

import os
import openai
openai.api_type = "azure"
openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")
openai.api_key = os.getenv("AZURE_OPENAI_API_KEY")
openai.api_version = "2023-05-15"

response = openai.ChatCompletion.create(
engine="gpt-35-turbo", # engine = "deployment_name".
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},
{"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},
{"role": "user", "content": "Do other Azure AI services support this too?"}
]
)

print(response)
print(response['choices'][0]['message']['content'])

我們?cè)贏zure官方提供的代碼的基礎(chǔ)上,進(jìn)行修改,封裝成一個(gè)函數(shù):

import os
import openai

def get_completion_azure(prompt, model="gpt-35-turbo"):
openai.api_key = os.getenv("AZURE_OPENAI_API_KEY")
openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")
openai.api_type = "azure"
openai.api_version = "2023-05-15"

response = openai.ChatCompletion.create(
engine = model,
temperature = 0,
messages = [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": prompt
}
]
)
return response['choices'][0]['message']['content']

注意,OpenAI對(duì)于gpt-3.5-turbo的引用是gpt-3.5-turbo,而Azure是gpt-35-turbo,這個(gè)地方比較細(xì)節(jié),容易出錯(cuò)……

在設(shè)置好上面的get_completion_openaiget_completion_azure函數(shù)后,我們就可以在各種場(chǎng)景下靈活應(yīng)用OpenAI API 。

以下是一個(gè)基礎(chǔ)的API調(diào)用示例:

get_completion_openai("TextMatters是一個(gè)專注于基于文本分析的金融會(huì)計(jì)領(lǐng)域?qū)嵶C研究的微信公眾號(hào),請(qǐng)你為它撰寫一個(gè)30字以內(nèi)的簡(jiǎn)短介紹。")

以上API調(diào)用代碼會(huì)返回以下結(jié)果:

'TextMatters是專注于金融會(huì)計(jì)領(lǐng)域?qū)嵶C研究的微信公眾號(hào),致力于通過(guò)文本分析揭示財(cái)務(wù)報(bào)告中的信息和趨勢(shì),為投資者和研究者提供有益的見(jiàn)解和分析。關(guān)注TextMatters,了解最新的研究成果和行業(yè)動(dòng)態(tài)。'

Prompt Engineering

Prompt最初是為下游任務(wù)而設(shè)計(jì)的一種任務(wù)專屬的輸入形式或模板,在ChatGPT引發(fā)大語(yǔ)言模型新時(shí)代后,Prompt成為與大模型交互輸入的代名詞。因此,我們通常將提供給大模型的輸入稱為Prompt。

Prompt Engineering是指設(shè)計(jì)和調(diào)整Prompt的過(guò)程。正如吳恩達(dá)本人所強(qiáng)調(diào),通過(guò)正確地使用和優(yōu)化提示詞,我們才能夠充分發(fā)揮LLM的潛力,指導(dǎo)它按照我們的意圖生成所需輸出。

Prompt 實(shí)踐指南

上一章講到的調(diào)用API的函數(shù),我們需要在本章進(jìn)行復(fù)用。因此我們?cè)?a href="http://cnzze.cn/wiki/python-language/">Python中運(yùn)行以下代碼,定義函數(shù)get_completion

def get_completion(prompt, model="gpt-3.5-turbo"):
openai.api_key = os.getenv('OPENAI_API_KEY')

messages = [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": prompt
}
]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0
)
return response.choices[0].message['content']

吳恩達(dá)和 Iza Fulford給出了設(shè)定Prompt的兩條基礎(chǔ)原則。它們分別是:

原則1:Prompt需要清晰具體

在撰寫指令時(shí),明確并具體的Prompt是十分重要的。在具體的應(yīng)用過(guò)程中,原則1可以體現(xiàn)為以下幾種Prompt實(shí)踐。

(1)使用分隔符清楚地表示輸入的不同部分

我們可以使用分隔符清晰地劃分輸入的不同部分,這有助于模型準(zhǔn)確理解輸入的結(jié)構(gòu)。分隔符可以是各種形式的,比如雙引號(hào)""、三引號(hào)''',尖括號(hào)<>、標(biāo)簽<tag></tag>或者冒號(hào):

示例代碼:

text = f"""
您應(yīng)該通過(guò)提供盡可能清晰和具體的指令來(lái)表達(dá)您希望模型執(zhí)行的任務(wù)。這將引導(dǎo)模型朝著期望的輸出方向發(fā)展,并減少接收到無(wú)關(guān)或不正確響應(yīng)的幾率。不要混淆寫清晰提示與寫簡(jiǎn)短提示。在許多情況下,更長(zhǎng)的提示為模型提供了更多的清晰度和上下文,這可能導(dǎo)致更詳細(xì)和相關(guān)的輸出。
"""

prompt = f"""
把用三個(gè)反引號(hào)括起來(lái)的文本總結(jié)成一句話。
``{text}`` """ # 調(diào)用函數(shù) response = get_completion(prompt) print(response)

以上代碼的輸出結(jié)果為:

提供清晰和具體的指令可以引導(dǎo)模型朝著期望的輸出方向發(fā)展,減少接收到無(wú)關(guān)或不正確響應(yīng)的幾率。

(2)設(shè)定結(jié)構(gòu)化的輸出

當(dāng)我們調(diào)用API與模型進(jìn)行交互時(shí),為了獲得更有用的結(jié)果,有時(shí)候可以要求它提供結(jié)構(gòu)化輸出,例如JSON或HTML格式的數(shù)據(jù)。

示例代碼:

prompt = f"""
生成三本虛構(gòu)中文書(shū)籍標(biāo)題,包括它們的作者和流派。
以JSON格式提供,包含以下鍵:
book_id,title,author,genre。
"""
# 調(diào)用函數(shù)
response = get_completion(prompt)
print(response)

以上代碼的輸出結(jié)果為:

```json
[
{
"book_id": 1,
"title": "夢(mèng)境之城",
"author": "張小明",
"genre": "奇幻"
},
{
"book_id": 2,
"title": "時(shí)間之門",
"author": "王小紅",
"genre": "科幻"
},
{
"book_id": 3,
"title": "幽靈之謎",
"author": "李大山",
"genre": "懸疑"
}
]
```

(3)要求模型檢查是否滿足條件

在處理任務(wù)時(shí),我們經(jīng)常會(huì)面對(duì)各種假設(shè)或條件,有些條件可能并非總是被滿足。這種方法可以幫助我們?cè)陂_(kāi)始任務(wù)之前排除一些可能導(dǎo)致錯(cuò)誤結(jié)果的情況。如果發(fā)現(xiàn)條件不滿足,模型會(huì)及時(shí)指出并停止執(zhí)行后續(xù)的完整流程。

示例代碼:

text = f"""
今天陽(yáng)光明媚,鳥(niǎo)兒在歡唱。今天是去公園散步的好日子?;▋菏㈤_(kāi)著,樹(shù)木在微風(fēng)中輕輕搖曳。人們出門在外,享受著美好的天氣。
"""

prompt = f"""
您將獲得由三個(gè)引號(hào)界定的文本。如果其中包含一系列指令,請(qǐng)按以下格式重新編寫這些指令:

步驟1 - ...
步驟2 - …

步驟N - …

如果文本中不包含一系列指令,則簡(jiǎn)單寫為“未提供步驟”。

'''{text}'''
"""
# 調(diào)用函數(shù)
response = get_completion(prompt)
print(response)

以上代碼的輸出結(jié)果為:

未提供步驟。

(4)Few-shot prompting

Few-shot prompting 的核心思想是提供一個(gè)簡(jiǎn)短的提示或示例,然后讓模型根據(jù)這些提示進(jìn)行推理和生成,指導(dǎo)它按照我們的意圖生成所需輸出。

示例代碼:

text = f"""
龍騰虎躍鬧春意
"""
prompt = f"""
您的任務(wù)是以對(duì)聯(lián)的格式回答問(wèn)題。
對(duì)聯(lián)是中國(guó)傳統(tǒng)文化中的一種形式,通常由兩句相對(duì)、呼應(yīng)或?qū)φ痰脑?shī)句構(gòu)成。這兩句詩(shī)句往往在意義、韻律或結(jié)構(gòu)上相呼應(yīng),構(gòu)成了一種文學(xué)藝術(shù)形式。
例如:
“春風(fēng)吹綠柳,夏雨潤(rùn)花枝?!?br /> 下面三引號(hào)中的內(nèi)容是你需要回答的問(wèn)題:
'''{text}'''
"""
# 調(diào)用函數(shù)
response = get_completion(prompt)
print(response)

以上代碼的輸出結(jié)果為:

鳥(niǎo)語(yǔ)花香迎新春

原則2:給模型充分“思考”的時(shí)間

我們可以在Prompt中先要求語(yǔ)言模型自己嘗試解決這個(gè)問(wèn)題,思考出自己的解法,然后再與提供的解答進(jìn)行對(duì)比,判斷正確性。在具體的應(yīng)用過(guò)程中,原則2可以體現(xiàn)為以下幾種Prompt實(shí)踐。

(1)指定完成任務(wù)所需的步驟

在Prompt中明確指定語(yǔ)言模型需要執(zhí)行的操作步驟,以便引導(dǎo)模型有條不紊地進(jìn)行推理和生成。

示例代碼:

text = f"""
畢竟西湖六月中,風(fēng)光不與四時(shí)同。\
接天蓮葉無(wú)窮碧,映日荷花別樣紅。
"""
prompt = f"""
執(zhí)行以下操作:
1-請(qǐng)描述下面用三個(gè)反引號(hào)括起來(lái)的古詩(shī)文本的意思。
2-找出其中的提到的顏色。
3-找出顏色對(duì)應(yīng)的物體。
4-輸出一個(gè) JSON 對(duì)象,其中包含以下鍵:顏色,物體。
請(qǐng)用換行符分隔您的答案。
Text:
``{text}`` """ # 調(diào)用函數(shù) response = get_completion(prompt) print(response)

輸出結(jié)果為:

1- 這首古詩(shī)描述了西湖六月的景色,與其他季節(jié)不同。蓮葉碧綠無(wú)窮,荷花在陽(yáng)光下映出別樣的紅色。
2- 綠色、紅色
3- 蓮葉、荷花
4-
```json
{
"顏色": ["綠色", "紅色"],
"物體": ["蓮葉", "荷花"]
}
```

(2)在指導(dǎo)模型得出結(jié)論之前讓它自行思考問(wèn)題

當(dāng)我們要求語(yǔ)言模型判斷數(shù)學(xué)問(wèn)題的解答是否正確,但僅僅提供問(wèn)題和解答是不夠的,過(guò)于匆忙可能導(dǎo)致錯(cuò)誤的判斷。我們應(yīng)該在Prompt中鼓勵(lì)模型首先嘗試自己解決問(wèn)題,思考出自己的解決方案。這種方式能夠讓模型有足夠的時(shí)間去理解問(wèn)題,從而提高解決問(wèn)題的準(zhǔn)確性。

迭代優(yōu)化 Prompt

我們接下來(lái)展示一個(gè)初始Prompt被不斷迭代優(yōu)化的過(guò)程,包括:添加長(zhǎng)度限制;提取信息并結(jié)構(gòu)化輸出。

text = f"""
Author: Chen Yi-Chun,Hung Mingyi,Wang Yongxiang \
Journal: Journal of Accounting and Economics \
Year: 2018 \
Abstract: We examine how mandatory disclosure of corporate social responsibility (CSR) \
impacts firm performance and social externalities. Our analysis exploits China’s 2008 mandate \
requiring firms to disclose CSR activities, using a difference-in-differences design. \
Although the mandate does not require firms to spend on CSR, we find that mandatory CSR \
reporting firms experience a decrease in profitability subsequent \
to the mandate. In addition, the cities most impacted by the disclosure mandate \
experience a decrease in their industrial wastewater and SO2 emission levels. \
These findings suggest that mandatory CSR disclosure alters firm behavior and \
generates positive externalities at the expense of shareholders.
"""

prompt = f"""
請(qǐng)你用中文概括下面論文摘要中的核心結(jié)論。
``{text}`` """ response = get_completion(prompt) print(response)

輸出結(jié)果為:

這段論文摘要的核心結(jié)論是:強(qiáng)制性披露企業(yè)社會(huì)責(zé)任(CSR)對(duì)公司績(jī)效和社會(huì)外部性產(chǎn)生影響。研究發(fā)現(xiàn),雖然強(qiáng)制性CSR披露并不要求公司在CSR方面進(jìn)行支出,但披露CSR活動(dòng)的公司在法規(guī)實(shí)施后經(jīng)歷了盈利能力下降。此外,受披露要求影響最大的城市在工業(yè)廢水和二氧化硫排放水平上也出現(xiàn)下降。這些發(fā)現(xiàn)表明,強(qiáng)制性CSR披露改變了公司行為,并在股東的代價(jià)下產(chǎn)生了積極的外部性影響。

可以看到,這個(gè)回復(fù)還是太長(zhǎng)了,沒(méi)有起到概括的作用。因此我們可以在Prompt中添加輸出長(zhǎng)度限制。

prompt = f"""
請(qǐng)你用中文概括下面論文摘要中的核心結(jié)論。長(zhǎng)度限制到20字以內(nèi)。
``{text}`` """ response = get_completion(prompt) print(response)

輸出結(jié)果為:

強(qiáng)制CSR披露影響企業(yè)績(jī)效和社會(huì)外部性,減少盈利,改善環(huán)境。

最后,我們進(jìn)一步優(yōu)化prompt,讓它提取我們感興趣的特定信息并生成結(jié)構(gòu)化輸出。

prompt = f"""
針對(duì)三個(gè)反引號(hào)括起來(lái)的文本,請(qǐng)你提取下列信息并組織成Json格式輸出:
作者,期刊,年份,核心結(jié)論(20字以內(nèi))
``{text}`` """ response = get_completion(prompt) print(response)

輸出結(jié)果為:

```json
{
"Author": "Chen Yi-Chun, Hung Mingyi, Wang Yongxiang",
"Journal": "Journal of Accounting and Economics",
"Year": "2018",
"Core Conclusion": "Mandatory CSR disclosure affects firm performance and social externalities."
}
```

模型局限性:幻覺(jué) (Hallucination)

當(dāng)我們讓語(yǔ)言模型描述一個(gè)實(shí)際上不存在的產(chǎn)品或概念時(shí),它可能會(huì)憑空捏造出貌似合理的細(xì)節(jié),自行”補(bǔ)全”這個(gè)虛構(gòu)的事物,一本正經(jīng)地向我們提供這些編造的”知識(shí)”。這種現(xiàn)象被稱為”幻覺(jué)”(Hallucination),是語(yǔ)言模型的一大局限性和缺陷。

雖然我們?cè)谇懊娴膬?nèi)容中學(xué)習(xí)了如何設(shè)定準(zhǔn)確合適的Prompt來(lái)指導(dǎo)模型的輸出方向,但我們?nèi)匀恍枰杌糜X(jué)現(xiàn)象可能帶來(lái)的問(wèn)題和風(fēng)險(xiǎn)。

text = f"""
用50字向我描述小米公司最新開(kāi)發(fā)的Mate60手機(jī)的特點(diǎn)。
"""
prompt = f"""
請(qǐng)你用專業(yè)的語(yǔ)言回答下列三個(gè)反引號(hào)括起來(lái)的問(wèn)題
Text:
``{text}`` """ # 調(diào)用函數(shù) response = get_completion(prompt) print("prompt") print(response)

輸出結(jié)果為:

小米公司最新開(kāi)發(fā)的Mate60手機(jī)具有高性能處理器、創(chuàng)新設(shè)計(jì)、多攝像頭系統(tǒng)、大容量電池和快速充電技術(shù)等特點(diǎn)。

讀取數(shù)據(jù)集

我們先讀入數(shù)據(jù)集,再在DataFrame中選取名為'Text'這一列,即包含產(chǎn)品評(píng)論文本內(nèi)容的那一列。

import pandas as pd

amazon = pd.read_excel('./amazon_review.xlsx')
amazon_review = amazon['Text'].tolist()
# 取前5條數(shù)據(jù)
amazon_review = amazon_review[:5]

定義OpenAI API函數(shù)

我們定義函數(shù)get_setiment,它接受兩個(gè)參數(shù):

  1. amazon_review是一個(gè)字符串,表示待分析的產(chǎn)品評(píng)論文本
  2. model是一個(gè)可選參數(shù),默認(rèn)值為"gpt-3.5-turbo"代表使用OpenAI的gpt-3.5-turbo模型

在函數(shù)內(nèi)部,我們?cè)O(shè)計(jì)了一個(gè)prompt,明確指示模型對(duì)給定的產(chǎn)品評(píng)論進(jìn)行情感分類,并僅輸出”positive”或”negative”兩個(gè)詞匯作為結(jié)果,確保輸出的準(zhǔn)確性。

import openai
import os

# 設(shè)定情感分類相關(guān)的OpenAI API調(diào)用函數(shù)
def get_setiment(amazon_review, model="gpt-3.5-turbo"):
openai.api_key = os.getenv('OPENAI_API_KEY')
prompt = f"""
What is the sentiment of the following product review,
which is delimited with triple backticks
Give your answer as a single word, either "positive" or "negative".
Review text: ``{amazon_review}`` """ messages = [ { "role": "user", "content": prompt } ] response = openai.ChatCompletion.create( model=model, messages=messages, temperature=0 ) return response.choices[0].message['content'] #運(yùn)行函數(shù) setiment = {} for text in amazon_review: setiment[text] = get_setiment(text) sentiment_df = pd.DataFrame(setiment.items(), columns=['Review', 'Sentiment'])

輸出結(jié)果整理如下。從分類結(jié)果來(lái)看,大型語(yǔ)言模型展現(xiàn)出了非常優(yōu)秀的性能,模型能夠精準(zhǔn)地區(qū)分出正面(positive)和負(fù)面(negative)兩種情感。

識(shí)別情感類型

在這一小節(jié),我們將嘗試設(shè)定一個(gè)Prompt來(lái)分析評(píng)論本文的情感類型。我們期望模型可以識(shí)別出評(píng)論作者表達(dá)的情感,并將其整理成一個(gè)不超過(guò)五個(gè)項(xiàng)目的列表。

prompt = f"""
Identify a list of emotions that the writer of the \
following review is expressing. Include no more than \
five items in the list. Format your answer as a list of \
lower-case words separated by commas.

Review text: '''{amazon_review[0]}'''
"""
response = get_completion(prompt)
print(response)

輸出結(jié)果如下:

satisfied, pleased, impressed, grateful, content

識(shí)別憤怒

prompt = f"""
Is the writer of the following review expressing anger?\
The review is delimited with triple backticks. \
Give your answer as either yes or no.

Review text: '''{amazon_review[0]}'''"""
response = get_completion(prompt)
print(response)

輸出結(jié)果如下:

No

文本嵌入(Text Embeddings)

文本嵌入(Text embeddings)是一種將文本轉(zhuǎn)換為向量表示(Vector Representation)的技術(shù)(更加通俗地說(shuō),嵌入就是將人類可讀的文字變成模型可讀的數(shù)字)。其核心思想是捕捉單詞或短語(yǔ)之間的語(yǔ)義,并將其表示為向量空間中的距離。

換句話說(shuō),語(yǔ)義上相似的單詞在嵌入空間中會(huì)有更接近的向量表示,而語(yǔ)義上不相關(guān)的單詞則會(huì)有較遠(yuǎn)的向量表示。

常見(jiàn)的嵌入模型包括Word2Vec、GloVe、BERT等。

OpenAI 嵌入模型

*下文提到的內(nèi)容具有一定時(shí)效性,建議定期跟蹤OpenAI API官方文檔,更新信息。

2024 年年初,OpenAI API發(fā)布了全新的V3嵌入模型?text-embedding-3-small?和?text-embedding-3-large

模型比較

截至目前(2024年3月),OpenAI 提供的嵌入模型主要包括:

text-embedding-ada-002

text-embedding-3-small

text-embedding-3-large

縮短嵌入維度

考慮到使用較大的嵌入會(huì)消耗更多的計(jì)算、內(nèi)存和存儲(chǔ),OpenAI 現(xiàn)在允許用戶通過(guò)API 傳遞維度參數(shù)來(lái)縮短嵌入維度,且不會(huì)使嵌入失去其代表概念的屬性。根據(jù)下圖官方測(cè)試中提供的信息,兩個(gè)V3嵌入模型即使在縮短嵌入維度后的表現(xiàn)仍然高于ada-002。

因此綜上,如果只是用于金融/會(huì)計(jì)學(xué)術(shù)領(lǐng)域的文本研究,我強(qiáng)烈建議無(wú)條件使用text-embedding-3-small模型。

如何調(diào)用API獲得嵌入

下列代碼中,我們定義了一個(gè)函數(shù)?get_embedding_v1(text_to_embed),該函數(shù)接受一個(gè)字符串參數(shù)?text_to_embed,該字符串是要嵌入的文本。函數(shù)內(nèi)我們調(diào)用了?openai.Embedding.create()?方法,發(fā)起一個(gè) API 請(qǐng)求。

import json
import openai
import os
import time

def get_embedding(text_to_embed):
openai.api_key = os.getenv('OPENAI_API_KEY')

response = openai.Embedding.create(
model= "text-embedding-3-small",
input=[text_to_embed]
)

try:
embedding = response["data"][0]["embedding"]
except:
embedding = None
time.sleep(2)
print("error")
pass

if embedding:
with open("./mydata_embedding.json", "a+") as f:
json.dump({text_to_embed: embedding}, f)
f.write("\n")
return embedding

上述代碼的響應(yīng)是一個(gè) JSON 對(duì)象,我們用embedding = response["data"][0]["embedding"]提取其中的嵌入,它是一個(gè)長(zhǎng)度(維度)為 1536 維的向量。我們將文本及其對(duì)應(yīng)的嵌入向量寫入一個(gè)名為 mydata_embedding.json 的 JSON 文件中。

我們可以在一個(gè)簡(jiǎn)單文本上,運(yùn)行上述函數(shù):

get_embedding("Harry potter, the boy who lived.")

得到嵌入返回的向量:

[-0.029458941891789436,
0.04615234211087227,
-0.0445975624024868,
0.033100392669439316,
0.015087478794157505,
-0.061004556715488434,
-0.005027454812079668,
...
-0.01764467917382717,
-0.02884521335363388,
-0.021930545568466187,
-0.011804034002125263,
...]

我們看一下這個(gè)向量的維度:

print(len(get_embedding("Harry potter, the boy who lived.")))

會(huì)得到嵌入維度:

1536

通常,使用更大的嵌入向量會(huì)消耗更多的計(jì)算、內(nèi)存和存儲(chǔ)資源。上文提到,OpenAI 現(xiàn)在允許在兩個(gè) V3 嵌入模型上通過(guò) API 傳遞維度參數(shù)來(lái)縮短嵌入維度(ada-002不支持維度調(diào)整)。

具體實(shí)現(xiàn)代碼如下,我們只需在 response 中添加對(duì)維度參數(shù)的要求:

response = openai.Embedding.create(
model= "text-embedding-3-small",
input= [text_to_embed],
dimensions = 512
)

此時(shí)維度從1536維下降至512維:

print(len(get_embedding("Harry potter, the boy who lived.")))

返回值:

512

文本相似度

文本嵌入為機(jī)器學(xué)習(xí)模型和其他算法執(zhí)行各種下游任務(wù)(如聚類或檢索)提供了基礎(chǔ)。包括但不限于:

本節(jié)進(jìn)一步展示一個(gè)簡(jiǎn)化后的下游任務(wù):計(jì)算文本相似度。通過(guò)將文本轉(zhuǎn)換成嵌入向量,我們可以利用向量空間中的距離或相似度度量來(lái)比較它們之間的相似性。

作為一個(gè)示例,我同時(shí)獲取了哈利波特和指環(huán)王主角們的姓名文本嵌入。通過(guò)比較這些嵌入向量之間的距離或相似度,我們可以探索這些主角之間在文本語(yǔ)境中的相似性或相關(guān)性。

# 哈利波特人物
harry_potter = get_embedding("Harry potter")
ron_weasley = get_embedding("Ron Weasley")
hermione_granger = get_embedding("Hermione Granger")

# 指環(huán)王人物
gandalf = get_embedding("Gandalf the Grey")
frodo = get_embedding("Frodo Baggins")
legolas = get_embedding("Legolas")

我們使用scipy庫(kù)中的distance.cosine函數(shù)來(lái)計(jì)算哈利波特與其他人物之間的余弦距離。

# 計(jì)算哈利到各個(gè)人的距離

from scipy.spatial import distance

print(distance.cosine(harry_potter, ron_weasley))
print(distance.cosine(harry_potter, hermione_granger))
print(distance.cosine(harry_potter, gandalf))
print(distance.cosine(harry_potter, frodo))
print(distance.cosine(harry_potter, legolas))

上述代碼輸出結(jié)果如下。我們可以看出,同一故事的角色之間的余弦距離(= 1-余弦相似度)更小,這表明這些角色在語(yǔ)義上更為相似或者相關(guān)。

0.4510517158795876
0.46182439707308476
0.613488967442906
0.6424822454338903
0.6501364169064245

為了更清晰地展示嵌入的空間距離,我們利用主成分分析將文本的高維向量表示降維至二維空間,并將其呈現(xiàn)在二維圖表中。結(jié)果顯示,同一系列或同一故事中的角色之間的文本嵌入更相似,在圖表中呈現(xiàn)為更接近的空間距離。

本文章轉(zhuǎn)載微信公眾號(hào)@TextMatters

上一篇:

十行代碼就能搞定深度學(xué)習(xí)?飛槳框架高層API,一起輕松玩轉(zhuǎn)AI

下一篇:

從Flask切到FastAPI后,起飛了!
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)