正在加载

使用 semantic_text 的混合搜索

Elastic Stack Serverless

本教程演示了如何执行混合搜索,将语义搜索与传统的全文搜索相结合。

在混合搜索中,语义搜索根据文本的含义检索结果,而全文搜索侧重于精确的单词匹配。 通过结合这两种方法,混合搜索可以提供更相关的结果,尤其是在仅依赖一种方法可能不足的情况下。

在 Elastic Stack 中使用混合搜索的推荐方法是遵循 semantic_text 工作流程。 本教程使用 elasticsearch 服务 进行演示,但您可以使用推理 API 提供的任何服务及其支持的模型。

目标索引将包含用于语义搜索的嵌入和用于全文搜索的原始文本字段。 这种结构可以组合语义搜索和全文搜索。

 PUT semantic-embeddings {
  "mappings": {
    "properties": {
      "semantic_text": {
        "type": "semantic_text"
      },
      "content": {
        "type": "text",
        "copy_to": "semantic_text"
      }
    }
  }
}
  1. 包含为语义搜索生成的嵌入的字段的名称。
  2. 包含用于词法搜索的原始文本的字段的名称。
  3. 存储在 content 字段中的文本数据将被复制到 semantic_text 并且由推理端点处理。
注意

如果您想在由网络爬虫或连接器填充的索引上运行搜索,则必须更新这些索引的索引映射以包括 semantic_text 字段。 更新映射后,您需要运行完整的网络爬网或完整的连接器同步。 这可确保所有现有文档都经过重新处理,并使用新的语义嵌入进行更新,从而可以在更新后的数据上启用混合搜索。

在此步骤中,您加载稍后用于创建嵌入的数据。

使用 msmarco-passagetest2019-top1000 数据集,它是 MS MARCO Passage Ranking 数据集的一个子集。 它包含 200 个查询,每个查询都附带一个相关的文本段落列表。 所有唯一的段落及其 ID 都已从该数据集中提取并编译到一个 tsv 文件中。

下载该文件并使用机器学习 UI 中的 数据可视化器将其上传到您的集群。 分析完您的数据后,单击覆盖设置。 在编辑字段名称下,将 id 分配给第一列,将 content 分配给第二列。 单击应用,然后单击导入。 将索引命名为 test-data,然后单击导入。 上传完成后,您将看到一个名为 test-data 的索引,其中包含 182,469 个文档。

将数据从 test-data 索引重新索引到 semantic-embeddings 索引。 源索引的 content 字段中的数据被复制到目标索引的 content 字段中。 在索引映射创建中设置的 copy_to 参数确保内容被复制到 semantic_text 字段中。 数据在摄取时由推理端点处理,以生成嵌入。

注意

此步骤使用重新索引 API 来模拟数据摄取。 如果您正在处理已经索引的数据,而不是使用 test-data 集,则仍然需要重新索引,以确保数据由推理端点处理并生成必要的嵌入。

 POST _reindex?wait_for_completion=false {
  "source": {
    "index": "test-data",
    "size": 10
  },
  "dest": {
    "index": "semantic-embeddings"
  }
}
  1. 重新索引的默认批量大小为 1000。将大小减小到更小的数字可以更快地更新重新索引过程,从而使您能够密切关注进度并及早发现错误。

该调用返回一个任务 ID 以监视进度

 GET _tasks/<task_id> 

重新索引大型数据集可能需要很长时间。 您可以使用数据集的子集来测试此工作流程。

要取消重新索引过程并为已重新索引的子集生成嵌入

 POST _tasks/<task_id>/_cancel 

将数据重新索引到 semantic-embeddings 索引后,您可以执行混合搜索以组合语义和词法搜索结果。 选择 retrieversES|QL 语法来执行查询。

此示例使用带有倒数排名融合 (RRF)retrievers 语法。 RRF 是一种将语义查询和词法查询的排名合并的技术,它会给予在任何一种搜索中排名较高的结果更高的权重。 这确保了最终结果是平衡且相关的。

 GET semantic-embeddings/_search {
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": {
                "content": "How to avoid muscle soreness while running?"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_text",
                "query": "How to avoid muscle soreness while running?"
              }
            }
          }
        }
      ]
    }
  }
}
  1. 第一个 standard retriever 代表传统的词法搜索。
  2. 使用指定的短语在 content 字段上执行词法搜索。
  3. 第二个 standard retriever 指的是语义搜索。
  4. semantic_text 字段用于执行语义搜索。

执行混合搜索后,该查询将返回语义和词法搜索条件的合并的前 10 个文档。 结果包括有关每个文档的详细信息。

{
  "took": 107,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 473,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
      {
        "_index": "semantic-embeddings",
        "_id": "wv65epIBEMBRnhfTsOFM",
        "_score": 0.032786883,
        "_rank": 1,
        "_source": {
          "semantic_text": {
            "inference": {
              "inference_id": "my-elser-endpoint",
              "model_settings": {
                "task_type": "sparse_embedding"
              },
              "chunks": [
                {
                  "text": "What so many out there do not realize is the importance of what you do after you work out. You may have done the majority of the work, but how you treat your body in the minutes and hours after you exercise has a direct effect on muscle soreness, muscle strength and growth, and staying hydrated. Cool Down. After your last exercise, your workout is not over. The first thing you need to do is cool down. Even if running was all that you did, you still should do light cardio for a few minutes. This brings your heart rate down at a slow and steady pace, which helps you avoid feeling sick after a workout.",
                  "embeddings": {
                    "exercise": 1.571044,
                    "after": 1.3603843,
                    "sick": 1.3281639,
                    "cool": 1.3227621,
                    "muscle": 1.2645415,
                    "sore": 1.2561599,
                    "cooling": 1.2335974,
                    "running": 1.1750668,
                    "hours": 1.1104802,
                    "out": 1.0991782,
                    "##io": 1.0794281,
                    "last": 1.0474665,
                   (...)
                  }
                }
              ]
            }
          },
          "id": 8408852,
          "content": "What so many out there do not realize is the importance of (...)"
        }
      }
    ]
  }
}

ES|QL 方法结合使用匹配运算符 : 和匹配函数 match() 来执行混合搜索。

 POST /_query?format=txt {
  "query": """
    FROM semantic-embeddings METADATA _score
    | WHERE content: "muscle soreness running?" OR match(semantic_text, "How to avoid muscle soreness while running?", { "boost": 0.75 }) <2>
    | SORT _score DESC
    | LIMIT 1000
  """
}
  1. METADATA _score 子句用于返回每个文档的分数
  2. 匹配 (:) 运算符content 字段上用于标准关键字匹配
  3. 语义搜索使用 match() 函数在 semantic_text 字段上进行,提升值为 0.75
  4. 按降序对分数进行排序,并限制为 1000 个结果
© . All rights reserved.