Model2Vec - 世界上最快的静态嵌入技术


一、关于 Model2Vec


img

Model2Vec是一种将任何句子转换成非常小的静态模型的技术,将模型大小减少15倍,使模型速度提高500倍,性能略有下降。我们的最佳模型是世界上性能最好的静态嵌入模型。在这里查看我们的结果,或者深入了解它是如何工作的。


更新和公告


二、快速入门


安装

使用以下方式安装软件包:

pip install model2vec

这将安装基本推理包,它只依赖于numpy和其他一些次要依赖项。如果您想提取自己的模型,您可以使用以下方式安装蒸馏附加组件:

pip install model2vec[distill]

简单调用

开始使用Model2Vec的最简单方法是从HuggingFace Hub 中加载我们的一个旗舰模型。这些模型经过预训练并可以使用。以下代码片段展示了如何加载模型并进行嵌入:

from model2vec import StaticModel

# Load a model from the HuggingFace hub (in this case the potion-base-8M model)
model = StaticModel.from_pretrained("minishlab/potion-base-8M")

# 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."])

就是这样。您可以使用该模型对文本进行分类、聚类或构建RAG系统。

除了使用我们的模型之一,您还可以从 Sentence Transformer 模型中提取您自己的Model2Vec模型。以下代码片段展示了如何提取模型:

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

蒸馏非常快,在中央处理器上只需要30秒。最重要的是,蒸馏不需要训练数据。

有关高级用法,例如在句子Transformers 库中使用Model2Vec,请参阅用法部分。


主要特点

  • 最先进的性能:Model2Vec模型的性能大大优于任何其他静态嵌入(如GLoVe和BPEmb),如我们的结果所示。
  • 小型:Model2Vec将 Sentence Transformer 模型的大小减少了15倍,从120M参数减少到7.5M(磁盘上30 MB,使其成为MTEB上最小的模型!)。
  • 轻量级依赖项:基本包的唯一主要依赖项是numpy
  • 闪电般的推断:CPU速度比原始型号快500倍。去绿色或回家。
  • 快速、无数据集的蒸馏:在CPU上在30秒内提取您自己的模型,无需数据集。您只需要一个模型和(可选)一个自定义词汇表。
  • 集成在许多流行的库中:Model2Vec可以直接在流行的库中使用,如SentenceTransformers LangChaintxtaChonkie。有关更多信息,请参阅集成部分。
  • 与HuggingFace集线器紧密集成:使用熟悉的from_pretrainedpush_to_hub从HuggingFace集线器轻松共享和加载模型。我们自己的模型可以在这里找到。请随时分享您自己的。

什么是Model2Vec?

Model2vec创建了一个小型、快速、强大的模型,在我们能找到的所有任务上远远优于其他静态嵌入模型,同时创建速度比传统的静态嵌入模型(如GloVe)快得多。像BPEmb一样,它可以创建子词嵌入,但性能要好得多。蒸馏不需要任何数据,只需要一个词汇和一个模型。

基本模型2vec技术的工作原理是通过 Sentence Transformer 模型传递词汇,然后使用PCA降低生成嵌入的维数,最后使用zipf加权对嵌入进行加权。在推理过程中,我们只需取句子中出现的所有标记嵌入的平均值。

我们的药水模型使用Tokenlearn进行预训练,这是一种预训练Model2vec蒸馏模型的技术。

  • 蒸馏:我们使用上述方法从 Sentence Transformer 模型中提取Model2Vec模型。
  • Sentence Transformer 推断:我们使用 Sentence Transformer 模型为语料库中的大量文本创建均值嵌入。
  • 训练:我们训练一个模型以最小化句子变换模型生成的平均嵌入与Model2Vec模型生成的平均嵌入之间的余弦距离。
  • 训练后再正则化:我们通过首先执行PCA来重新正则化训练好的嵌入,然后使用以下公式使用smooth inverse frequency (SIF)加权嵌入:w = 1e-3 / (1e-3 + proba)。在这里,proba是我们用于训练的语料库中令牌的概率。

有关更广泛的深入了解,请参阅我们的Model2Vec博客文章和我们的Tokenlearn博客文章


三、用法


推理


使用预训练模型推理

推理工作如下。该示例显示了我们自己的模型之一,但您也可以只加载本地模型,或者从集线器加载另一个。

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."])

使用 Sentence Transformer 库进行推理

下面的代码片段展示了如何在 Sentence Transformer 库中使用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 蒸馏

以下代码可用于从 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")

从加载的模型中蒸馏

如果您已经加载了模型,或者需要以某种特殊方式加载模型,我们还提供了一个接口来提取内存中的模型。

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

使用 Sentence Transformers 库蒸馏

下面的代码片段展示了如何使用 Sentence Transformer 库提取模型。如果您想在 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."])

用自定义词汇蒸馏

如果您传递一个词汇表,您将获得一组静态词嵌入,以及该词汇表的自定义标记器。这与您使用GLoVe或传统word2vec的方式相当,但实际上不需要语料库或数据。

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)

**重要提示:**我们假设传递的词汇按等级频率排序。也就是说,我们不关心实际的单词频率,但是假设最频繁的单词是第一个,最不频繁的单词是最后一个。如果你不确定这是否是案例,将apply_zipf设置为False。这会禁用权重,但也会使性能稍微差一点。


四、评估


安装

我们的模型可以使用我们的评估包进行评估。

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

五、集成


Sentence Transformers

Model2Vec可以使用StaticEmbedding模块直接在 Sentence Transformer 中使用。

以下代码片段显示了如何将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."])

更多文档请参考句子Transformers 文档


LangChain

Model2Vec可以在朗链中使用langchain-community包。有关详细信息,请参阅朗链Model2Vec文档。以下代码片段显示了如何在使用pip install langchain-社区安装langchain-community包后在pip install langchain-community

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)

Txtai

Model2Vec可以在txtai中用于文本嵌入、最近邻搜索以及txta提供的任何其他功能。以下代码片段展示了如何在安装txtai软件包(包括vectors依赖项)后在pip install txtai[vectors]中使用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)

Chonkie

Model2Vec是Chonkie中语义分块的默认模型。要在Chonkie中使用Model2Vec进行语义分块,只需使用pip install chonkie[semantic]安装Chonkie,然后使用SemanticChunker类中的potion模型之一。以下代码片段展示了如何在Chonkie中使用Model2Vec:

from chonkie import SDPMChunker

# Create some example text to chunk
text = "It's dangerous to go alone! Take this."

# Initialize the SemanticChunker with a potion model
chunker = SDPMChunker(
    embedding_model="minishlab/potion-base-8M",
    similarity_threshold=0.3
)

# Chunk the text
chunks = chunker.chunk(text)

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

请注意,这要求Model2Vec有一个model.onnx文件和几个必需的标记器文件。要为还没有它们的模型生成这些,可以使用以下代码片段:

python scripts/export_to_onnx.py --model_path <path-to-a-model2vec-model> --save_path "<path-to-save-the-onnx-model>"

六、模型列表

我们提供了许多可以开箱即用的模型,这些模型在HuggingFace集线器上提供,可以使用from_pretrained方法加载,模型如下所列。

ModelLanguageVocabSentence TransformerTokenizer TypeParamsTokenlearn
potion-base-32MEnglishOutput + Frequent C4 tokensbge-base-en-v1.5Subword32.3M
potion-base-8MEnglishOutputbge-base-en-v1.5Subword7.5M
potion-base-4MEnglishOutputbge-base-en-v1.5Subword3.7M
potion-base-2MEnglishOutputbge-base-en-v1.5Subword1.8M
potion-retrieval-32MEnglishOutput + Frequent C4 tokensbge-base-en-v1.5Subword32.3M
M2V_multilingual_outputMultilingualOutputLaBSESubword471M

七、结果

我们进行了广泛的实验来评估Model2Vec模型的性能。结果记录在结果文件夹中。结果在以下部分中呈现:


2025-02-03(一)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值