正在加载

教程:使用数据摄取管道的密集和稀疏工作流

Elastic Stack Serverless

重要提示
  • 为了在 Elastic Stack 中执行语义搜索的最简单方法,请参阅 semantic_text 端到端教程。
  • 本教程是在引入 推理端点semantic_text 字段类型 之前编写的。 现在,我们有更简单的选项来执行语义搜索。

本指南向您展示如何使用部署在 Elasticsearch 中的模型实现语义搜索:从选择 NLP 模型到编写查询。

Elasticsearch 提供了对 各种 NLP 模型(包括密集和稀疏向量模型)的使用。 您对语言模型的选择对于成功实现语义搜索至关重要。

虽然可以自带文本嵌入模型,但通过模型调优获得良好的搜索结果具有挑战性。 从我们的第三方模型列表中选择合适的模型是第一步。 在您自己的数据上训练模型对于确保比仅使用 BM25 获得更好的搜索结果至关重要。 但是,模型训练过程需要一个数据科学家和 ML 专家团队,这使得它既昂贵又耗时。

为了解决这个问题,Elastic 提供了一个名为 Elastic Learned Sparse EncodeR (ELSER) 的预训练表示模型。 ELSER 目前仅适用于英语,是一种开箱即用的稀疏向量模型,无需微调。 这种适应性使其适用于各种 NLP 用例。 除非您拥有一支 ML 专家团队,否则强烈建议使用 ELSER 模型。

在稀疏向量表示的情况下,向量主要由零值组成,只有一小部分包含非零值。 这种表示通常用于文本数据。 对于 ELSER,索引中的每个文档和查询文本本身都由高维稀疏向量表示。 向量的每个非零元素都对应于模型词汇表中的一个术语。 ELSER 词汇表包含大约 30000 个术语,因此 ELSER 创建的稀疏向量包含大约 30000 个值,其中大部分为零。 实际上,ELSER 模型正在用其他术语替换原始查询中的术语,这些术语已被学习存在于最匹配训练数据集中原始搜索术语的文档中,并且权重用于控制每个术语的重要性。

在确定要使用哪个模型来实现语义搜索后,需要在 Elasticsearch 中部署该模型。

要部署 ELSER,请参阅 下载和部署 ELSER

要部署第三方文本嵌入模型,请参阅 部署文本嵌入模型

在开始使用已部署的模型基于您的输入文本生成嵌入之前,您需要首先准备您的索引映射。 索引的映射取决于模型的类型。

ELSER 生成来自输入文本和查询的令牌-权重对作为输出。 Elasticsearch sparse_vector 字段类型可以将这些令牌-权重对存储为数值特征向量。 该索引必须具有一个具有 sparse_vector 字段类型的字段,以索引 ELSER 生成的令牌。

要为您的 ELSER 索引创建映射,请参阅教程的 创建索引映射部分。 该示例展示了如何为 my-index 创建索引映射,该映射定义了 my_embeddings.tokens 字段(它将包含 ELSER 输出)作为 sparse_vector 字段。

 PUT my-index {
  "mappings": {
    "properties": {
      "my_tokens": {
        "type": "sparse_vector"
      },
      "my_text_field": {
        "type": "text"
      }
    }
  }
}
  1. 将包含 ELSER 生成的令牌的字段的名称。
  2. 包含令牌的字段必须是 sparse_vector 字段。
  3. 从中创建稀疏向量表示的字段的名称。 在此示例中,该字段的名称为 my_text_field
  4. 在此示例中,字段类型为 text

与 Elasticsearch NLP 兼容的模型生成密集向量作为输出。 dense_vector 字段类型适用于存储数值的密集向量。 该索引必须具有一个具有 dense_vector 字段类型的字段,以索引您选择的受支持的第三方模型生成的嵌入。 请记住,该模型生成具有一定维度数量的嵌入。 必须使用 dims 选项配置具有相同维度数量的 dense_vector 字段。 请参阅相应的模型文档以获取有关嵌入维度数量的信息。

要查看 NLP 模型的索引映射,请参阅教程的 将文本嵌入模型添加到摄取推理管道 部分中的映射代码片段。 该示例展示了如何创建索引映射,该映射定义了 my_embeddings.predicted_value 字段(它将包含模型输出)作为 dense_vector 字段。

 PUT my-index {
  "mappings": {
    "properties": {
      "my_embeddings.predicted_value": {
        "type": "dense_vector",
        "dims": 384
      },
      "my_text_field": {
        "type": "text"
      }
    }
  }
}
  1. 将包含模型生成的嵌入的字段的名称。
  2. 包含嵌入的字段必须是 dense_vector 字段。
  3. 该模型生成具有一定维度数量的嵌入。 必须使用 dims 选项配置具有相同维度数量的 dense_vector 字段。 请参阅相应的模型文档以获取有关嵌入维度数量的信息。
  4. 从中创建密集向量表示的字段的名称。 在此示例中,该字段的名称为 my_text_field
  5. 在此示例中,字段类型为 text

创建索引的映射后,您可以从输入文本生成文本嵌入。 这可以通过使用带有 推理处理器摄取管道 来完成。 摄取管道处理输入数据并将其索引到目标索引中。 在索引时,推理摄取处理器使用训练的模型来针对通过管道摄取的数据进行推理。 在使用推理处理器创建摄取管道后,您可以通过它摄取数据以生成模型输出。

以下是创建使用 ELSER 模型的摄取管道的方式

 PUT _ingest/pipeline/my-text-embeddings-pipeline {
  "description": "Text embedding pipeline",
  "processors": [
    {
      "inference": {
        "model_id": ".elser_model_2",
        "input_output": [
          {
            "input_field": "my_text_field",
            "output_field": "my_tokens"
          }
        ]
      }
    }
  ]
}
  1. 定义推理过程的 input_field 和将包含推理结果的 output_field 的配置对象。

要通过管道摄取数据以使用 ELSER 生成令牌,请参阅教程的 通过推理摄取管道摄取数据 部分。 成功使用管道摄取文档后,您的索引将包含 ELSER 生成的令牌。 令牌是捕获相关性的学习关联,它们不是同义词。 要了解有关令牌的更多信息,请参阅 此页面

以下是创建使用文本嵌入模型的摄取管道的方式

 PUT _ingest/pipeline/my-text-embeddings-pipeline {
  "description": "Text embedding pipeline",
  "processors": [
    {
      "inference": {
        "model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
        "target_field": "my_embeddings",
        "field_map": {
          "my_text_field": "text_field"
        }
      }
    }
  ]
}
  1. 您要使用的文本嵌入模型的模型 ID。
  2. field_map 对象将输入文档字段名称(在此示例中为 my_text_field)映射到模型期望的字段的名称(始终为 text_field)。

要通过管道摄取数据以使用您选择的模型生成文本嵌入,请参阅将文本嵌入模型添加到推理摄取管道章节。该示例展示了如何使用推理处理器创建管道,并通过管道重新索引您的数据。在使用管道成功摄取文档后,您的索引将包含模型生成的文本嵌入。

现在是执行语义搜索的时候了!

根据您部署的模型类型,您可以使用稀疏向量查询来查询排名特征,或者使用 kNN 搜索来查询密集向量。

可以使用稀疏向量查询来查询 ELSER 文本嵌入。稀疏向量查询使您能够通过提供与您要使用的 NLP 模型关联的推理 ID 和查询文本来查询稀疏向量字段

 GET my-index/_search {
   "query":{
    "sparse_vector": {
        "field": "my_tokens",
        "inference_id": "my-elser-endpoint",
        "query": "the query string"
      }
   }
}

可以使用kNN 搜索来查询密集向量模型生成的文本嵌入。在 knn 子句中,提供密集向量字段的名称,以及包含模型 ID 和查询文本的 query_vector_builder 子句。

 GET my-index/_search {
  "knn": {
    "field": "my_embeddings.predicted_value",
    "k": 10,
    "num_candidates": 100,
    "query_vector_builder": {
      "text_embedding": {
        "model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
        "model_text": "the query string"
      }
    }
  }
}

在某些情况下,词法搜索可能比语义搜索效果更好。 例如,当搜索单个单词或 ID(例如产品编号)时。

使用倒数排名融合将语义搜索和词法搜索合并到一次混合搜索请求中,可提供两者的最佳效果。 不仅如此,使用倒数排名融合的混合搜索已被证明通常表现更好

可以通过使用rrf retriever作为搜索请求的一部分来实现语义查询和词法查询之间的混合搜索。 提供 sparse_vector 查询和全文查询作为 rrf retriever 的standard retrieversrrf retriever 使用倒数排名融合来对排名最高的文档进行排名。

 GET my-index/_search {
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": {
                "my_text_field": "the query string"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
             "sparse_vector": {
                "field": "my_tokens",
                "inference_id": "my-elser-endpoint",
                "query": "the query string"
              }
            }
          }
        }
      ]
    }
  }
}

可以通过提供以下内容来实现语义查询和词法查询之间的混合搜索

  • 使用倒数排名融合来对排名最高的文档进行排名的 rrf retriever
  • 带有全文查询的 query 子句的子 retriever standard retriever
  • 带有查询密集向量字段的 kNN 搜索的子 retriever knn retriever
 GET my-index/_search {
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": {
                "my_text_field": "the query string"
              }
            }
          }
        },
        {
          "knn": {
            "field": "text_embedding.predicted_value",
            "k": 10,
            "num_candidates": 100,
            "query_vector_builder": {
              "text_embedding": {
                "model_id": "sentence-transformers__msmarco-minilm-l-12-v3",
                "model_text": "the query string"
              }
            }
          }
        }
      ]
    }
  }
}
© . All rights reserved.