静态嵌入的实际应用

耗时:20 分钟难度:中等

在资源受限的计算领域,一场悄无声息的革命正在发生。虽然 Transformer 模型凭借其出色的性能在各项排行榜上占据主导地位,但静态嵌入正迎来意想不到的回归,它在提供显著速度提升的同时,仅付出了极小的质量损失。我们评估了 Qdrant 用户如何从这一复兴中获益,结果令人振奋

是什么让静态嵌入与众不同?

提到嵌入,Transformer 通常被视为唯一的选择。注意力机制的使用有助于捕捉输入标记(token)之间的关系,因此每个标记都能获得一个上下文感知的向量表示,该表示不仅由标记本身定义,还由周围的标记定义。基于 Transformer 的模型在质量上轻松超越了 word2vec 或 GloVe 等旧方法,后者只能为每个单词创建一个单一的向量嵌入。因此,单词“bank”在“river bank”(河岸)和“financial institution”(金融机构)这两个语境下会有完全相同的表示。

Static embeddings

而基于 Transformer 的模型会在不同语境下以不同的方式表示单词“bank”。然而,Transformer 带来了相应的代价。它们计算成本高昂,通常需要大量内存,尽管嵌入模型通常比大语言模型(LLM)参数更少。即便如此,即使在推理阶段,通常也倾向于使用 GPU。

不过,静态嵌入依然有其价值!MinishLab 在 2024 年 10 月推出了他们的 model2vec 技术,在保持出色性能水平的同时,实现了模型大小 15 倍的缩减和高达 500 倍的速度提升。他们的想法是从基于 Transformer 的句子转换器(Sentence Transformer)中提取知识,并创建一个更快、内存消耗更少的静态嵌入模型。这一举措似乎成了静态嵌入复兴的催化剂,因为我们看到静态嵌入甚至已被集成到流行的 Sentence Transformers 库中。Tom AarsenHugging Face 博客上发表的最新文章揭示了如何使用 Sentence Transformers 训练静态嵌入模型,并以极低的计算成本获得高达 85% 的 Transformer 级别质量。该博客文章还介绍了一种用于英文文本检索的嵌入模型,名为 static-retrieval-mrl-en-v1

Qdrant 中的静态嵌入

从向量数据库的角度来看,静态嵌入与其他任何嵌入模型并无不同。它们毕竟也是稠密向量,你可以简单地将它们存储在 Qdrant 集合中。以下是使用 sentence-transformers/static-retrieval-mrl-en-v1 模型实现的方法

import uuid

from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient, models

# The model produces vectors of size 1024
model = SentenceTransformer(
    "sentence-transformers/static-retrieval-mrl-en-v1"
)

# Let's assume we have a collection "my_collection" 
# with a single vector called "static"
client = QdrantClient("https://:6333")

# Calling the sentence transformer model to encode 
# the text is not different compared to any other model
client.upsert(
    "my_collection",
    points=[
        models.PointStruct(
            id=uuid.uuid4().hex,
            vector=model.encode("Hello, world!"),
            payload={"static": "Hello, world!"},
        )
    ]
)

检索速度并不会仅仅因为你使用了静态嵌入而变快。然而,在从数据创建向量的过程中,你将体验到巨大的速度提升,而这通常是性能瓶颈所在。Hugging Face 的那篇博客文章提到,该模型在 CPU 上的速度甚至可能比最先进的嵌入模型快 400 倍。

虽然我们没有对编码速度进行严格的基准测试,但在 BeIRTREC-COVID 数据集上所做的一项实验表明,我们可以在 约 7.5 分钟内完成 17.1 万条文档在 Qdrant 中的编码和完整索引。这一切都是在消费级笔记本电脑上完成的,且没有使用 GPU 加速。

静态嵌入的量化

真正能提升检索速度的是使用 Matryoshka Embeddings(套娃嵌入),因为 static-retrieval-mrl-en-v1 模型在训练时就考虑了该技术。然而,这并不是加速搜索的唯一方法。量化方法在我们的用户中非常受欢迎,我们很好奇它们是否可以同样成功地应用于静态嵌入。

我们选取了 static-retrieval-mrl-en-v1 模型,并在 BeIR 的不同子集上进行了测试(包括开启和关闭二进制量化),以观察它对检索质量的影响。结果非常有希望,正如我们的 NDCG@10 测量值(一种评估搜索结果排名质量的指标,分数越高代表性能越好)所示:

NDCG@10
数据集原始向量二进制量化,无重排序 (rescoring)
SciFact0.593480.54195
TREC-COVID0.44280.44185
ArguAna0.443930.42164
NFCorpus0.300450.28027

二进制量化无疑加快了检索速度并降低了成本,但在某些情况下,它似乎对检索质量的影响并不大。然而,这需要你在自己的数据上仔细验证。如果你是 Qdrant 用户,你可以直接在现有集合上启用量化,并衡量其对检索质量的影响

我们所有的测试都是使用 beir-qdrant 完成的,你可以通过运行 项目仓库中提供的脚本来重现这些测试。

谁应该使用静态嵌入?

对于那些希望在应用程序中使用语义搜索,但无法负担托管标准表示模型(例如由于硬件限制)的用户来说,静态嵌入似乎是一个预算友好的选择。一些可能的用例如下:

  • 移动应用程序 - 尽管许多智能手机拥有强大的 CPU 甚至 GPU,但电池续航仍然是个问题。静态嵌入可能是质量与功耗之间的一个良好折衷。此外,静态嵌入可以用于需要离线模式的应用程序。
  • Web 浏览器扩展 - 在 Web 浏览器中运行基于 Transformer 的模型通常不太可行,但静态嵌入可能是一个不错的选择,因为它们的参数更少,编码速度更快。
  • 嵌入式系统 - 对于计算能力有限的设备,如物联网(IoT)设备或微控制器,静态嵌入可能是一个很好的选择。

如果你属于上述情况,那么你绝对应该尝试一下静态嵌入。然而,如果搜索质量不是你的首要任务,那么即使在高性能环境中,你也可以考虑使用静态嵌入。编码过程的速度提升对你来说可能是颠覆性的。

静态嵌入的定制化

最后但同样重要的是,Tom Aarsen 发布的训练流水线可以帮助你训练自己的静态嵌入模型,因此你可以轻松地根据数据的具体情况进行调整。这个训练过程也将比基于 Transformer 的模型快得多,因此你可以更频繁地进行再训练。重新计算嵌入是语义搜索系统的瓶颈,而静态嵌入可能是解决此问题的一个好方案。定制的静态嵌入模型能否超越通用的预训练模型仍是一个悬而未决的问题,但绝对值得一试。

此页面有用吗?

感谢您的反馈!🙏

很遗憾听到这个消息。😔 你可以在 GitHub 上编辑此页面,或者创建一个 GitHub Issue