教程:使用推理 API 进行语义搜索

编辑

教程:使用推理 API 进行语义搜索

编辑

本教程中的说明将向您展示如何使用推理 API 工作流以及各种服务对您的数据执行语义搜索。

要在 Elastic Stack 中执行语义搜索的最简单方法,请参阅 semantic_text 端到端教程。

以下示例使用

您可以使用任何 Cohere 和 OpenAI 模型,推理 API 都支持它们。有关 HuggingFace 上推荐模型的列表,请参阅 支持的模型列表

单击下面任何小部件上要使用的服务名称,以查看相应的说明。

要求

编辑

需要一个 Cohere 帐户才能将推理 API 与 Cohere 服务一起使用。

创建推理端点

编辑

使用 创建推理 API 创建推理端点

resp = client.inference.put(
    task_type="text_embedding",
    inference_id="cohere_embeddings",
    inference_config={
        "service": "cohere",
        "service_settings": {
            "api_key": "<api_key>",
            "model_id": "embed-english-v3.0",
            "embedding_type": "byte"
        }
    },
)
print(resp)
const response = await client.inference.put({
  task_type: "text_embedding",
  inference_id: "cohere_embeddings",
  inference_config: {
    service: "cohere",
    service_settings: {
      api_key: "<api_key>",
      model_id: "embed-english-v3.0",
      embedding_type: "byte",
    },
  },
});
console.log(response);
PUT _inference/text_embedding/cohere_embeddings 
{
    "service": "cohere",
    "service_settings": {
        "api_key": "<api_key>", 
        "model_id": "embed-english-v3.0", 
        "embedding_type": "byte"
    }
}

路径中的任务类型为 text_embedding,推理端点的唯一标识符 inference_idcohere_embeddings

您的 Cohere 帐户的 API 密钥。您可以在 Cohere 仪表板的 API 密钥部分中找到您的 API 密钥。您只需要提供一次 API 密钥。获取推理 API 不会返回您的 API 密钥。

要使用的嵌入模型的名称。您可以在 此处找到 Cohere 嵌入模型的列表。

使用此模型时,建议在 dense_vector 字段映射中使用相似性度量 dot_product。在 Cohere 模型的情况下,嵌入被归一化为单位长度,在这种情况下,dot_productcosine 度量是等效的。

创建索引映射

编辑

必须创建目标索引的映射,该索引包含模型将根据您的输入文本创建的嵌入。对于大多数模型,目标索引必须具有一个带有 dense_vector 字段类型的字段,对于稀疏向量模型,如 elasticsearch 服务的情况,则具有 sparse_vector 字段类型,以便为所用模型的输出建立索引。

resp = client.indices.create(
    index="cohere-embeddings",
    mappings={
        "properties": {
            "content_embedding": {
                "type": "dense_vector",
                "dims": 1024,
                "element_type": "byte"
            },
            "content": {
                "type": "text"
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'cohere-embeddings',
  body: {
    mappings: {
      properties: {
        content_embedding: {
          type: 'dense_vector',
          dims: 1024,
          element_type: 'byte'
        },
        content: {
          type: 'text'
        }
      }
    }
  }
)
puts response
const response = await client.indices.create({
  index: "cohere-embeddings",
  mappings: {
    properties: {
      content_embedding: {
        type: "dense_vector",
        dims: 1024,
        element_type: "byte",
      },
      content: {
        type: "text",
      },
    },
  },
});
console.log(response);
PUT cohere-embeddings
{
  "mappings": {
    "properties": {
      "content_embedding": { 
        "type": "dense_vector", 
        "dims": 1024, 
        "element_type": "byte"
      },
      "content": { 
        "type": "text" 
      }
    }
  }
}

包含生成的标记的字段的名称。它必须在下一步的推理管道配置中被引用。

包含标记的字段是一个 dense_vector 字段。

模型的输出维度。在您使用的模型的 Cohere 文档中查找此值。

从中创建密集向量表示的字段的名称。在此示例中,字段的名称为 content。它必须在下一步的推理管道配置中被引用。

此示例中的字段类型为文本。

使用推理处理器创建索引管道

编辑

创建一个带有 推理处理器索引管道,并使用您上面创建的模型对管道中正在索引的数据进行推理。

resp = client.ingest.put_pipeline(
    id="cohere_embeddings_pipeline",
    processors=[
        {
            "inference": {
                "model_id": "cohere_embeddings",
                "input_output": {
                    "input_field": "content",
                    "output_field": "content_embedding"
                }
            }
        }
    ],
)
print(resp)
const response = await client.ingest.putPipeline({
  id: "cohere_embeddings_pipeline",
  processors: [
    {
      inference: {
        model_id: "cohere_embeddings",
        input_output: {
          input_field: "content",
          output_field: "content_embedding",
        },
      },
    },
  ],
});
console.log(response);
PUT _ingest/pipeline/cohere_embeddings_pipeline
{
  "processors": [
    {
      "inference": {
        "model_id": "cohere_embeddings", 
        "input_output": { 
          "input_field": "content",
          "output_field": "content_embedding"
        }
      }
    }
  ]
}

您使用 创建推理 API 创建的推理端点的名称,在该步骤中称为 inference_id

配置对象,定义推理过程的 input_field 和将包含推理结果的 output_field

加载数据

编辑

在此步骤中,您加载稍后在推理索引管道中使用的数据,以便从中创建嵌入。

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

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

通过推理索引管道索引数据

编辑

通过重新索引通过使用您选择的模型的推理管道的数据,从文本中创建嵌入。此步骤使用 reindex API 模拟通过管道进行数据索引。

resp = client.reindex(
    wait_for_completion=False,
    source={
        "index": "test-data",
        "size": 50
    },
    dest={
        "index": "cohere-embeddings",
        "pipeline": "cohere_embeddings_pipeline"
    },
)
print(resp)
const response = await client.reindex({
  wait_for_completion: "false",
  source: {
    index: "test-data",
    size: 50,
  },
  dest: {
    index: "cohere-embeddings",
    pipeline: "cohere_embeddings_pipeline",
  },
});
console.log(response);
POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "test-data",
    "size": 50 
  },
  "dest": {
    "index": "cohere-embeddings",
    "pipeline": "cohere_embeddings_pipeline"
  }
}

重新索引的默认批处理大小为 1000。将 size 减小到较小的数字可以更快地更新重新索引过程,这使您能够密切关注进度并及早发现错误。

您的 Cohere 帐户的速率限制可能会影响重新索引过程的吞吐量。

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

resp = client.tasks.get(
    task_id="<task_id>",
)
print(resp)
const response = await client.tasks.get({
  task_id: "<task_id>",
});
console.log(response);
GET _tasks/<task_id>

重新索引大型数据集可能需要很长时间。您可以使用数据集的子集测试此工作流程。通过取消重新索引过程,并且仅为重新索引的子集生成嵌入来执行此操作。以下 API 请求将取消重新索引任务

resp = client.tasks.cancel(
    task_id="<task_id>",
)
print(resp)
const response = await client.tasks.cancel({
  task_id: "<task_id>",
});
console.log(response);
POST _tasks/<task_id>/_cancel

语义搜索

编辑

使用嵌入丰富数据集后,您可以使用 语义搜索查询数据。对于密集向量模型,将 query_vector_builder 传递到 k 最近邻 (kNN) 向量搜索 API,并提供查询文本以及您用于创建嵌入的模型。对于像 ELSER 这样的稀疏向量模型,请使用 sparse_vector 查询,并提供查询文本以及您用于创建嵌入的模型。

如果您取消了重新索引过程,则您只能查询一部分数据,这会影响结果的质量。

resp = client.search(
    index="cohere-embeddings",
    knn={
        "field": "content_embedding",
        "query_vector_builder": {
            "text_embedding": {
                "model_id": "cohere_embeddings",
                "model_text": "Muscles in human body"
            }
        },
        "k": 10,
        "num_candidates": 100
    },
    source=[
        "id",
        "content"
    ],
)
print(resp)
response = client.search(
  index: 'cohere-embeddings',
  body: {
    knn: {
      field: 'content_embedding',
      query_vector_builder: {
        text_embedding: {
          model_id: 'cohere_embeddings',
          model_text: 'Muscles in human body'
        }
      },
      k: 10,
      num_candidates: 100
    },
    _source: [
      'id',
      'content'
    ]
  }
)
puts response
const response = await client.search({
  index: "cohere-embeddings",
  knn: {
    field: "content_embedding",
    query_vector_builder: {
      text_embedding: {
        model_id: "cohere_embeddings",
        model_text: "Muscles in human body",
      },
    },
    k: 10,
    num_candidates: 100,
  },
  _source: ["id", "content"],
});
console.log(response);
GET cohere-embeddings/_search
{
  "knn": {
    "field": "content_embedding",
    "query_vector_builder": {
      "text_embedding": {
        "model_id": "cohere_embeddings",
        "model_text": "Muscles in human body"
      }
    },
    "k": 10,
    "num_candidates": 100
  },
  "_source": [
    "id",
    "content"
  ]
}

因此,您会收到与 cohere-embeddings 索引中与查询含义最接近的前 10 个文档,这些文档按其与查询的接近程度排序

"hits": [
      {
        "_index": "cohere-embeddings",
        "_id": "-eFWCY4BECzWLnMZuI78",
        "_score": 0.737484,
        "_source": {
          "id": 1690948,
          "content": "Oxygen is supplied to the muscles via red blood cells. Red blood cells carry hemoglobin which oxygen bonds with as the hemoglobin rich blood cells pass through the blood vessels of the lungs.The now oxygen rich blood cells carry that oxygen to the cells that are demanding it, in this case skeletal muscle cells.ther ways in which muscles are supplied with oxygen include: 1  Blood flow from the heart is increased. 2  Blood flow to your muscles in increased. 3  Blood flow from nonessential organs is transported to working muscles."
        }
      },
      {
        "_index": "cohere-embeddings",
        "_id": "HuFWCY4BECzWLnMZuI_8",
        "_score": 0.7176013,
        "_source": {
          "id": 1692482,
          "content": "The thoracic cavity is separated from the abdominal cavity by the  diaphragm. This is a broad flat muscle.    (muscular) diaphragm The diaphragm is a muscle that separat…e the thoracic from the abdominal cavity. The pelvis is the lowest part of the abdominal cavity and it has no physical separation from it    Diaphragm."
        }
      },
      {
        "_index": "cohere-embeddings",
        "_id": "IOFWCY4BECzWLnMZuI_8",
        "_score": 0.7154432,
        "_source": {
          "id": 1692489,
          "content": "Muscular Wall Separating the Abdominal and Thoracic Cavities; Thoracic Cavity of a Fetal Pig; In Mammals the Diaphragm Separates the Abdominal Cavity from the"
        }
      },
      {
        "_index": "cohere-embeddings",
        "_id": "C-FWCY4BECzWLnMZuI_8",
        "_score": 0.695313,
        "_source": {
          "id": 1691493,
          "content": "Burning, aching, tenderness and stiffness are just some descriptors of the discomfort you may feel in the muscles you exercised one to two days ago.For the most part, these sensations you experience after exercise are collectively known as delayed onset muscle soreness.urning, aching, tenderness and stiffness are just some descriptors of the discomfort you may feel in the muscles you exercised one to two days ago."
        }
      },
      (...)
    ]

交互式教程

编辑

您还可以使用 Elasticsearch Python 客户端,找到交互式 Colab 笔记本格式的教程。