向量检索库总结
向量相似度检索,即根据一个向量Q从海量的向量库中寻找TopK个与Q最相似或者距离最近的向量,其在工业中有着广泛的应用场景,比如图像检索、文本语义检索以及推荐系统中基于User与Item的Embedding向量召回等。在生产环境中,被查找的向量库往往是海量,甚至超过了内存的限制,而且面临着高并发与低延迟的需求。当前涌现出了一系列高质量的向量化工具。
向量检索工具 | 发布 | 支持算法 | 分布式支持 | GPU 加速 | 备注 |
---|---|---|---|---|---|
Faiss | 全量计算LSHPQ近邻图 | 不支持 | 部分算法支持 | 开源目前最为成熟 | |
Milvus | 国产 | 全量计算LSHPQ近邻图搜索树 | 支持 | 部分算法支持 | 开源社区活跃 |
Elastic Search | 暴力搜索近邻图 | 支持 | 不支持 | ||
Vearch | JD | HNSWLSHPQ搜索树 | 支持 | 部分算法支持 | 基于 ES 二次开发 |
SPTAG | Microsoft | 近邻图搜索树 | 不支持 | 不支持 | 基于KD-Tree |
Annoy | Spotify | 近邻图搜索树 | 不支持 | 不支持 | 基于二叉树 |
向量数据库 weaviate | 开源的向量数据库,可以存储对象和向量,允许将向量搜索与结构化过滤相结合,并具有云原生数据库的容错性和可扩展性,可通过 GraphQL、REST 和各种语言客户端进行访问。 |
---|---|
向量数据库 PineCone | Pinecone为向量数据提供了数据存储解决方案。 |
嵌入式数据库 chroma | Chroma 是一个用于 Python / JavaScript LLM 应用程序的嵌入式数据库,它具有内存快速访问的优势 |
1、Gensim
Gensim是 Radim Řehůřek开源的一个主题建模、文本向量化计算工具库,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达,支持包括TF-IDF,LSA,LDA,和word2vec在内的多种主题模型算法,提供了针对向量的多种操作,如相似度计算,信息检索等一些常用任务的API接口,如找到与一个词相似度最高的词语集合,比较两个词语之间的相似度值。
地址:https://radimrehurek.com/gensim/
Gensim的提供了wordvec模块提供了cbow和skipgram两种词向量训练接口,用户可以通过训练自有语料来得到特定的向量文件。
因此,我们一方面可以直接使用该向量文件实现检索操作,也可以预先将预先得到的embedding【如DeepWalk、Node2vec得到的向量,根据TFIDF得到的文本向量,从其他开源渠道下载得到的向量等】按照gensim所规定的格式【一般是文件首行为词表大小、空格、向量维度,第二行至最后一行为每个词、空格、以空格连接的各维度向量】,调用该工具完成加载和使用,实验表明,gensim加载模型耗时很长,会将所有的词向量加载进入内存,占用内存很大,most_similar函数耗时较长。
2、Annoy
Annoy是Spotify开源的一个用于高维空间求近似最近邻的一个开源库,全称:Approximate Nearest Neighbors Oh Yeah,是一种适合实际应用的快速相似查找算法。Annoy对内存使用进行了优化,索引可以在硬盘保存或者加载,提供欧式距离,曼哈顿距离,余弦距离,汉明距离,內积距离等距离的度量方法,可以使用 Annoy 对 word2vec 等向量建立索引。
不过,Annoy仅支持树结构的索引类型,且不支持批量插入和查询,仅支持一种索引类型,单步查询速度快,另外,annoy中向量的item-id只接受非负数,如果自己的数据不符合要求需要自己维护一份映射。
地址:https://github.com/spotify/annoy
3、FAISS
Faiss是Facebook AI团队开源的针对聚类和相似性搜索的开源库,为稠密向量提供高效相似度搜索服务,支持十亿级别向量的搜索,是目前最为成熟的近似近邻搜索库之一。
Faiss提供了高效的索引类库。是向量化检索开山鼻祖的应用。
Faiss 支持多种向量检索方式,包括内积、欧氏距离等,同时支持精确检索与模糊搜索,并使用 GPU 来获得更高的内存带宽和计算吞吐量。
不过,Faiss本身只是一个能够单机运行的支持各种向量检索模型的机器学习算法基础库,不支持分布式实时索引和检索,同时也不支持标量字段的存储和索引等功能。
地址:https://github.com/facebookresearch/faiss
tutorial: https://github.com/facebookresearch/faiss/wiki/Getting-started
Faiss的使用
直接通过 pip install faiss-cpu —no-cache 进行安装。
faiss的使用方法也比较简单,归纳为以下三个步骤:
- 构建向量库,对已知的数据进行向量,最终以矩阵的形式表示
- 为矩阵选择合适的index,将第一步得到的矩阵add到index中
- search得到最终结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import numpy as np
import faiss
d = 64
nb = 100000
nq = 10000
# 构建向量库
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000.
# 关键步骤,build index
index = faiss.IndexFlatL2(d)
index.add(xb)
k = 4
D, I = index.search(xq[:5], k) # 分别返回距离和索引
4、SPTAG
SPTAG(空间分区树和图)是微软开源的BING搜索算法库,作为一种分布式近似最近邻域搜索(ANN)库,可用于大规模矢量搜索场景提供高质量矢量的索引构建,搜索和分布式在线服务。SPTAG内置L2 距离或余弦距离来计算向量之间的相似度,并提供KD-Tree 和相对邻域图(SPTAG-KDT)、以及平衡 k-means 树和相对邻域图(SPTAG-BKT)两种搜索算法。前者在指数构建成本方面能够有效降低成本,后者则在非常高维数据中保持较高的搜索精度。
地址:https://github.com/microsoft/SPTAG
5、Vearch
Vearch 是由京东开源的一个分布式向量搜索系统,考虑到开发及可扩展性,vearch 中的 Master,Router 和 PS 均采用 GO 语言编写。出于性能考虑,核心的存储检索引擎 gamma 基于 faiss 采用 c++ 语言实现, 提供了快速的向量检索功能,以及类似 Elasticsearch 的 Restful API 可以方便地对数据及表结构进行管理查询等工作。
此外,为满足实际业务场景需要,Vearch 还提供了算法插件服务模块,通过选择默认的 VGG,Resnet 或自定义算法模型等,能够提供端到端的图像检索,视频流智能监控等业务应用场景的实现。
地址:https://github.com/vearch/vearch
6、Milvus
Milvus 是一款国产开源的特征向量相似度搜索引擎,使用方便、实用可靠、易于扩展、稳定高效和搜索迅速。
- 高性能:涵盖如Faiss、Annoy和hnswlib等主流第三方索引库,性能高,支持对海量向量数据进行相似搜索。
- 高可用、高可靠:Milvus支持使用Kubernetes部署,支持在云上扩展。其容灾能力能够保证服务的高可用。Milvus依照日志及数据的理念,使用如Pulsar、Kafka等消息队列的技术实现组件间的通信,对组件进行解耦,拥抱云原生。
- 混合查询:Milvus支持在向量检索过程中进行标量字段过滤,实现混合查询。
- 开发者友好:支持多语言、多工具的Milvus生态。如今Milvus已经支持Python、Java、Go和Node.js,未来可能还会扩展对更多语言的支持。Milvus提供了如Attu等工具,帮助用户简化操作。
在实际实验中发现,与FAISS相比,Milvus多平台通用,mac,windows和linux都是支持的,可以通过docker部署,在平台通用性上好了不少,并且支持Java,c,c++和python等多种编程语言。值得注意的是,Milvus 专门开通了训练营们,对了解向量数据库的操作及各种应用场景做了索引,例如如何进行 Milvus 性能测评,搭建智能问答机器人、推荐系统、以图搜图系统、分子式检索系统。
嵌入式数据库:chroma
Chroma 是一个用于 Python / JavaScript LLM 应用程序的嵌入式数据库,它具有内存快速访问的优势。它只有 4 个核心函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import chromadb
# setup Chroma in-memory, for easy prototyping. Can add persistence easily!
client = chromadb.Client()
# Create collection. get_collection, get_or_create_collection, delete_collection also available!
collection = client.create_collection("all-my-documents")
# Add docs to the collection. Can also update and delete. Row-based API coming soon!
collection.add(
documents=["This is document1", "This is document2"], # we handle tokenization, embedding, and indexing automatically. You can skip that and add your own embeddings as well
metadatas=[{"source": "notion"}, {"source": "google-docs"}], # filter on these!
ids=["doc1", "doc2"], # unique for each doc
)
# Query/search 2 most similar results. You can also .get by id
results = collection.query(
query_texts=["This is a query document"],
n_results=2,
# where={"metadata_field": "is_equal_to_this"}, # optional filter
# where_document={"$contains":"search_string"} # optional filter
)
总结
在实践中,可以发现的是,gensim适合小规模试验的场景当中,只需要简单的命令,将向量文件表示为对应的格式,就可以完成相应的处理。Annoy、FAISS、SPTAG是较为底层的相似度算法库,FAISS目前广泛应用于搜索推荐场景当中,后两者在facebook以及微软的实际业务中成功的应用,直接证明了两个系统的稳定性和工业落地性。
此外,通过对比faiss和SPTAG,Vearch和Milvus两者属于同类型产品,Milvus和Vearch是两款基于现有的开发库,开箱即用的应用,在实现基本的相似计算功能的基础上,围绕服务整体易用性、部署、稳定性等方面做了更多工作。此外,Milvus对比Vearch,在社区活跃度、支持度上具有更明显的优势。
总之,我们在实际的业务落地场景中,要考虑自身的数据、资源、业务需求,合适的选用向量化方法和向量化搜索框架,将现有数据价值发挥到最大。