Model2Vec:RAG 加速新引擎,模型瘦身15倍,速度提升500倍,最新emb benchmark
嵌入(Embedding)技術作為基石,廣泛應用于自然語言處理(NLP)、搜索引擎、推薦系統等多個關鍵領域,發揮著不可或缺的作用。盡管嵌入技術歷經持續發展并取得諸多顯著成果,但傳統嵌入方法始終受困于模型規模龐大、計算資源消耗嚴重、推理速度遲緩等難題,這些問題猶如枷鎖,限制了其進一步的拓展與應用。
在此背景下,Model2Vec 的全新嵌入技術為行業帶來了突破性的解決方案。它憑借創新性的設計,成功實現了嵌入模型規模縮小 15 倍、速度提升 500 倍(在CPU上)的驚人跨越,同時還能維持出色的性能表現,堪稱嵌入技術領域的一次重大飛躍。
1. Model2Vec:靜態嵌入的革新者
Model2Vec 是一種致力于提供高效、輕便且快速的靜態嵌入解決方案的創新模型,它與傳統的動態嵌入模型(如 Sentence Transformers)存在本質區別。傳統動態嵌入模型在處理每一個句子時,都需要實時計算新的嵌入向量,這使得其在運行過程中對計算資源有著極高的需求。而 Model2Vec 另辟蹊徑,采用靜態嵌入方式,提前對單詞或短語的嵌入向量進行計算并存儲。這種預計算的方式避免了重復計算帶來的資源浪費,大大提高了系統的整體運行效率。
Model2Vec 的優勢十分顯著。
- 從模型體積來看,在同等計算能力的前提下,它的嵌入模型相較于傳統模型縮小了 15 倍,這意味著可以節省大量的存儲空間,在資源有限的環境中也能輕松部署;
- 在速度方面,受益于預計算的靜態嵌入技術,其推理速度比傳統動態嵌入模型快 500 倍,幾乎能夠實現即時響應,為用戶帶來更為流暢的體驗;
- 此外,Model2Vec 無需進行復雜的預索引操作,支持直接對文檔進行向量搜索,這一特性極大地簡化了使用流程,降低了技術門檻。
2. 強大功能:重塑嵌入技術新格局
2.1 即時向量搜索
在處理大規模數據時,向量搜索的效率至關重要。Model2Vec 具備卓越的即時向量搜索能力,無論是面對數百萬文檔的海量數據集,還是復雜的搜索需求,它都能在秒級時間內給出響應,精準地完成向量搜索任務,這一特性為許多依賴大規模數據檢索的應用提供了強大支持。
2.2 模型壓縮與加速
Model2Vec 在模型壓縮和加速方面成績斐然。它成功將模型體積壓縮至原來的 1/15,同時實現了 500 倍的速度提升,且在這一過程中,性能幾乎沒有損失,依然保持著高精度和高效能,在保證結果準確性的同時,顯著提高了運行效率。
2.3 簡便易用的蒸餾
模型蒸餾是 Model2Vec 的又一亮點功能。通過簡單的操作,只需短短幾秒鐘,就能將復雜的 Sentence Transformers 模型轉化為靜態嵌入模型。這一過程無需大量的訓練數據,也不需要繁瑣的配置,極大地簡化了開發者的工作流程,讓更多開發者能夠輕松利用這一技術。
2.4 豐富的預訓練模型
為了進一步降低開發成本,Model2Vec 在 HuggingFace 平臺上提供了一系列預訓練的最先進的靜態嵌入模型。開發者無需從頭開始進行復雜的訓練過程,可直接調用這些預訓練模型,快速將其應用于自己的項目中,有效節省了時間和資源。
3. Model2Vec 與 RAG:珠聯璧合的高效組合
在 RAG(Retrieval-Augmented Generation,檢索增強生成) 模型中,檢索模塊是影響生成質量和效率的核心環節。Model2Vec 通過優化靜態嵌入技術,完美契合了 RAG 模型的需求,為其帶來了顯著的性能提升。
3.1 超高效的向量檢索
Model2Vec 強大的即時向量檢索能力,使其能夠對數百萬篇文檔進行快速檢索,而且無需復雜的預索引過程。這種高效的檢索速度直接加快了 RAG 模型中檢索模塊的響應速度,讓模型能夠更快地獲取相關信息,為后續的生成任務提供有力支持。
3.2 大幅度壓縮與加速
如前文所述,Model2Vec 將嵌入模型體積縮小 15 倍、速度提升 500 倍的特性,使得 RAG 模型在執行過程中的計算開銷大幅降低。這一優勢讓 RAG 模型在需要快速響應的大規模應用場景中表現更為出色,能夠更好地滿足用戶的需求。
3.3 與現有 RAG 架構無縫集成
Model2Vec 具備良好的兼容性,可以輕松與像 LangChain 等常見的 RAG 工具集成。通過這種集成,開發者能夠優化現有的 RAG 工作流,進一步提升數據檢索和生成的速度,實現更高效的應用開發。
4. 快速上手 Model2Vec
4.1 快速入門
對于想要嘗試 Model2Vec 的開發者來說,從 HuggingFace 中心加載其旗艦模型是最簡單的入門方式。這些模型已經過預先訓練,可直接投入使用。
安裝
pip install model2vec
# 安裝蒸餾附加功能
pip install model2vec[distill]
以下是加載模型并進行嵌入操作的示例代碼:
from model2vec import StaticModel
# 從HuggingFace中心加載模型(這里以potion-base-8M模型為例)
model = StaticModel.from_pretrained("minishlab/potion-base-8M")
# 進行嵌入操作
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
# 生成詞元嵌入序列
token_embeddings = model.encode_as_sequence(["It's dangerous to go alone!", "It's a secret to everybody."])
如果不想用官方提供的模型,可以采用下面的方法蒸餾自己的 Model2Vec 模型。蒸餾速度非常快,在 CPU 上只需要 30 秒。最重要的是,蒸餾不需要訓練數據。
from model2vec.distill import distill
# Distill a Sentence Transformer model, in this case the BAAI/bge-base-en-v1.5 model
m2v_model = distill(model_name="BAAI/bge-base-en-v1.5", pca_dims=256)
# Save the model
m2v_model.save_pretrained("m2v_model")
4.2 推理
4.2.1 用預訓練模型推理
from model2vec import StaticModel
# Load a model from the Hub. You can optionally pass a token when loading a private model
model = StaticModel.from_pretrained(model_name="minishlab/potion-base-8M", token=None)
# Make embeddings
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
# Make sequences of token embeddings
token_embeddings = model.encode_as_sequence(["It's dangerous to go alone!", "It's a secret to everybody."])
4.2.2 用Sentence Transformers庫推理
from sentence_transformers import SentenceTransformer
from sentence_transformers.models import StaticEmbedding
# Initialize a StaticEmbedding module
static_embedding = StaticEmbedding.from_model2vec("minishlab/potion-base-8M")
model = SentenceTransformer(modules=[static_embedding])
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
4.3 蒸餾
4.3.1 從Sentence Transformer模型蒸餾
from model2vec.distill import distill
# Distill a Sentence Transformer model
m2v_model = distill(model_name="BAAI/bge-base-en-v1.5", pca_dims=256)
# Save the model
m2v_model.save_pretrained("m2v_model")
4.3.2 從加載的模型蒸餾
from transformers import AutoModel, AutoTokenizer
from model2vec.distill import distill_from_model
# Assuming a loaded model and tokenizer
model_name = "baai/bge-base-en-v1.5"
model = AutoModel.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
m2v_model = distill_from_model(model=model, tokenizer=tokenizer, pca_dims=256)
m2v_model.save_pretrained("m2v_model")
4.3.3 從Sentence Transformers庫蒸餾
from sentence_transformers import SentenceTransformer
from sentence_transformers.models import StaticEmbedding
static_embedding = StaticEmbedding.from_distillation("BAAI/bge-base-en-v1.5", device="cpu", pca_dims=256)
model = SentenceTransformer(modules=[static_embedding])
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
4.3.4 帶自定義詞典蒸餾
from model2vec.distill import distill
# Load a vocabulary as a list of strings
vocabulary = ["word1", "word2", "word3"]
# Distill a Sentence Transformer model with the custom vocabulary
m2v_model = distill(model_name="BAAI/bge-base-en-v1.5", vocabulary=vocabulary)
# Save the model
m2v_model.save_pretrained("m2v_model")
# Or push it to the hub
m2v_model.push_to_hub("my_organization/my_model", token="<it's a secret to everybody>")
默認情況下,這將使用子詞分詞器來蒸餾模型,把模型(子詞)的詞匯表和新詞匯表合并起來。如果你希望得到一個詞級分詞器(僅包含傳入的詞匯表),可以將use_subword參數設置為False,例如:
m2v_model = distill(model_name=model_name, vocabulary=vocabulary, use_subword=False)
4.4 評估
安裝
pip install git+https://github.com/MinishLab/evaluation.git@main
下面的代碼片段展示了如何評估一個 Model2Vec 模型:
from model2vec import StaticModel
from evaluation import CustomMTEB, get_tasks, parse_mteb_results, make_leaderboard, summarize_results
from mteb import ModelMeta
# Get all available tasks
tasks = get_tasks()
# Define the CustomMTEB object with the specified tasks
evaluation = CustomMTEB(tasks=tasks)
# Load the model
model_name = "m2v_model"
model = StaticModel.from_pretrained(model_name)
# Optionally, add model metadata in MTEB format
model.mteb_model_meta = ModelMeta(
name=model_name, revision="no_revision_available", release_date=None, languages=None
)
# Run the evaluation
results = evaluation.run(model, eval_splits=["test"], output_folder=f"results")
# Parse the results and summarize them
parsed_results = parse_mteb_results(mteb_results=results, model_name=model_name)
task_scores = summarize_results(parsed_results)
# Print the results in a leaderboard format
print(make_leaderboard(task_scores))
4.5 集成
4.5.1 與Sentence Transformers集成
Model2Vec 可以通過StaticEmbedding模塊直接在 Sentence Transformers 中使用。
以下代碼片段展示了如何將 Model2Vec 模型加載到 Sentence Transformer 模型中:
from sentence_transformers import SentenceTransformer
from sentence_transformers.models import StaticEmbedding
# Initialize a StaticEmbedding module
static_embedding = StaticEmbedding.from_model2vec("minishlab/potion-base-8M")
model = SentenceTransformer(modules=[static_embedding])
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
以下代碼片段展示了如何將模型直接蒸餾為 Sentence Transformer 模型:
from sentence_transformers import SentenceTransformer
from sentence_transformers.models import StaticEmbedding
static_embedding = StaticEmbedding.from_distillation("BAAI/bge-base-en-v1.5", device="cpu", pca_dims=256)
model = SentenceTransformer(modules=[static_embedding])
embeddings = model.encode(["It's dangerous to go alone!", "It's a secret to everybody."])
4.5.2 與LangChain集成
Model2Vec 可以通過langchain-community包在 LangChain 中使用。在使用pip install langchain-community安裝langchain-community包后,以下代碼片段展示了如何在 LangChain 中使用 Model2Vec:
from langchain_community.embeddings import Model2vecEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.schema import Document
# Initialize a Model2Vec embedder
embedder = Model2vecEmbeddings("minishlab/potion-base-8M")
# Create some example texts
texts = [
"Enduring Stew",
"Hearty Elixir",
"Mighty Mushroom Risotto",
"Spicy Meat Skewer",
"Fruit Salad",
]
# Embed the texts
embeddings = embedder.embed_documents(texts)
# Or, create a vector store and query it
documents = [Document(page_content=text) for text in texts]
vector_store = FAISS.from_documents(documents, embedder)
query = "Risotto"
query_vector = embedder.embed_query(query)
retrieved_docs = vector_store.similarity_search_by_vector(query_vector, k=1)
4.5.3 與Txtai集成
Model2Vec 可在 txtai 中用于文本嵌入、最近鄰搜索,以及 txtai 提供的任何其他功能。在使用pip install txtai[vectors]安裝 txtai 包(包括向量相關依賴項)后,以下代碼片段展示了如何在 txtai 中使用 Model2Vec:
from txtai import Embeddings
# Load a model2vec model
embeddings = Embeddings(path="minishlab/potion-base-8M", method="model2vec", backend="numpy")
# Create some example texts
texts = ["Enduring Stew", "Hearty Elixir", "Mighty Mushroom Risotto", "Spicy Meat Skewer", "Chilly Fruit Salad"]
# Create embeddings for downstream tasks
vectors = embeddings.batchtransform(texts)
# Or create a nearest-neighbors index and search it
embeddings.index(texts)
result = embeddings.search("Risotto", 1)
4.5.4 與 Transformers.js 集成
要在 transformers.js 中使用 Model2Vec 模型,可將以下代碼片段作為起點:
import { AutoModel, AutoTokenizer, Tensor } from '@huggingface/transformers';
const modelName = 'minishlab/potion-base-8M';
const modelConfig = {
config: { model_type: 'model2vec' },
dtype: 'fp32',
revision: 'refs/pr/1'
};
const tokenizerConfig = {
revision: 'refs/pr/2'
};
const model = await AutoModel.from_pretrained(modelName, modelConfig);
const tokenizer = await AutoTokenizer.from_pretrained(modelName, tokenizerConfig);
const texts = ['hello', 'hello world'];
const { input_ids } = await tokenizer(texts, { add_special_tokens: false, return_tensor: false });
const cumsum = arr => arr.reduce((acc, num, i) => [...acc, num + (acc[i - 1] || 0)], []);
const offsets = [0, ...cumsum(input_ids.slice(0, -1).map(x => x.length))];
const flattened_input_ids = input_ids.flat();
const modelInputs = {
input_ids: new Tensor('int64', flattened_input_ids, [flattened_input_ids.length]),
offsets: new Tensor('int64', offsets, [offsets.length])
};
const { embeddings } = await model(modelInputs);
console.log(embeddings.tolist()); // output matches python version
本文轉載自??鴻煊的學習筆記??,作者: 乘風破浪jxj ?
