一、向量数据库介绍
向量数据库能够有效存储和快速检索向量数据,特别是在人工智能和大数据分析中,能够支持复杂的数据类型和高效的相似度搜索,极大地提升了数据处理和分析的效率和精度。百度向量数据库 VectorDB支持多种索引类型和相似度算法,不仅能配合大模型打造专业知识库,还可以应用于图片搜索,音乐推荐,文本分类等领域。
二、向量索引的选择
VectorDB当前支持FLAT和HNSW索引,同时也支持“无索引”,即不对向量字段建立任何向量索引,仍然可以提供向量检索,而且是召回率为100%的KNN检索。如何根据业务特点选择这些索引,我们通过一个表格来进行对比分析:
索引类型 | 索引简介 | 成本 | 性能 | 召回率 | 适用场景 |
---|---|---|---|---|---|
无索引 | 不建立向量索引,在检索时,需要先将原始向量数据从磁盘中读取并加载到内存,然后在内存中执行KNN检索。 | 很低 | 很低 | 很高(100%) | 对成本有苛刻要求,同时对性能要求不高的场景。 |
FLAT | 即平坦索引,顾名思义,将原始向量数据平坦地摆放在内存中,不增加任何辅助机制。在检索时,需要计算每个向量与目标向量的相似性,所以一般也被称为“暴力检索”。其本质是全内存+KNN检索,相比于无索引,其数据需要全内存,会带来相应的成本。 | 高 | 中低 | 很高(100%) | 可以接受较高成本,也可以接受稍差一点的性能(相比于非暴力检索),但是对召回率有苛刻要求的场景。 |
HNSW | HNSW的全称是Hierarchical Navigable Small World,即分层可导航小世界,是一种经典的图结构索引,该索引的优势在于性能和召回率都比较稳定,整体效果受向量数据集的分布/倾斜的影响很小。HNSW索引目前最为广泛使用的索引方法之一,用于支撑ANN检索。 | 高 | 高(但在极限过滤场景下,可能会很低) | 高(但在极限过滤场景下,可能会很低) | 可以接受较高的成本,对性能也有较高的诉求,对召回率也有较高的诉求的场景。综合上来看是比较平衡的场景,此类场景广泛存在。 |
Puck | Puck是百度自行研发的向量索引,在百度内部得到了广泛的应用,索引了上万亿条向量。Puck是倒排类索引,但在基础倒排结构上做了大量的改造和优化,效果提升明显。 | 高 | 高 | 中、高 | 与图结构索引不同的是,倒排类索引在构建索引之前,往往需要在采样数据集的基础上执行一个基于K-Means聚类的训练过程训练出码本,Puck也不例外。训练过程比较消耗资源,因此训练时间可能较长,故此类索引不建议频繁重建,更适用于向量规模较大(比如单个数据集达到上亿级别),且对召回率没有过于严格要求的场景。基于大语言模型的应用场景不建议使用该索引。 |
HNSW索引看起来非常平衡,但在实际应用中,受该索引算法的固有特性影响,容易出现性能急剧下降或者召回率严重下滑的情况,这种情况一般出现在“极限过滤”的场景。所谓极限过滤场景,是指在检索时,需要将该索引集合中的绝大部分数据都过滤掉,只检索极小一部分数据。主要原因在于,在构建HNSW的图结构时,依据的是构建集合中的全部数据及其他们之间的距离,而在检索时,由于绝大部分数据又都过滤掉了不参与距离计算,检索的结果中可能出现严重的漏召现象,从而导致召回率严重下降,当然其严重程度也受数据的分布影响。这类极限场景容易出现在ToC的业务中,比如一个ToC业务,有很多终端用户,但是每个终端用户的数据量很小(例如几百几千条),同时在检索的时候,由于用户隐私问题,只能检索属于该用户自身的数据。如果按照数十万上百万的规模来对这类数据集构建HNSW索引,一个索引集中包含数百到上千个用户的数据,检索时仅检索其中的一个用户的数据,就会造成极限过滤场景。这类极限过滤场景并不容易优化。
三、开通VDB
请参考官方文档:https://cloud.baidu.com/doc/VDB/s/hlrsoazuf
四、AppBuilder-SDK操作VDB
共3步:
- 将数据segments插入VDB数据库;
- 构造查询;
- 从VDB返回查询信息。
详见代码注释。
import os
import appbuilder
from appbuilder import AppBuilderTracer
tracer=AppBuilderTracer(
enable_phoenix = False, # 暂时关闭Tracer
enable_console = False,
)
#开始Trace
tracer.start_trace()
# 请前往千帆AppBuilder官网创建密钥,流程详见:https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1%E3%80%81%E5%88%9B%E5%BB%BA%E5%AF%86%E9%92%A5
os.environ["APPBUILDER_TOKEN"] = 'bce-v3/ALTAK-bppeq3zxoIY1Kc4CvfB6j/74ca5e86a49606d2e84bb49d86a0230f8fb1b97f'
segments = appbuilder.Message(["Guoluan同学是大二老生", "Guoluan同学在黑龙江大学就读", "Guoluan同学从3岁开始跳舞", "黑大诞生于延安","Guoluan同学的专业是计算机及应用","Guoluan同学的生日跟财神爷一天","昨天交了453.2的英语书本费","黑龙江大学今年8月24日开学"])
# 初始化构建索引
vector_index = appbuilder.BaiduVDBVectorStoreIndex.from_params(
instance_id='vdb-bj-driaxot******',# 替换为你的VDB的instance_id
api_key='vdb$20uajh*****',# VBD的key即root用户的密码
drop_exists=True,# 如果索引存在则删除,否则可能会查出多条相同数据
)
vector_index.add_segments(segments)
# 循环提问和回答
while True:
user_input = input("请输入你的问题: ")
if user_input=='exit':
break
query = appbuilder.Message(user_input)
retriever = vector_index.as_retriever()
res = retriever(query,3) # 第2个参数为top_k即返回几条记录
# print(res)
for item in res.content:
if item['score']>0.8:
print(f"从向量数据库查询score>0.8的结果为:{item['text']},score为{item['score']}")
else:
print(f"其他参考结果:{item['text']},score为{item['score']}")
# 结束trace
tracer.end_trace()
执行python代码,当查询计算机的专业课时,根据语义搜索的效果如下图:
网友评论