ElasticSearch向量检索技术方案介绍
1、背景
在人工智能快速发展的今天,推荐技术、以文搜图、以文搜视频、以图搜图等技术已经得到了广泛的应用,在百度、小红书、抖音、快手等app上随便输入一段文本,搜索结果已不像早些年那么单一:只有一些文字信息,现在的搜索结果里不仅有文字,还能够搜索出与检索词高度相关的图片、视频、或者商品(电商app),甚至都不用检索,feed流推荐的内容或者商品都是自身感兴趣的,大家一定会有疑问,整个系统背后是如何实现的呢,为什么输入一段文字,就能检索到相关的视频、音频或者图像呢?不同的内容形式,中间是怎么实现的匹配呢?
答案就是向量匹配,不同形式的内容需要转化成一个统一的结构化数据。
AI的出现,实现了这个过程,他可以以一定的算法提取文字、图像、音频、视频等各种形式内容的特征向量,实现了将所有内容形式转化为特征向量的过程。
内容结构化为特征向量后,那么如何进行检索呢?这就涉及到了本文的主题:向量检索了。
2、es向量检索
2.1 检索算法
1、KNN算法
KNN (K-Nearest Neighbor Search)指的是最近邻搜索。它的原理是:计算待查询向量与数据库中所有向量之间的距离,然后按照距离从小到大排序,选择距离最近的 K 个向量作为查询结果。KNN 算法的优点是可以保证精确的结果,但是效率较低。
2、ANN算法
ANN(Approximate Nearest Neighbor Search) 表示近似最近邻搜索,是一种用于高维数据空间中快速查找最近邻点的方法。与KNN(最近邻搜索)相比,ANN 牺牲了一定的精度以换取更高的搜索速度,因此在处理大规模数据集时具有较高的效率。
ANN 会对数据进行预处理,从而在查询时减少计算距离的次数。其优点是速度快、效率高,但精度有所下降。
3、HNSW
HNSW(Hierarchical Navigable Small World) 是一种基于图的高维向量相似性搜索算法。通过构建一张图来表示向量之间的相似度关系,并使用一些优化策略来加速搜索过程。
2.2 向量距离
向量检索的本质就是计算向量之间的距离,向量距离的大小直接反映两个向量的相似程度,距离越小,两个向量越相似,反之,相似度越低。
常用的距离度量有:
- 欧式距离:l2
- 余弦距离:cosine
- 内积:innerproduct
2.3 elasticsearch环境
es使用的是厂内的:百度Elasticsearch,最新版本7.10,支持向量检索。
2.4 创建索引
以下面创建索引的语句为例说明,这个索引即为工作中开发使用到的,只是对字段做了精简。
{
"settings": {
"index": {
"knn": true,
"number_of_shards": 9,
"number_of_replicas": 1
}
},
"mappings": {
"_source": {
"excludes": [
"IFV",
"TFV"
]
},
"properties": {
"car_id": {
"type": "keyword",
"ignore_above": 256
},
"camera_type": {
"type": "keyword",
"ignore_above": 256
},
"image_id": {
"type": "keyword",
"ignore_above": 256,
"index": false
},
"bbox": {
"properties": {
"left": {
"type": "integer",
"index": false
},
"top": {
"type": "integer",
"index": false
},
"width": {
"type": "integer",
"index": false
},
"height": {
"type": "integer",
"index": false
}
}
},
"IFV": {
"type": "bpack_vector",
"index_type": "hnsw_sq8",
"dims": 768,
"space_type": "l2",
"parameters": {
"m": 32,
"ef_construction": 256
}
},
"TFV": {
"type": "bpack_vector",
"index_type": "hnsw_sq8",
"dims": 768,
"space_type": "innerproduct",
"parameters": {
"m": 32,
"ef_construction": 256
}
}
}
}
}
各重要字段的含义如下:
字段 | 示例 | 说明 |
---|---|---|
setting | { "index": { "knn": true, "number_of_shards": 9, "number_of_replicas": 1 } } | knn:设置为ture,开启向量检索功能。 number_of_shards:分片数量,与集群节点数量一致。 number_of_replicas:副本数量,一般设置为1. |
excludes | : { "excludes": [ "IMAGE", "TEXT" ] }, | 这个字段主要是为了减少数据的存储,这样可以大大降低对存储的消耗(IFV、TFV为向量字段) |
IMAGE | "IMAGE": { "type": "bpack_vector", "index_type": "hnsw_sq8", "dims": 768, "space_type": "l2", "parameters": { "m": 32, "ef_construction": 256 } } | type:向量字段类型固定为 bpack_vector index_type: 向量检索算法,hnsw算法+sq8量化 dims:向量维度,768维 space_type:距离计算方式,l2,欧式距离 m:hnsw算法参数。此参数表示构造期间为每个新元素创建的双向链接数,主要影响内存、存储消耗以及召回率。m值越高,意味着更高消耗的内存和存储,更慢的索引构建时间,以及更好的召回率。建议根据min(向量维度 * 1.5, 32)取值,以保证性能,12-48可以满足大多数场景的需求。 ef_construction:hnsw算法参数。此参数表示在索引构建过程中,最近邻居的动态扫描区域大小。该值越大,越不容易陷入局部最优解,召回率更高,但是索引构建越慢,取值范围为[2,+∞]。需要注意,如果用户业务需求要求检索top k,那设置的ef_construction值需要大于k。 |
注意,向量检索算法、维数、距离计算方式千万不能出错,否则会出现检索结果相关性降低,甚至是不相关。
索引创建完成后,就可以正是写入数据了。
2.5 检索
检索dsl:
{
"size": 2,
"query": {
"knn": {
"image-vector": {
"vector": [
3,
4,
5,
6
],
"k": 2,
"ef": 100,
"filter": {
"term": {
"car_id": "A88888"
}
}
}
}
}
}
百度elasticsearch的向量检索与官方8.x版本es的检索语句稍有不同,支持向量检索和标量的组合检索。
3、代码实现(golang)
向量检索与普通检索在代码的实现上区别不大,重点是dsl的构建与普通检索略有不同,目前在自研的dsl包(elasticsearch查询语言DSL构建包使用及实现原理(golang)_golang es包-CSDN博客)也实现了向量检索dsl的构建,可以直接使用,非常方便,使用示例:
package main
import (
"fmt"
"github.com/liupengh3c/esbuilder"
)
func main() {
vector := []float64{0.045727044343948364, 0.029040496796369553,
0.02996855601668358, 0.0001537138596177101,
-0.011850773356854916, 0.016586067155003548,
0.029250113293528557}
dslQuery := esbuilder.NewDsl()
knnQuery := esbuilder.NewKnnQuery("IFV")
knnQuery.SetK(10).SetEf(256).SetVector(vector)
filter := esbuilder.NewTermQuery("car_id.keyword", "京AJB139")
knnQuery.Filter(filter)
dslQuery.SetQuery(knnQuery)
fmt.Println(dslQuery.BuildJson())
}
构建的dsl如下:
{
"query": {
"knn": {
"IFV": {
"ef": 256,
"filter": {
"term": {
"car_id.keyword": "京AJB139"
}
},
"k": 10,
"vector": [
0.045727044343948364,
0.029040496796369553,
0.02996855601668358,
0.0001537138596177101,
-0.011850773356854916,
0.016586067155003548,
0.029250113293528557
]
}
}
}
}
含义为,检索car_id为京AJB139且与检索条件中向量近似的数据。
4、展望
向量检索在信息技术和数据处理领域具有广泛的应用前景和重要性。随着技术的不断发展,向量检索的性能和准确性将不断提高,为各个领域带来更多的创新和价值。