02. 向量数据库
1. 简介
存储和搜索非结构化数据的最常见方法之一是将其编码为嵌入向量并存储,然后在查询时嵌入非结构化查询并检索与嵌入查询“最相似”的嵌入向量。向量数据库负责存储嵌入数据并为您执行向量搜索。
Rag中常用的向量数据库:In-Memory、Faiss(facebook ai similarity search)、Milvus。
向量数据库工作过程:1)获取被检索语料文本的向量集;2)将向量集存储,并构建索引。3)当收到用户Query的嵌入向量时,根据构建的索引高效检索预料内容。
2. 向量相似度(距离)的衡量
一般通过向量之间的距离来衡量向量之间的相似度。
常见的距离度量方式:
1)INNER_PRODUCT:向量标准化之后的内积:向量夹角。
2) L2(欧式距离):向量每个维度差的 平方和 再开根号。
3)L1(曼哈顿距离):向量每个维度差的 绝对值 总和。
... ...
3. 向量数据库的索引(Faiss为例)
当Query嵌入向量在检索向量数据库中最相似的向量的时候,如果采用暴力搜索的方法,时间复杂度O(mnd),很低效。因此,向量数据会采用构建索引的方式来加速搜索构成。在实际应用中,工业常用 IVFxPQy;但是HNSWx在不care内存的时候,可以达到实时的效果。
3.0 准备搜索语料向量和用户query向量
import numpy as np
d = 64 # 嵌入向量维度
nb = 100000 # 向量库中的向量数量
nq = 10000 # query的数量
np.random.seed(1234) # 设置随机种子,随机生成嵌入向量。
xb = np.random.random((nb, d)).astype('float32') # 预料库中向量的矩阵的shape:[nb, d]
xb[:, 0] += np.arange(nb) / 1000. # 对随机向量的第0维度引入偏移,偏移值和数据条数相关。(好玩)
xq = np.random.random((nq, d)).astype('float32') # 用户Query向量的矩阵的shape:[nq, d]
xq[:, 0] += np.arange(nq) / 1000. # 同样对Query矩阵的第0维度引入偏移值
3.1 暴力检索
50万条数据以内,且内存不紧张。
import faiss # make faiss available
index = faiss.IndexFlatL2(d) # build the index
print(index.is_trained) # 输出为True,说明已经训练完成了,不需要再额外训练
index.add(xb) # add vectors to the index
D, I = index.search(xq, k) # D为query向量与检索结果之间的 距离矩阵shape:[xq,];I为query向量的检索结果在数据库矩阵中的索引坐标。
3.2 逆向量倒排检索IVF
对向量k-means聚类,选取每个聚簇中心向量作为kw,每次搜索的时候先选取最近的几个聚簇中心,然后只从这几个最近的聚簇向量集合中搜索。
dim, measure = 64, faiss.METRIC_L2
param = 'IVF100,Flat' # 代表k-means聚类中心为100,
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为False,因为倒排索引需要训练k-means,
index.train(xb) # 因此需要先训练index,再add向量
index.add(xb)
3.3 倒排量化索引 IVFPQ
先对所有向量进行粗聚类(IVF),使得查询向量可以快速定位;然后进行乘积量化(向量压缩+查表距离估算,会将每个向量分段),使得能够用极小的存储和极快的查表运算,近似代替后续的高成本的原始向量计算过程。 简单理解:桶数量越少,构建索引过程块但查询过程慢;量化时分段的段数越少,编码粗糙查表次数少检索更快但精度低。向量压缩是指:向量分段之后,每一小段都会进行256个簇的聚类,然后具体的每个小段的值就用其最近的聚簇中心的值来表示。
dim, measure = 64, faiss.METRIC_L2
param = 'IVF100,PQ16'
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为False,因为倒排索引需要训练k-means,
index.train(xb) # 因此需要先训练index,再add向量
index.add(xb)
3.4 HNSWx分层图检索
分层图结构,最底层是最稠密的k近邻图结构,然后按概率将节点分到上层,每层再分别建立k近邻图结构。上层的稀疏图负责导航,最底层的稠密图负责精确索引。
优点:检索速度极快可以适应实时需求;缺点:构建索引很慢,内存占用很大,不支持从索引中删除向量。
4. Milvus vs Faiss
Milvus:国产的开源向量数据库,分布式部署可扩展,需要部署。适合企业级大规模应用场景(支持数亿甚至数十亿。)
Faiss:facebook开源的向量数据库,适合轻量级(百万级及以下)场景,单机检索性能出色。

浙公网安备 33010602011771号