混合搜索
2.11 版引入
混合搜索结合了关键词搜索和语义搜索,以提高搜索相关性。要实现混合搜索,您需要设置一个在搜索时运行的搜索管道。该搜索管道在中间阶段拦截搜索结果,并应用处理来规范化和组合文档分数。
混合搜索有两种可用的处理器类型
- 归一化处理器(2.10 版本引入):一种基于分数的处理器,用于归一化和组合来自多个查询子句的文档分数,使用所选的归一化和组合技术对文档进行重新评分。
- 分数排名器处理器(2.19 版本引入):一种基于排名的处理器,使用排名融合来组合和重新排序来自多个查询子句的文档。
先决条件
要遵循此示例,您必须设置一个文本嵌入模型。更多信息请参见选择模型。如果您已生成文本嵌入,请跳到步骤 3。
配置混合搜索
配置混合搜索有两种方式
自动化工作流
OpenSearch 提供了一个工作流模板,可自动创建摄入管道、索引和搜索管道。创建工作流时,您必须提供已配置模型的模型 ID。请查阅混合搜索工作流模板的默认值,以确定是否需要更新任何参数。例如,如果模型维度与默认值(1024
)不同,请在 output_dimension
参数中指定模型的维度。要创建默认的混合搜索工作流,请发送以下请求
POST /_plugins/_flow_framework/workflow?use_case=hybrid_search&provision=true
{
"create_ingest_pipeline.model_id": "mBGzipQB2gmRjlv_dOoB"
}
OpenSearch 会为创建的工作流返回一个工作流 ID:
{
"workflow_id" : "U_nMXJUBq_4FYQzMOS4B"
}
要检查工作流状态,请发送以下请求:
GET /_plugins/_flow_framework/workflow/U_nMXJUBq_4FYQzMOS4B/_status
工作流完成后,state
将变为 COMPLETED
。该工作流创建以下组件
- 一个名为
nlp-ingest-pipeline
的摄入管道 - 一个名为
my-nlp-index
的索引 - 一个名为
nlp-search-pipeline
的搜索管道
您现在可以继续步骤 4 和 5,将文档摄入到索引中并搜索索引。
手动设置
要手动配置混合搜索,请遵循以下步骤
步骤 1:创建摄入管道
要生成向量嵌入,您需要创建一个包含 text_embedding
处理器的摄入管道,该处理器会将文档字段中的文本转换为向量嵌入。处理器的 field_map
决定了从中生成向量嵌入的输入字段以及存储嵌入的输出字段。
以下示例请求创建了一个摄入管道,它将 passage_text
中的文本转换为文本嵌入,并将嵌入存储在 passage_embedding
中
PUT /_ingest/pipeline/nlp-ingest-pipeline
{
"description": "A text embedding pipeline",
"processors": [
{
"text_embedding": {
"model_id": "bQ1J8ooBpBj3wT4HVUsb",
"field_map": {
"passage_text": "passage_embedding"
}
}
}
]
}
步骤 2:创建用于摄取的索引
为了使用管道中定义的文本嵌入处理器,请创建一个向量索引,并将上一步中创建的管道添加为默认管道。确保 field_map
中定义的字段映射为正确的类型。继续这个示例,passage_embedding
字段必须映射为维度与模型维度匹配的 k-NN 向量。同样,passage_text
字段应映射为 text
。
以下示例请求创建了一个设置了默认摄入管道的向量索引
PUT /my-nlp-index
{
"settings": {
"index.knn": true,
"default_pipeline": "nlp-ingest-pipeline"
},
"mappings": {
"properties": {
"id": {
"type": "text"
},
"passage_embedding": {
"type": "knn_vector",
"dimension": 768,
"method": {
"engine": "lucene",
"space_type": "l2",
"name": "hnsw",
"parameters": {}
}
},
"passage_text": {
"type": "text"
}
}
}
}
有关创建向量索引和使用支持方法的更多信息,请参见创建向量索引。
步骤 3:配置搜索管道
要使用 normalization-processor
配置搜索管道,请使用以下请求。处理器中的归一化技术设置为 min_max
,组合技术设置为 arithmetic_mean
。weights
数组以小数百分比形式指定分配给每个查询子句的权重。
PUT /_search/pipeline/nlp-search-pipeline
{
"description": "Post processor for hybrid search",
"phase_results_processors": [
{
"normalization-processor": {
"normalization": {
"technique": "min_max"
},
"combination": {
"technique": "arithmetic_mean",
"parameters": {
"weights": [
0.3,
0.7
]
}
}
}
}
]
}
步骤 4:将文档摄取到索引中
要将文档摄取到上一步创建的索引中,请发送以下请求:
PUT /my-nlp-index/_doc/1
{
"passage_text": "Hello world",
"id": "s1"
}
PUT /my-nlp-index/_doc/2
{
"passage_text": "Hi planet",
"id": "s2"
}
在文档被摄入到索引中之前,摄入管道会在文档上运行 text_embedding
处理器,为 passage_text
字段生成文本嵌入。索引文档包括包含原始文本的 passage_text
字段,以及包含向量嵌入的 passage_embedding
字段。
步骤 5:使用混合搜索搜索索引
要在您的索引上执行混合搜索,请使用 hybrid
查询,它结合了关键词搜索和语义搜索的结果。
示例:组合神经查询和匹配查询
以下示例请求结合了两个查询子句——一个 neural
查询和一个 match
查询。它将上一步中创建的搜索管道指定为查询参数。
GET /my-nlp-index/_search?search_pipeline=nlp-search-pipeline
{
"_source": {
"exclude": [
"passage_embedding"
]
},
"query": {
"hybrid": {
"queries": [
{
"match": {
"passage_text": {
"query": "Hi world"
}
}
},
{
"neural": {
"passage_embedding": {
"query_text": "Hi world",
"model_id": "aVeif4oB5Vm0Tdw8zYO2",
"k": 5
}
}
}
]
}
}
}
或者,您可以为 my-nlp-index
索引设置一个默认搜索管道。更多信息请参见默认搜索管道。
响应包含匹配的文档
{
"took" : 36,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.2251667,
"hits" : [
{
"_index" : "my-nlp-index",
"_id" : "1",
"_score" : 1.2251667,
"_source" : {
"passage_text" : "Hello world",
"id" : "s1"
}
}
]
}
}
示例:组合匹配查询和术语查询
以下示例请求结合了两个查询子句——一个 match
查询和一个 term
查询。它将上一步中创建的搜索管道指定为查询参数。
GET /my-nlp-index/_search?search_pipeline=nlp-search-pipeline
{
"_source": {
"exclude": [
"passage_embedding"
]
},
"query": {
"hybrid": {
"queries": [
{
"match":{
"passage_text": "hello"
}
},
{
"term":{
"passage_text":{
"value":"planet"
}
}
}
]
}
}
}
响应包含匹配文档:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.7,
"hits": [
{
"_index": "my-nlp-index",
"_id": "2",
"_score": 0.7,
"_source": {
"id": "s2",
"passage_text": "Hi planet"
}
},
{
"_index": "my-nlp-index",
"_id": "1",
"_score": 0.3,
"_source": {
"id": "s1",
"passage_text": "Hello world"
}
}
]
}
}
后续步骤
- 浏览我们的教程,了解如何构建 AI 搜索应用程序。