使用ElasticSearch实现文本相似性搜索

本文将会介绍如何使用ElastiSearch来部署文本嵌入(Embedding)模型,并实现之前向量数据库中的文本相似性搜索功能。

在文章使用ElasticSearch进行自然语言处理:以命名实体识别为例中,我们介绍了如何使用ElasticSearch来部署NER模型,并在ElasticSearch中利用部署的NLP模型来进行智能文本分析:从文本中提取实体,并形成词云图。

在文章向量数据库入门(一)文本相似性搜索中,笔者利用向量数据库如faissMilvus, Qdrant来实现文本相似性搜索。

本文将会在此基础上,使用ElastiSearch来部署文本嵌入(Embedding)模型,并实现之前向量数据库中的文本相似性搜索功能。

文本嵌入模型部署

我们在这里使用的文本嵌入模型为BAAI/bge-base-zh-v1.5,其网址为: https://huggingface.co/BAAI/bge-base-zh-v1.5 .该模型支持中文文本嵌入(Embedding),输出的向量维度为768,L2范数为1,即单位向量。

在文章使用ElasticSearch进行自然语言处理:以命名实体识别为例中,我们介绍了如何使用ElasticSearch来部署NER模型。类似地,我们可以部署文本嵌入模型,命令如下:

1
2
3
4
5
docker run -itd --rm docker.elastic.co/eland/eland \
eland_import_hub_model --url http://localhost:9200 \
--hub-model-id BAAI/bge-base-zh-v1.5 \
--task-type text_embedding \
--start --clear-previous

在Kibana界面中的Machine Learning -> Model Management -> Trained Models中,可查看部署的模型信息如下:

文本嵌入模型信息

在Dev Tools页面,使用API调用该模型,命令如下:

1
2
3
4
5
6
7
8
POST _ml/trained_models/baai__bge-base-zh-v1.5/_infer
{
"docs": [
{
"text_field": "阿波罗登月计划"
}
]
}

输出结果如下(取向量的前3位):

1
2
3
4
5
6
7
8
9
10
11
12
{
"inference_results": [
{
"predicted_value": [
-0.022389261052012444,
0.00514355069026351,
0.025597693398594856,
...
]
}
]
}

文本相似性搜索

我们使用和文章向量数据库入门(一)文本相似性搜索一样的示例文本,来实现相似文本的搜索。

利用Kibana上传json文本,创建dengyue索引,mapping如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"dengyue": {
"mappings": {
"_meta": {
"created_by": "file-data-visualizer"
},
"properties": {
"line": {
"type": "long"
},
"text": {
"type": "text"
}
}
}
}
}

创建Ingest Pipeline如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PUT _ingest/pipeline/text-embeddings
{
"description": "Demo text embedding pipeline",
"processors": [
{
"inference": {
"model_id": "baai__bge-base-zh-v1.5",
"target_field": "text_embedding",
"field_map": {
"text": "text_field"
}
}
}
],
"on_failure": [
{
"set": {
"description": "Index document to 'failed-<index>'",
"field": "_index",
"value": "failed-{{{_index}}}"
}
},
{
"set": {
"description": "Set error message",
"field": "ingest.failure",
"value": "{{_ingest.on_failure_message}}"
}
}
]
}

再创建一个新的索引dengyue-with-embeddings,其中索引dengyue-with-embeddings的mapping如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"dengyue-with-embeddings": {
"mappings": {
"properties": {
"line": {
"type": "long"
},
"text": {
"type": "text"
},
"text_embedding": {
"properties": {
"model_id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"predicted_value": {
"type": "dense_vector",
"dims": 768,
"index": true,
"similarity": "cosine"
}
}
}
}
}
}
}

其中text_embedding.predicted_value即为文本嵌入后的向量字段。

对索引dengyue应用text-embeddings pipeline,将数据迁移至dengyue-with-embeddings,此时已对索引dengyue中的text字段进行了文本嵌入。命令如下:

1
2
3
4
5
6
7
8
9
10
POST _reindex?wait_for_completion=false
{
"source": {
"index": "dengyue"
},
"dest": {
"index": "dengyue-with-embeddings",
"pipeline": "text-embeddings"
}
}

稍等片刻,新索引dengyue-with-embeddings已完成数据迁移,查看前3条数据,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[
{
"_index": "dengyue-with-embeddings",
"_id": "wAphqY4BTApH2kxu6Agz",
"_score": 1,
"_source": {
"text_embedding": {
"predicted_value": [
-0.06904672831296921,
-0.0306668933480978,
0.02560381218791008,
...
],
"model_id": "baai__bge-base-zh-v1.5"
},
"line": 0,
"text": "2023年7月12日,中国载人航天工程办公室副总师张海联披露,中国计划在2030年前实现载人登月。"
}
},
{
"_index": "dengyue-with-embeddings",
"_id": "wQphqY4BTApH2kxu6Agz",
"_score": 1,
"_source": {
"text_embedding": {
"predicted_value": [
-0.06188153848052025,
-0.0077980696223676205,
0.03301164135336876,
...
],
"model_id": "baai__bge-base-zh-v1.5"
},
"line": 1,
"text": "中文名中国载人登月工程外文名Manned lunar exploration project属 性科技工程发布时间2013年3月3日所属领域航天工程"
}
},
{
"_index": "dengyue-with-embeddings",
"_id": "wgphqY4BTApH2kxu6Agz",
"_score": 1,
"_source": {
"text_embedding": {
"predicted_value": [
-0.036897893995046616,
-0.05945304036140442,
0.0025381790474057198,
...
],
"model_id": "baai__bge-base-zh-v1.5"
},
"line": 2,
"text": "目录"
}
}
]

完成上述的准备工作后,我们就可以实现类似向量数据库中的文本相似性搜索功能了。

输入query为阿波罗登月计划,先使用如下命令获得其嵌入向量:

1
2
3
4
5
6
7
8
POST _ml/trained_models/baai__bge-base-zh-v1.5/_infer
{
"docs": [
{
"text_field": "阿波罗登月计划"
}
]
}

再利用ElasticSearch中内置的向量相似度检索命令(_knn_search)来搜索相似文本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GET dengyue-with-embeddings/_knn_search
{
"knn": {
"field": "text_embedding.predicted_value",
"query_vector": [
-0.022389261052012444,
0.00514355069026351,
0.025597693398594856,
...
],
"k": 3,
"num_candidates": 100
},
"_source": [
"line",
"text"
]
}

搜索出来的最相似的三条记录如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"took": 15,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 44,
"relation": "eq"
},
"max_score": 0.85360855,
"hits": [
{
"_index": "dengyue-with-embeddings",
"_id": "1gphqY4BTApH2kxu6Ag0",
"_score": 0.85360855,
"_source": {
"line": 22,
"text": "二十世纪六、七十年代,美国人凭借“阿波罗”计划率先登上月球。"
}
},
{
"_index": "dengyue-with-embeddings",
"_id": "wQphqY4BTApH2kxu6Agz",
"_score": 0.8161578,
"_source": {
"line": 1,
"text": "中文名中国载人登月工程外文名Manned lunar exploration project属 性科技工程发布时间2013年3月3日所属领域航天工程"
}
},
{
"_index": "dengyue-with-embeddings",
"_id": "5wphqY4BTApH2kxu6Ag0",
"_score": 0.7933982,
"_source": {
"line": 39,
"text": "在探月方面,2020年前将实现“回”的任务,即飞行器不但在月球上落下来,还取一些东西带回地球,并计划在2025年实现航天员登月。"
}
}
]
}
}

总结

本文使用ElastiSearch来部署文本嵌入(Embedding)模型,并实现之前向量数据库中的文本相似性搜索功能。同时,我们也可以看到,在ElastiSearch中也可以实现向量检索功能,十分方便。

推荐阅读

  1. 使用ElasticSearch进行自然语言处理:以命名实体识别为例
  2. 向量数据库入门(一)文本相似性搜索

参考文献

  1. 如何部署自然语言处理 (NLP):文本嵌入和矢量搜索: https://www.elastic.co/cn/blog/how-to-deploy-nlp-text-embeddings-and-vector-search

欢迎关注我的公众号NLP奇幻之旅,原创技术文章第一时间推送。

欢迎关注我的知识星球“自然语言处理奇幻之旅”,笔者正在努力构建自己的技术社区。


使用ElasticSearch实现文本相似性搜索
https://percent4.github.io/使用ElasticSearch实现文本相似性搜索/
作者
Jclian91
发布于
2024年4月6日
许可协议