RAG实践:ES混合搜索BM25+kNN(cosine)

1 缘起

最近在研究与应用混合搜索,

存储介质为ES,ES作为大佬牌数据库,

非常友好地支持关键词检索和向量检索,

当然,支持混合检索(关键词检索+向量检索),

是提升LLM响应质量RAG(Retrieval-augmented Generation)的一种技术手段,

那么,如何通过ES实现混合搜索呢?

请看本篇文章。

本系列分为两大部分:实践理论
先讲 实践,应对快速开发迭代 ,可快速上手实践;
再讲 理论,应对优化,如归一化。

RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化 https://blog.csdn.net/Xin_101/article/details/140237669

2 实践

2.1 环境准备

2.1.1 部署ES

  • 添加分词器

    将分词器文件添加到目录:/home/xindaqi/data/es-8-12-2/plugins

    新建分词器文件夹:mkdir -p /home/xindaqi/data/es-8-12-2/plugins/ik_analyzer_8.12.2

    将zip文件复制到文件夹:ik_analyzer_8.12.2

  • 启动ES

    docker run -dit
    --restart=always
    --name es01-8-12-2
    -p 9200:9200
    -p 9300:9300
    -v /home/xindaqi/data/es-8-12-2/data:/usr/share/elasticsearch/data
    -v /home/xindaqi/data/es-8-12-2/logs:/usr/share/elasticsearch/logs
    -v /home/xindaqi/data/es-8-12-2/plugins:/usr/share/elasticsearch/plugins
    -e ES_JAVA_OPS="-Xms512m -Xmx1g"
    -e discovery.type="single-node"
    -e ELASTIC_PASSWORD="admin-es"
    -m 1GB
    docker.elastic.co/elasticsearch/elasticsearch:8.12.2

2.1.2 数据准备

实践之前,需要准备数据,包括索引和索引中存储的数据。

为了演示混合搜索,这里创建两种类型的数据:text和dense_vector。

(1)创建索引
curl -X 'PUT' \
  'http://localhost:9200/vector_5' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Basic ZWxhc3RpYzphZG1pbi1lcw==' \
  -d '{
    "settings": {
		"index": {
			"number_of_shards": 1,
			"number_of_replicas": 1,
			"refresh_interval": "3s"
		}
	},
	"mappings": {
		"properties": {
			"dense_values": {
				"type": "dense_vector",
				"dims": 5,
				"index": true,
				"similarity": "cosine"
			},
			"id": {
				"type": "keyword"
			},
			"ik_text": {
				"type": "text",
        "analyzer": "ik_max_word"
			},
      "default_text": {
				"type": "text"
			},
			"timestamp": {
				"type": "long"
			},
			"dimensions": {
				"type": "integer"
			}
		}
	}
}'
(2)新建数据

新建两条数据:

curl -X POST 'http://localhost:9200/vector_5/_doc/1' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzphZG1pbi1lcw==' \
--data '{
    "dense_values": [0.1, 0.2, 0.3, 0.4, 0.5],
    "id": "1",
    "ik_text": "今天去旅游了",
    "default_text":"今天去旅游了",
    "timestamp": 1715659103373,
    "dimensions": 5
}'

curl -X POST 'http://localhost:9200/vector_5/_doc/2' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzphZG1pbi1lcw==' \
--data '{
    "dense_values": [0.1, 0.2, 0.3, 0.4, 0.5],
    "id": "1",
    "ik_text": "好美的太阳",
    "default_text":"好美的太阳",
    "timestamp": 1715659103373,
    "dimensions": 5
}'

2.2 向量搜索

kNN搜索

ES中向量搜索使用k-Nearest Neighbor(k最近邻分类算法)进行搜索。

输入的请求参数如下:

参数 参数 描述
knn 向量搜索k-Nearest Neighbor
field 向量字段名称
query_vector 向量值
k 召回结果数量
num_candidates 召回范围,每个分片选取的数量

请求样例如下:

由样例可知,存储向量数据的字段名称为:dense_values,填充向量值字段为query_vector(为固定属性),召回结果k为3个,每个分片选择100条数据(num_candidates),最大值为:10000。

实际应用过程中,又有向量数据较多(依据维度而定),为节约内存,检索时,在结果中排除,excludes。

curl 复制代码
curl -X POST 'http://localhost:9200/vector_5/_search' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzphZG1pbi1lcw==' \
--data '{
  "knn": {
    "field": "dense_values",
    "query_vector": [
      0.1,
      0.1,
      0.1,
      0.1,
      0.1
    ],
    "k": 3,
    "num_candidates": 100
  },
  "_source": {
    "excludes": [
      "dense_values"
    ]
  }
}'

检索结果如下,

由于创建过程中使用的向量数据相同,因此计算的结果也是相同的,

使用

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.8427159,
        "hits": [
            {
                "_index": "vector_5",
                "_id": "1",
                "_score": 0.8427159,
                "_source": {
                    "id": "1",
                    "ik_text": "今天去旅游了",
                    "default_text": "今天去旅游了",
                    "timestamp": 1715659103373,
                    "dimensions": 5
                }
            },
            {
                "_index": "vector_5",
                "_id": "2",
                "_score": 0.8427159,
                "_source": {
                    "id": "1",
                    "ik_text": "好美的太阳",
                    "default_text": "好美的太阳",
                    "timestamp": 1715659103373,
                    "dimensions": 5
                }
            }
        ]
    }
}

2.2 混合搜索

混合搜索即将搜索拆分成多个部分,每个部分使用不同的权重,实现混合搜索的效果。

ES中使用boost参数来分配不同部分的权重,搜索案例如下。

由案例可知,混合搜索使用关键词+向量搜索,关键词b1与向量总权重b2,其中b1+b2=1,

案例中关键词权重为0.6,向量权重0.4,

关键词搜索将搜索的内容映射到query上,权重映射到boost上,

default_text为实际存储的属性名称。

curl 复制代码
curl -X POST 'http://localhost:9200/vector_5/_search' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic ZWxhc3RpYzphZG1pbi1lcw==' \
--data '{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "default_text": {
                            "query": "好美的太阳",
                            "boost": 0.6
                        }
                    }
                }
            ]
        }
    },
    "knn": {
        "field": "dense_values",
        "query_vector": [
           0.1,
           0.1,
           0.1,
           0.1,
           0.1
        ],
        "k": 3,
        "num_candidates": 100,
        "boost": 0.4
    },
    "_source": {
        "excludes": [
            "dense_values"
        ]
    }
}'

3 小结

(1)ES混合搜索:通过boost配置比例,其中,关键词计算使用BM25计算分数,同时加入boost参数;

(2)关键词搜索boost基础比例为2.2,计算过程boost=2.2boost;
(3)向量搜索的最终分数为:final_score=boost
kNN。

计算过程参见文章:RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化
https://blog.csdn.net/Xin_101/article/details/140237669

相关推荐
消失在人海中1 小时前
大模型基础:基本概念、Prompt、RAG、Agent及多模态
大模型·prompt
Elastic 中国社区官方博客1 小时前
Elasticsearch:使用 LLM 实现传统搜索自动化
大数据·人工智能·elasticsearch·搜索引擎·ai·自动化·全文检索
慕雪华年1 小时前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch
网安-搬运工3 小时前
RAG再总结之如何使大模型更好使用外部数据:四个不同层级及查询-文档对齐策略
人工智能·自然语言处理·大模型·llm·大语言模型·ai大模型·rag
大模型八哥3 小时前
大模型扫盲系列——大模型实用技术介绍(上)
人工智能·程序人生·ai·大模型·llm·llama·ai大模型
Elastic 中国社区官方博客4 小时前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
alfiy4 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
alfiy5 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
百里香酚兰18 小时前
【AI学习笔记】基于Unity+DeepSeek开发的一些BUG记录&解决方案
人工智能·学习·unity·大模型·deepseek
一眼万里*e18 小时前
fish-speech语音大模型本地部署
python·flask·大模型