向量检索(Vector Retrieval) 也叫近似最近邻搜索(Approximate Nearest Neighbor Search, ANN),目标是在大规模向量集合中,快速找到与查询向量最相似的前k个向量。
向量检索是RAG(检索增强生成)、推荐系统、相似度搜索等应用的核心技术,随着大模型和向量数据库的发展,变得越来越重要。
X = {x1, x2, ..., xn},每个xi是d维向量。对于查询向量q,找到与q距离最近(相似度最高)的k个向量。常用的相似度/距离度量:
Annoy(Approximate Nearest Neighbors Oh Yeah) 是Spotify开源的高维空间近似最近邻搜索库。
核心思想:
构建过程:
参数调优:
n_trees:树的数量,构建时指定。值越大精度越高,但索引更大,构建慢search_k:搜索时检查的节点数量,值越大精度越高,但搜索越慢。默认为 n_trees * n代码示例:
1from annoy import AnnoyIndex
2import random
3
4f = 40 # 向量维度
5t = AnnoyIndex(f, 'angular') # angular表示余弦距离
6for i in range(1000):
7 v = [random.gauss(0, 1) for z in range(f)]
8 t.add_item(i, v)
9
10t.build(10) # 构建10棵树
11t.save('test.ann')
12
13# 加载查询
14u = AnnoyIndex(f, 'angular')
15u.load('test.ann') # mmap映射,很快
16print(u.get_nns_by_item(0, 10)) # 找离0最近的1000个邻居Faiss 是Facebook开源的稠密向量匹配检索库,支持C++和Python,是目前最流行的ANN库之一。
主要特性:
使用步骤:
代码示例:
1import numpy as np
2import faiss
3
4d = 64 # 向量维度
5nb = 100000 # 数据库大小
6nq = 10000 # 查询数量
7xb = np.random.random((nb, d)).astype('float32')
8xb[:, 0] += np.arange(nb) / 1000.
9xq = np.random.random((nq, d)).astype('float32')
10xq[:, 0] += np.arange(nq) / 1000.
11
12# 构建索引
13index = faiss.IndexFlatL2(d) # L2距离精确检索
14index.add(xb) # 添加向量到索引
15k = 4
16D, I = index.search(xq[:5], k) # 搜索,返回距离D和索引I
17print(D)
18print(I)Faiss提供多种索引类型,从精确检索到各种近似检索,精度和速度trade-off不同,选择合适的即可。
Milvus 是一款开源的特征向量相似度搜索引擎,特点:
Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,也支持向量检索。
倒排索引:
ES本质上是一个支持全文搜索的分布式数据库,面向文档,使用JSON存储数据,天然适合存储文档和搜索。
ES对应关系对比: | 关系数据库 | 数据库 → 表 → 行 → 列 | | Elasticsearch | 索引(Index) → 类型(type) → 文档(Document) → 字段(Fields) |
所有ANN算法都存在精度和速度的权衡:
什么是近似最近邻搜索(ANN)?为什么需要近似?
最近邻搜索就是在向量库找和查询向量最相似的k个向量。精确搜索需要遍历所有向量计算距离,时间复杂度O(n),n很大(百万/亿级)时太慢。近似最近邻通过构建索引、剪枝搜索空间,牺牲微小精度换得几个数量级的速度提升,能处理大规模向量库的实时检索,所以实际应用都用近似。
Annoy的原理是什么?
Annoy构建多个随机二叉搜索树,每个节点根据随机两个中心点分割空间。查询时遍历每棵树收集候选,最后从候选中选最近的。多个树提升准确率,查询时间是对数级。实现简单,索引文件可以mmap加载,内存占用小。
Faiss是什么?它的优势是什么?
Faiss是Facebook开源的向量检索库,是目前最流行的ANN库之一。优势:支持多种索引类型(从精确到各种近似),支持CPU/GPU,支持多种距离度量,C++实现性能很高,同时提供Python接口易用,工业界应用广泛。
向量检索在RAG中起什么作用?
RAG需要从海量文档库中找到和用户问题最相关的文档片段。首先把所有文档片段编码成向量存入向量库,用户问题编码成向量后,用向量检索找到最相似的top-k个文档片段,作为上下文输入给大模型。向量检索是RAG能够快速找到相关文档的核心。
Milvus和Faiss有什么区别?
Faiss是一个ANN算法库,需要你自己管理数据和索引;Milvus是完整的向量数据库,提供数据管理、CRUD、混合查询、持久化、服务化等功能,开箱即用,更适合生产环境部署。Milvus内部也集成了Faiss作为索引引擎。
欧氏距离和余弦相似度的区别是什么?什么时候用哪个?
欧氏距离衡量空间中的绝对距离,余弦相似度衡量方向的一致性,不考虑向量长度。如果是文本嵌入(BERT/Sentence-BERT输出),通常用余弦相似度,因为我们关心方向(语义)不关心长度。如果是特征向量绝对值本身就很重要,用欧氏距离。
倒排索引是什么?为什么适合全文搜索?
倒排索引是"词→文档"的映射,先分词,然后建立每个词对应的文档列表,查询时直接找到包含查询词的文档,把全文搜索转化为词查找,速度快。相比于B树索引,倒排索引更适合关键词匹配,但不适合频繁更新。
为什么向量检索现在这么火?
大语言模型发展,RAG成为大模型落地的主流方案,RAG需要向量检索;深度学习发展,很多任务都可以用向量表示内容(文本、图像、视频),相似度搜索需求增加;向量数据库成熟,降低了使用门槛,所以越来越火。