譯者 | 朱先忠
審校 | 重樓
出品 | 51CTO技術棧(微信號:blog51cto)
本文對OpenAI的多個嵌入模型與多家開源的多語言嵌入模型進行了綜合比較,幫助你最終選擇最適合自己的大數(shù)據(jù)開發(fā)模型。
1.引言
OpenAI最近發(fā)布了他們的新一代嵌入模型,稱為嵌入v3,他們將其描述為性能最高的嵌入模型,而且具有更高的多語言性能。這些模型分為兩類:一類較小,稱為text-embedding-3-mall;另一類較大,功能也更強大,稱為text-embedding-3-large。
關于這些模型的設計和訓練方式,披露的信息很少。作為他們之前發(fā)布的嵌入模型(2022年12月,通過模型類ada-002的方式呈現(xiàn)),OpenAI公司再次選擇了一種閉源市場策略,即這些模型只能通過付費的API方式進行訪問。
但是,這些模型的性能是否如此優(yōu)秀以至于值得人們以付費方式來使用呢?
這篇文章的目的是將這些新模型的性能與開源模型的性能進行實證比較。我們將使用數(shù)據(jù)檢索工作流進行比較;在該工作流中,必須在給定用戶查詢的情況下找到語料庫中最相關的文檔。
我們的語料庫將是《歐盟人工智能法案》(https://artificialintelligenceact.eu/),該法案目前正處于最后的驗證階段。這個語料庫的一個有趣的特點是,除了是世界上第一個人工智能的法律框架外,它還有24種語言版本。這使得可以比較不同語言族的數(shù)據(jù)檢索準確性。
本文將采取以下兩個主要步驟:
- 從多語言文本語料庫生成自定義合成問答數(shù)據(jù)集;
- 在這個自定義數(shù)據(jù)集上比較OpenAI和當今最先進的開源嵌入模型的準確性。
在Github存儲庫(https://github.com/Yannael/multilingual-embeddings)中提供了重現(xiàn)本文中呈現(xiàn)的所有結果的代碼和相關數(shù)據(jù)。請注意,以《歐盟人工智能法案》為例,本文所遵循的方法可以適用于其他數(shù)據(jù)語料庫。
2.生成自定義問答數(shù)據(jù)集
讓我們首先從生成自定義數(shù)據(jù)的問答數(shù)據(jù)集(Q/a)開始,該數(shù)據(jù)集將用于評估不同嵌入模型的性能。生成自定義問答數(shù)據(jù)集的好處有兩個。
首先,它通過確保數(shù)據(jù)集沒有成為嵌入模型訓練的一部分來避免偏差,這可能發(fā)生在參考基準,如MTEB:https://huggingface.co/spaces/mteb/leaderboard)上。
其次,它允許根據(jù)特定的數(shù)據(jù)語料庫進行評估,例如在檢索增強應用程序(RAG)的情況下,這可能是相關的。
我們將遵循Llama Index在其文檔(https://blog.llamaindex.ai/fine-tuning-embeddings-for-rag-with-synthetic-data-e534409a3971)中建議的簡單流程。語料庫首先被分成一組組的塊。然后,對于每個塊,通過大型語言模型(LLM)生成一組合成問題,使得答案位于相應的塊中。該過程如下所示:
圖片
通過Llama Index方法為你的數(shù)據(jù)生成問答數(shù)據(jù)集
使用LLM的數(shù)據(jù)框架(如Llama Index)實現(xiàn)上述策略非常簡單。使用高級函數(shù)可以方便地加載語料庫和分割文本,如以下代碼所示:
from llama_index.readers.web import SimpleWebPageReader
from llama_index.core.node_parser import SentenceSplitter
language = "EN"
url_doc = "https://eur-lex.europa.eu/legal-content/"+language+"/TXT/HTML/?uri=CELEX:52021PC0206"
documents = SimpleWebPageReader(html_to_text=True).load_data([url_doc])
parser = SentenceSplitter(chunk_size=1000)
nodes = parser.get_nodes_from_documents(documents, show_progress=True)
在本例中,語料庫是英語版的《歐盟人工智能法案》,使用其官方URL(https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A52021PC0206)可直接從網絡上獲取。
我們使用2021年4月的草案版本,因為最終版本尚未適用于所有歐洲語言。在這個版本中,URL中的英語可以替換為其他23種歐盟官方語言中的任何一種,以檢索不同語言的文本(保加利亞語為BG,西班牙語為ES,捷克語為CS,等等)。
圖片
下載24種歐盟官方語言的《歐盟人工智能法案》鏈接(來自歐盟官方網站)
我們使用PensioneSplitter對象將文檔拆分為1000個標記的塊。對于英語來說,這會產生大約100個塊。
然后,將每個塊作為上下文提供給以下提示(Llama索引庫中建議的默認提示:
https://github.com/run-llama/llama_index/blob/c058f2531ea86ee74822cb1421ceaeee7098a99f/llama_index/finetuning/embeddings/common.py#L51):
prompts={}
prompts["EN"] = """\
Context information is below.
---------------------
{context_str}
---------------------
Given the context information and not prior knowledge, generate only questions based on the below query.
You are a Teacher/ Professor. Your task is to setup {num_questions_per_chunk} questions for an upcoming quiz/examination.
The questions should be diverse in nature across the document. Restrict the questions to the context information provided."
"""
提示旨在生成有關文檔塊的問題,就好像老師正在準備即將到來的測驗一樣。為每個區(qū)塊生成的問題數(shù)量作為參數(shù)“num_questions_per_chunk”傳遞,我們將其值設置為2。然后,可以通過調用Llama索引庫中的generate_qa_embedding_pairs來生成問題:
from llama_index.llms import OpenAI
from llama_index.legacy.finetuning import generate_qa_embedding_pairs
qa_dataset = generate_qa_embedding_pairs(
llm=OpenAI(model="gpt-3.5-turbo-0125",additional_kwargs={'seed':42}),
nodes=nodes,
qa_generate_prompt_tmpl = prompts[language],
num_questions_per_chunk=2
)
我們依靠OpenAI的GPT-3.5-turbo-0125模型來完成這項任務,根據(jù)OpenAI的說法,這是該系列的旗艦模型,支持16K大小的上下文窗口,并針對對話框進行了優(yōu)化(https://platform.openai.com/docs/models/gpt-3-5-turbo)。
生成的對象“qa_dataset”中包含問題和答案(組塊)對。作為生成問題的示例,以下是前兩個問題的結果(“answer(答案)”是第一塊文本):
1)What are the main objectives of the proposal for a Regulation laying down harmonised rules on artificial intelligence (Artificial Intelligence Act) according to the explanatory memorandum?
大致中文意思是:根據(jù)解釋性備忘錄,制定人工智能統(tǒng)一規(guī)則的法規(guī)(《人工智能法》)提案的主要目標是什么?
2)How does the proposal for a Regulation on artificial intelligence aim to address the risks associated with the use of AI while promoting the uptake of AI in the European Union, as outlined in the context information?
大致中文意思是:如上下文信息所述,人工智能條例的提案如何旨在解決與人工智能使用相關的風險,同時促進歐盟對人工智能的吸收?
語塊和問題的數(shù)量取決于語言,從英語的大約100個語塊和200個問題到匈牙利語的200個語塊或400個問題。
3.OpenAI嵌入模型的評估
我們的評估功能遵循Llama Index文檔,如下:
(https://docs.llamaindex.ai/en/stable/examples/finetuning/embeddings/finetune_embedding.html),
包括兩個主要步驟——
首先,所有答案(文檔塊)的嵌入都存儲在VectorStoreIndex中,以實現(xiàn)高效檢索。然后,評估函數(shù)在所有查詢上循環(huán),檢索前k個最相似的文檔,并根據(jù)MRR(平均倒數(shù)排名)評估檢索的準確性。
def evaluate(dataset, embed_model, insert_batch_size=1000, top_k=5):
# 從qa_dataset對象獲取語料庫、查詢和相關文檔
corpus = dataset.corpus
queries = dataset.queries
relevant_docs = dataset.relevant_docs
# 為語料庫中的每個文檔創(chuàng)建TextNode對象,并創(chuàng)建VectorStoreIndex以有效地存儲和檢索嵌入
nodes = [TextNode(id_=id_, text=text) for id_, text in corpus.items()]
index = VectorStoreIndex(
nodes, embed_model=embed_model, insert_batch_size=insert_batch_size
)
retriever = index.as_retriever(similarity_top_k=top_k)
#準備收集評估結果
eval_results = []
# 對數(shù)據(jù)集中的每個查詢進行迭代,以評估檢索性能
for query_id, query in tqdm(queries.items()):
# 檢索當前查詢的前_k個最相似的文檔,并提取檢索到的文檔的ID
retrieved_nodes = retriever.retrieve(query)
retrieved_ids = [node.node.node_id for node in retrieved_nodes]
#檢查所需文檔是否在檢索到的文檔中
expected_id = relevant_docs[query_id][0]
is_hit = expected_id in retrieved_ids # 假設每個查詢有1個相關文檔
# 計算平均倒數(shù)排名(MRR)并添加到結果集中
if is_hit:
rank = retrieved_ids.index(expected_id) + 1
mrr = 1 / rank
else:
mrr = 0
eval_results.append(mrr)
#返回所有查詢的平均MRR作為最終評估度量
return np.average(eval_results)
嵌入模型通過“embed_mode”參數(shù)傳遞給評估函數(shù)。對于OpenAI模型,該參數(shù)是用模型名稱和模型維度初始化的OpenAIEmbedding對象。
from llama_index.embeddings.openai import OpenAIEmbedding
embed_model = OpenAIEmbedding(model=model_spec['model_name'],
dimensinotallow=model_spec['dimensions'])
API參數(shù)dimensions可以縮短嵌入(即從序列的末尾移除一些數(shù)字),而不會丟失嵌入的概念表示屬性。例如,OpenAI在其公告中建議,在MTEB基準上,嵌入可以縮短到256的大小,同時仍然優(yōu)于1536大小的未縮短的text-embedding-ada-002嵌入。
我們在四個不同的OpenAI嵌入模型上運行了評估函數(shù):
ltext-embedding-3-large的兩個版本:一個具有盡可能低的維度(256),
另一個具有最高的維度(3072)。這些被稱為“OAI-large256”和“OAI-Large3072”。
lOAI-small:即text-embedding-3-small嵌入模型,尺寸為1536。
lOAI-ada-002:傳統(tǒng)的text-embedding-ada-002模型,尺寸為1536。
每個模型在四種不同的語言上進行了評估:英語(EN)、法語(FR)、捷克語(CS)和匈牙利語(HU),分別涵蓋了日耳曼語、羅曼斯語、斯拉夫語和烏拉爾語。
embeddings_model_spec = {
}
embeddings_model_spec['OAI-Large-256']={'model_name':'text-embedding-3-large','dimensions':256}
embeddings_model_spec['OAI-Large-3072']={'model_name':'text-embedding-3-large','dimensions':3072}
embeddings_model_spec['OAI-Small']={'model_name':'text-embedding-3-small','dimensions':1536}
embeddings_model_spec['OAI-ada-002']={'model_name':'text-embedding-ada-002','dimensions':None}
results = []
languages = ["EN", "FR", "CS", "HU"]
# 循環(huán)遍歷所有語言
for language in languages:
#加載數(shù)據(jù)集
file_name=language+"_dataset.json"
qa_dataset = EmbeddingQAFinetuneDataset.from_json(file_name)
# 循環(huán)遍歷所有模型
for model_name, model_spec in embeddings_model_spec.items():
#取得模型
embed_model = OpenAIEmbedding(model=model_spec['model_name'],
dimensinotallow=model_spec['dimensions'])
# 評估嵌入分數(shù)(根據(jù)MRR)
score = evaluate(qa_dataset, embed_model)
results.append([language, model_name, score])
df_results = pd.DataFrame(results, columns = ["Language" ,"Embedding model", "MRR"])
根據(jù)MRR的結果準確性報告如下:
OpenAI模型的性能摘要
正如預期的那樣,對于大模型,3072的較大嵌入尺寸可以觀察到更好的性能。然而,與小型和傳統(tǒng)的Ada模型相比,大型模型比我們預期的要小。為了進行比較,我們還在下面報告了OpenAI模型在MTEB基準上獲得的性能。
OpenAI嵌入模型的性能(如其官方公告所述)
值得注意的是,在我們的評估中,大、小和Ada模型之間的性能差異遠不如MTEB基準中明顯。這反映了一個事實,即在大型基準中觀察到的平均性能并不一定反映在自定義數(shù)據(jù)集上獲得的性能。
4.開源嵌入模型的評估
當前,圍繞嵌入的開源研究相當活躍,并且定期發(fā)布新的模型。關于最新發(fā)布的模型,一個保持更新的好地方是Hugging Face MTEB排行榜(https://huggingface.co/spaces/mteb/leaderboard)。
為了在本文中進行比較,我們選擇了最近發(fā)表的一組四個嵌入模型(2024)。選擇的標準是它們在MTEB排行榜上的平均得分以及它們處理多語言數(shù)據(jù)的能力。所選模型的主要特征概述如下:
選定的開源嵌入模型
lE5-Mistral-7B-instruct(E5-Mistral-7B):微軟的這個E5嵌入模型(https://huggingface.co/intfloat/e5-mistral-7b-instruct)是從Mistral-7B-v0.1初始化的,并在多語言數(shù)據(jù)集的混合上進行了微調。該模型在MTEB排行榜上表現(xiàn)最好,但也是迄今為止最大的模型(14GB)。
lmultilingual-e5-large-instruct(ML-e5-larg):微軟的另一個e5模型(https://huggingface.co/intfloat/multilingual-e5-large-instruct),旨在更好地處理多語言數(shù)據(jù)。它是從xlm-roberta-large初始化的,并在多語言數(shù)據(jù)集的混合上進行訓練。它比E5-Mistral小得多(10倍),但上下文大小也低得多(514)。
lBGE-M3:該模型(https://huggingface.co/BAAI/bge-m3)由北京人工智能研究院設計,是他們最先進的多語言數(shù)據(jù)嵌入模型,支持100多種工作語言。截至2024年2月22日,尚未在MTEB排行榜上進行基準測試。
lnomic-embed-text-v1(nomic-embed):該模型由Nomic公司(https://home.nomic.ai/)設計,聲稱比OpenAI Ada-002和text-embedding-3-small性能更好,但尺寸僅為0.55GB。有趣的是,該模型是第一個完全可復制和可審計的模型(開放數(shù)據(jù)和開源訓練代碼)。
用于評估這些開源模型的代碼與用于OpenAI模型的代碼相似。主要的變化在于模型規(guī)范,其中必須指定額外的細節(jié),如最大上下文長度和池類型。然后,我們?yōu)樗姆N語言中的每一種評估每個模型:
embeddings_model_spec = {
}
embeddings_model_spec['E5-mistral-7b']={'model_name':'intfloat/e5-mistral-7b-instruct','max_length':32768, 'pooling_type':'last_token',
'normalize': True, 'batch_size':1, 'kwargs': {'load_in_4bit':True, 'bnb_4bit_compute_dtype':torch.float16}}
embeddings_model_spec['ML-E5-large']={'model_name':'intfloat/multilingual-e5-large','max_length':512, 'pooling_type':'mean',
'normalize': True, 'batch_size':1, 'kwargs': {'device_map': 'cuda', 'torch_dtype':torch.float16}}
embeddings_model_spec['BGE-M3']={'model_name':'BAAI/bge-m3','max_length':8192, 'pooling_type':'cls',
'normalize': True, 'batch_size':1, 'kwargs': {'device_map': 'cuda', 'torch_dtype':torch.float16}}
embeddings_model_spec['Nomic-Embed']={'model_name':'nomic-ai/nomic-embed-text-v1','max_length':8192, 'pooling_type':'mean',
'normalize': True, 'batch_size':1, 'kwargs': {'device_map': 'cuda', 'trust_remote_code' : True}}
results = []
languages = ["EN", "FR", "CS", "HU"]
# 循環(huán)遍歷所有模型
for model_name, model_spec in embeddings_model_spec.items():
print("Processing model : "+str(model_spec))
# 獲取模型
tokenizer = AutoTokenizer.from_pretrained(model_spec['model_name'])
embed_model = AutoModel.from_pretrained(model_spec['model_name'], **model_spec['kwargs'])
if model_name=="Nomic-Embed":
embed_model.to('cuda')
# 循環(huán)遍歷所有語言
for language in languages:
# 加載數(shù)據(jù)集
file_name=language+"_dataset.json"
qa_dataset = EmbeddingQAFinetuneDataset.from_json(file_name)
start_time_assessment=time.time()
# 評估嵌入得分(根據(jù)k=5時的命中率)
score = evaluate(qa_dataset, tokenizer, embed_model, model_spec['normalize'], model_spec['max_length'], model_spec['pooling_type'])
#計算分數(shù)評估的持續(xù)時間
duration_assessment = time.time()-start_time_assessment
results.append([language, model_name, score, duration_assessment])
df_results = pd.DataFrame(results, columns = ["Language" ,"Embedding model", "MRR", "Duration"])
根據(jù)MRR得出的精度報告如下:
開源模型的性能摘要
由上述圖表可見,BGE-M3的性能最好,其次是ML-E5-Large、E5-mistral-7b和Nomic Embed。BGE-M3模型尚未在MTEB排行榜上進行基準測試,我們的結果表明,它的排名可能高于其他模型。值得注意的是,雖然BGE-M3針對多語言數(shù)據(jù)進行了優(yōu)化,但它在英語方面的表現(xiàn)也比其他模型更好。
下面,我們還報告了每個嵌入模型的處理時間。
瀏覽英文問答數(shù)據(jù)集的處理時間(秒)
易見,E5-mistral-7b比其他模型大10多倍,是迄今為止速度最慢的模型。
5.結論
現(xiàn)在,讓我們把八個測試模型的性能放在同一個圖中進行比較。
八款測試模型的性能比對
從上述這些結果中,我們得到如下的主要分析結論:
- 開源模型獲得了最佳性能。其中,北京人工智能研究院開發(fā)的BGE-M3模型脫穎而出。該模型的上下文長度與OpenAI模型(8K)相同,大小為2.2GB。
- OpenAI范圍內的一致性。大型(3072)、小型和傳統(tǒng)OpenAI模型的性能非常相似。然而,減小大模型(256)的嵌入尺寸導致了性能的下降。
- 語言敏感性。幾乎所有模型(ML-E5-large除外)的英語表現(xiàn)都最好。捷克語和匈牙利語等語言的表現(xiàn)有顯著差異。
根據(jù)此結論,你應該訂閱付費的OpenAI還是選擇使用托管的開源嵌入模型呢?
OpenAI最近的價格修訂(https://openai.com/pricing)使其API的訪問變得更加實惠,目前成本為每百萬代幣0.13美元。因此,每月處理一百萬個查詢(假設每個查詢涉及大約1K個代幣)的成本約為130美元。因此,根據(jù)你的使用情況,租用和維護自己的嵌入服務器可能不劃算。
然而,成本效益并不是唯一的考慮因素??赡苓€需要考慮其他因素,如延遲、隱私和對數(shù)據(jù)處理工作流的控制。相對來說,開源模型提供了完全的數(shù)據(jù)控制、增強隱私和自定義的優(yōu)勢。另一方面,OpenAI的API還存在延遲問題,有時會導致響應時間延長。
總之,在開源模型和OpenAI等專有解決方案之間的選擇還不能馬上給出一個簡單的答案。顯然,開源嵌入提供了一種引人注目的選擇,其優(yōu)勢主要表現(xiàn)在能夠將性能與對數(shù)據(jù)的更大控制相結合。相反,OpenAI的產品可能仍然會吸引那些優(yōu)先考慮便利性的人,尤其是在隱私問題是次要的情況下。
關鍵參考資料
Companion Github存儲庫:
https://github.com/Yannael/multilingual-embeddings
你想知道的關于句子嵌入的一切(也許還有更多):
https://osanseviero.github.io/hackerllama/blog/posts
OpenAI博客發(fā)布:新的嵌入模型和API更新
https://openai.com/blog/new-embedding-models-and-api-updates
嵌入:OpenAI指南
ttps://platform.openai.com/docs/guides/embeddings/embedding-models
MTEB:海量文本嵌入基準與Hugging Face MTEB排行榜
https://huggingface.co/spaces/mteb/leaderboard
文本嵌入:綜合指南
https://towardsdatascience.com/text-embeddings-comprehensive-guide-afd97fce8fb5
檢索增強生成(RAG)從業(yè)者指南
https://cameronrwolfe.substack.com/p/a-practitioners-guide-to-retrieval。
如何為RAG找到最佳的多語言嵌入模型
譯者介紹
朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計算機教師,自由編程界老兵一枚。
原文鏈接:https://towardsdatascience.com/openai-vs-open-source-multilingual-embedding-models-e5ccb7c90f05