向量索引优化
- 索引的作用是:让向量数据库更快的找到相似内容
- 如果不使用向量索引,向量检索时,相当于在海量的数据中每次都全量的扫描所有的向量
- 通过向量索引,相当于给向量数据加上了目录导航,快速快速匹配相似内容,不需要遍历所有向量
向量索引常见类型
- HNSW 是 RAG 很常见的选择,可以理解为地图、建立导航,基于图的索引
- 建立地图、内存消耗大、查询快,适合语义查询
- flat可以理解为精准查询,结果最准,但数据量大时会比较慢
- 类似mysql的精确查询
- flat这种类型就像没有加索引的mysql的全表扫描
- 火山引擎的向量数据库**VikingDB,**索引算法支持HNSW混合检索
- HNSW-Hybrid:| 索引类型 | 简单理解 | | -------- | -------------------------------- | | Flat | 暴力搜索,最准确但慢 | | HNSW | 常用,速度快,效果好 | | IVF | 先聚类,再查相关区域 | | PQ | 压缩向量,省空间,但可能损失精度 |
向量索引类型记忆
- HNSW:图结构快速找到与查询向量相近的向量
| 名称 | 英文拆解 | 一句话记忆 |
|---|---|---|
| FLAT | flat = 平铺 | 全量扫描,最准但慢 |
| IVF | inverted file = 倒排文件 | 先分桶,再搜索 |
| IVF_FLAT | IVF + 原始向量 | 分桶后用原始向量比 |
| IVF_PQ | IVF + product quantization | 分桶后压缩向量,省内存 |
| PQ | product quantization | 向量压缩 |
| HNSW | hierarchical navigable small world | 图导航,高速找相似 |
| SCANN | scalable nearest neighbors | 可扩展近邻搜索 |
| DiskANN | disk approximate nearest neighbor | 磁盘版大规模向量索引 |
| Cosine | cosine similarity | 看方向是否相似 |
| IP | inner product | 看点积 |
| L2 | Euclidean distance | 看空间距离 |
对比传统数据库的索引
- 传统数据库索引:为了快速找到“精确匹配”的数据。
- 向量索引:为了快速找到“语义相似”的数据
| 对比项 | 传统数据库索引 | 向量索引 |
|---|---|---|
| 主要对象 | 数字、字符串、日期、ID、状态字段 | 高维向量,比如 [0.12, -0.35, 0.88...] |
| 查询方式 | 精确匹配、范围查询、排序查询 | 相似度查询、最近邻查询 |
| 是否精确 | 通常是精确查询 | 通常是近似查询 |
| 常见索引 | B-Tree、Hash、Bitmap、倒排索引 | Flat、HNSW、IVF、IVF_PQ、DiskANN |
| 结果含义 | 找到满足条件的数据 | 找到最相似的数据 |
| 主要优化目标 | 查询更快 | 相似搜索更快、召回更高 |
| 典型应用 | 用户表、订单表、商品表、日志表 | RAG、语义搜索、推荐系统、图片搜索 |
向量索引配置
- 选择索引类型
- 选择相似度计算方式
- 创建索引时的参数
- 查询的参数
| 配置项 | 作用 | 常见值 |
|---|---|---|
index_type | 选择索引类型 | FLAT、HNSW、IVF_FLAT、IVF_PQ |
metric_type | 选择相似度计算方式 | COSINE、IP、L2 |
index_params | 建索引时的参数 | M、efConstruction、nlist |
search_params | 查询时的参数 | efSearch、nprobe |
索引配置理解
index_type = 用哪种目录结构
metric_type = 用什么方式判断相似
index_params = 建目录时怎么建
search_params = 查询时查多深、查多广
RAG 推荐默认配置
- HNSW 负责快速语义召回
- BM25 负责关键词/编号召回
- Rerank 负责精排
- 最终 top 5 给大模型
{
"embedding_model": "你的文本向量模型",
"index_type": "HNSW",
"metric_type": "COSINE",
"index_params": {
"M": 32,
"efConstruction": 200
},
"search_params": {
"efSearch": 128
},
"retrieval": {
"vector_top_k": 30,
"bm25_top_k": 30,
"rerank_top_n": 5
},
"chunk": {
"chunk_size": "500~800 tokens",
"chunk_overlap": "50~150 tokens"
}
}
相关参数配置理解
nprobe是 IVF 索引里的查询参数,可以理解为查询时探测多少个桶。probe是“探测”的意思,
| 参数 | 属于哪里 | 作用一句话 |
|---|---|---|
top_k | 检索返回参数 | 最终返回多少条候选结果 |
efSearch | HNSW 索引查询参数 | HNSW 查询时搜索多大范围 |
索引优化
- 根据RAG的评测进行调整参数
速度慢 → 降低 efSearch / nprobe / top_k
内存高 → 降低 M 或使用 IVF_PQ
排序不准 → 加 rerank
召回低理解
召回可以理解为
- 召回:检索出来的chunk / 检索出来的结果
- Recall:召回
- 召回公式:Recall = 找到的正确结果数量 / 所有应该找到的正确结果数量
- 召回率 = 找回来了多少正确答案
- 例子:比如你要搜索一个答案,答案目标chunk有10个,却找出来了8个,漏了2个
- 召回率:8/10 = 80%
在 RAG 里,它主要用来衡量:
用户问一个问题时,检索系统有没有把包含答案的 chunk 找出来 召回低:
- 知识库里明明有答案,但检索阶段没有把答案相关的 chunk 找出来
召回低优化
| 问题 | 优化方法 |
|---|---|
| 正确答案排在后面 | 增大 top_k,比如从 5 提到 30 |
| HNSW 搜不到 | 增大 efSearch |
| IVF 搜不到 | 增大 nprobe |
| 专有名词搜不到 | 加 BM25 / 关键词检索 |
| 语义匹配差 | 换更好的 embedding 模型 |
| chunk 不合理 | 调整 chunk_size 和 overlap |
| 无关结果太多 | 加 rerank |
| 过滤太严格 | 检查 metadata filter |
| 新资料搜不到 | 检查索引更新流程 |