Link Search Menu Expand Document Documentation Menu

k-NN API

OpenSearch 提供了多个 k-最近邻 (k-NN) API,用于管理、监控和优化您的向量工作负载。

统计

k-NN stats API 提供了有关 k-NN 插件当前状态的信息,该插件实现了向量搜索功能。这包括集群级和节点级统计信息。集群级统计信息对整个集群只有一个值。节点级统计信息对集群中的每个节点有一个值。您可以通过 nodeIdstatName 筛选查询,如下例所示。

GET /_plugins/_knn/nodeId1,nodeId2/stats/statName1,statName2

响应正文字段

下表列出了可用的响应正文字段。

字段 描述
circuit_breaker_triggered 指示断路器是否触发。此统计信息仅与近似 k-NN 搜索相关。
total_load_time k-NN 将本地库索引加载到缓存所需的时间(以纳秒为单位)。此统计信息仅与近似 k-NN 搜索相关。
eviction_count 由于内存限制或空闲时间,从缓存中逐出的本地库索引的数量。此统计信息仅与近似 k-NN 搜索相关。
注意:由于索引删除而发生的显式逐出不计入在内。
hit_count 缓存命中次数。当用户查询已加载到内存中的本地库索引时,会发生缓存命中。此统计信息仅与近似 k-NN 搜索相关。
miss_count 缓存未命中次数。当用户查询尚未加载到内存中的本地库索引时,会发生缓存未命中。此统计信息仅与近似 k-NN 搜索相关。
graph_memory_usage 本地库索引在节点上使用的本地内存量(以千字节为单位)。
graph_memory_usage_percentage 本地库索引在节点上使用的本地内存量占最大缓存容量的百分比。
graph_index_requests 将文档的 knn_vector 字段添加到本地库索引的请求数量。
graph_index_errors 将文档的 knn_vector 字段添加到本地库索引时产生错误的请求数量。
graph_query_requests 已执行的本地库索引查询数量。
graph_query_errors 在本地库索引查询期间产生错误的数量。
knn_query_requests 收到的 k-NN 查询请求数量。
cache_capacity_reached 是否已达到 knn.memory.circuit_breaker.limit。此统计信息仅与近似 k-NN 搜索相关。
load_success_count k-NN 成功将本地库索引加载到缓存的次数。此统计信息仅与近似 k-NN 搜索相关。
load_exception_count 尝试将本地库索引加载到缓存时发生异常的次数。此统计信息仅与近似 k-NN 搜索相关。
indices_in_cache 对于每个具有 knn_vector 字段并开启近似 k-NN 的 OpenSearch 索引,此统计信息提供该 OpenSearch 索引拥有的本地库索引数量以及该 OpenSearch 索引使用的总 graph_memory_usage(以千字节为单位)。
script_compilations k-NN 脚本已编译的次数。此值通常应为 1 或 0,但如果包含已编译脚本的缓存已满,k-NN 脚本可能会被重新编译。此统计信息仅与 k-NN 评分脚本搜索相关。
script_compilation_errors 脚本编译期间的错误数量。此统计信息仅与 k-NN 评分脚本搜索相关。
script_query_requests 脚本查询的总次数。此统计信息仅与 k-NN 评分脚本搜索相关。
script_query_errors 脚本查询期间的错误数量。此统计信息仅与 k-NN 评分脚本搜索相关。
nmslib_initialized 一个布尔值,指示 nmslib JNI 库是否已在节点上加载和初始化。
faiss_initialized 一个布尔值,指示 faiss JNI 库是否已在节点上加载和初始化。
model_index_status 模型系统索引的状态。有效值为 redyellowgreen。如果索引不存在,此值为 null
indexing_from_model_degraded 布尔值,指示从模型索引是否已降级。如果 JVM 内存不足以缓存模型,则会发生这种情况。
ing_requests 向节点发出的训练请求数量。
training_errors 节点上发生的训练错误数量。
training_memory_usage 节点上训练使用的本地内存量(以千字节为单位)。
training_memory_usage_percentage 节点上训练使用的本地内存量占最大缓存容量的百分比。

某些统计信息名称中包含 graph。在这些情况下,graph本地库索引 同义。术语 graph 反映了插件仅支持 HNSW 算法时的状态,该算法由分层图组成。

远程索引构建统计信息

3.0 版本引入

如果您配置了远程索引构建,响应将包含其他字段。下表列出了可用的远程索引构建统计信息响应正文字段。

字段 描述
repository_stats.read_success_count 从仓库成功读取操作的次数。
repository_stats.read_failure_count 从仓库读取操作失败的次数。
repository_stats.successful_read_time_in_millis 成功读取操作所花费的总时间(以毫秒为单位)。
repository_stats.write_success_count 向仓库成功写入操作的次数。
repository_stats.write_failure_count 向仓库写入操作失败的次数。
repository_stats.successful_write_time_in_millis 成功写入操作所花费的总时间(以毫秒为单位)。
client_stats.build_request_success_count 成功构建请求操作的次数。
client_stats.build_request_failure_count 构建请求操作失败的次数。
client_stats.status_request_failure_count 状态请求操作失败的次数。
client_stats.status_request_success_count 状态请求操作成功的次数。
client_stats.index_build_success_count 成功索引构建操作的次数。
client_stats.index_build_failure_count 索引构建操作失败的次数。
client_stats.waiting_time_in_ms 客户端等待远程构建完成的总时间(毫秒)。
build_stats.remote_index_build_flush_time_in_millis 远程刷新操作的总耗时(毫秒)。
build_stats.remote_index_build_merge_time_in_millis 远程合并操作的总耗时(毫秒)。
build_stats.remote_index_build_current_merge_operations 当前正在进行的远程合并操作数量。
build_stats.remote_index_build_current_flush_operations 当前正在进行的远程刷新操作数量。
build_stats.remote_index_build_current_merge_size 当前远程合并操作的大小。
build_stats.remote_index_build_current_flush_size 当前远程刷新操作的大小。

请求示例

以下示例演示了如何检索与 k-NN 插件相关的统计信息。

以下示例获取了集群中所有节点上 k-NN 插件的综合统计信息

GET /_plugins/_knn/stats?pretty
{
    "_nodes" : {
        "total" : 1,
        "successful" : 1,
        "failed" : 0
    },
    "cluster_name" : "my-cluster",
    "circuit_breaker_triggered" : false,
    "model_index_status" : "YELLOW",
    "nodes" : {
      "JdfxIkOS1-43UxqNz98nw" : {
        "graph_memory_usage_percentage" : 3.68,
        "graph_query_requests" : 1420920,
        "graph_memory_usage" : 2,
        "cache_capacity_reached" : false,
        "load_success_count" : 179,
        "training_memory_usage" : 0,
        "indices_in_cache" : {
            "myindex" : {
                "graph_memory_usage" : 2,
                "graph_memory_usage_percentage" : 3.68,
                "graph_count" : 2
            }
        },
        "script_query_errors" : 0,
        "hit_count" : 1420775,
        "knn_query_requests" : 147092,
        "total_load_time" : 2436679306,
        "miss_count" : 179,
        "training_memory_usage_percentage" : 0.0,
        "graph_index_requests" : 656,
        "faiss_initialized" : true,
        "load_exception_count" : 0,
        "training_errors" : 0,
        "eviction_count" : 0,
        "nmslib_initialized" : false,
        "script_compilations" : 0,
        "script_query_requests" : 0,
        "graph_query_errors" : 0,
        "indexing_from_model_degraded" : false,
        "graph_index_errors" : 0,
        "training_requests" : 17,
        "script_compilation_errors" : 0
    }
  }
}

以下示例检索了单个节点的特定指标(熔断器状态和图内存使用情况)

GET /_plugins/_knn/HYMrXXsBSamUkcAjhjeN0w/stats/circuit_breaker_triggered,graph_memory_usage?pretty
{
    "_nodes" : {
        "total" : 1,
        "successful" : 1,
        "failed" : 0
    },
    "cluster_name" : "my-cluster",
    "circuit_breaker_triggered" : false,
    "nodes" : {
        "HYMrXXsBSamUkcAjhjeN0w" : {
            "graph_memory_usage" : 1
        }
    }
}

预热操作

用于执行近似 k-NN 搜索的本地库索引作为特殊文件与其他 Apache Lucene 段文件一起存储。要使用 k-NN 插件在此类索引上执行搜索,插件需要将这些文件加载到本地内存中。

如果插件尚未将文件加载到本地内存中,则它会在收到搜索请求时加载它们。加载时间可能会导致初始查询期间的高延迟。为了避免这种情况,用户通常会在预热期间运行随机查询。预热期过后,文件会加载到本地内存中,其生产工作负载即可启动。此加载过程是间接的,需要额外的工作。

另外,您可以通过对要搜索的索引运行 k-NN 插件预热 API 操作来避免此延迟问题。此操作会将请求中指定的所有索引的所有分片(主分片和副本分片)的所有本地库文件加载到本地内存中。

进程完成后,您可以对索引进行搜索,而不会产生初始延迟开销。预热 API 操作是幂等的,因此如果某个段的本地库文件已加载到内存中,此操作将不起作用。它只加载当前未存储在内存中的文件。

请求示例

以下请求对三个索引执行预热操作

GET /_plugins/_knn/warmup/index1,index2,index3?pretty
{
  "_shards" : {
    "total" : 6,
    "successful" : 6,
    "failed" : 0
  }
}

The total 值表示 k-NN 插件尝试预热的分片数量。响应还包括插件成功预热的分片数量和未能预热的分片数量。

此调用在预热操作完成或请求超时之前不会返回结果。如果请求超时,则操作将在集群上继续进行。要监控预热操作,请使用 OpenSearch _tasks API。

GET /_tasks

操作完成后,使用 k-NN _stats API 操作 来查看 k-NN 插件加载到图中的内容。

最佳实践

为了使预热操作正常运行,请遵循以下最佳实践

  • 不要对要预热的索引运行合并操作。在合并操作期间,k-NN 插件会创建新段,并且有时会删除旧段。例如,您可能会遇到这样一种情况:预热 API 操作将本地库索引 A 和 B 加载到本地内存中,但段 C 是由段 A 和 B 合并创建的。本地库索引 A 和 B 将不再在内存中,本地库索引 C 也将不在内存中。在这种情况下,加载本地库索引 C 的初始开销仍然存在。

  • 确认您要预热的所有本地库索引都能适应本地内存。有关本地内存限制的更多信息,请参阅 knn.memory.circuit_breaker.limit 统计信息。高图内存使用会导致缓存颠簸,从而可能导致操作不断失败并尝试再次运行。

  • 不要索引任何要加载到缓存中的文档。向段写入新信息会阻止预热 API 操作加载本地库索引,直到它们可搜索。这意味着您必须在索引后再次运行预热操作。

k-NN 清除缓存

2.14 版本引入

在近似 k-NN 搜索或预热操作期间,本地库索引(用于 faissnmslib(已弃用)引擎)会加载到本地内存中。目前,您可以通过删除索引或设置 k-NN 集群设置 knn.cache.item.expiry.enabledknn.cache.item.expiry.minutes 来从缓存或本地内存中逐出索引,这会在索引空闲一段时间后将其从缓存中删除。但是,您无法在不删除索引的情况下从缓存中逐出索引。为了解决这个问题,您可以使用 k-NN 清除缓存 API 操作,它会从缓存中清除给定的一组索引。

k-NN 清除缓存 API 会逐出请求中指定的所有索引的所有分片(主分片和副本分片)的所有本地库文件。与 预热操作 的行为类似,k-NN 清除缓存 API 是幂等的,这意味着如果您尝试清除已从缓存中逐出的索引的缓存,它不会产生任何额外效果。

此 API 操作仅适用于使用 faissnmslib(已弃用)引擎创建的索引。它对使用 lucene 引擎创建的索引没有影响。

请求示例

以下请求将三个索引的本地库索引从缓存中逐出

POST /_plugins/_knn/clear_cache/index1,index2,index3?pretty
{
  "_shards" : {
    "total" : 6,
    "successful" : 6,
    "failed" : 0
  }
}

The total 参数表示 API 尝试从缓存中清除的分片数量。响应包括已清除的分片数量和插件未能清除的分片数量。

k-NN 清除缓存 API 可以与索引模式一起使用,以从缓存中清除一个或多个与给定模式匹配的索引,如下例所示

POST /_plugins/_knn/clear_cache/index*?pretty
{
  "_shards" : {
    "total" : 6,
    "successful" : 6,
    "failed" : 0
  }
}

API 调用在操作完成或请求超时之前不会返回结果。如果请求超时,则操作将在集群上继续进行。要监控请求,请使用 _tasks API,如下例所示

GET /_tasks

操作完成后,使用 k-NN _stats API 操作 来查看哪些索引已从缓存中逐出。

获取模型

GET 模型操作检索集群中存在的模型信息。某些本地库索引配置在开始索引和查询之前需要一个训练步骤。训练的输出是一个模型,可用于在索引期间初始化本地库索引文件。该模型在 k-NN 模型系统索引中序列化。

请求示例

GET /_plugins/_knn/models/{model_id}

响应正文字段

下表列出了可用的响应正文字段。

响应字段 描述
模型 ID 所获取模型的唯一标识符。
模型 BLOB 序列化模型的 Base64 编码字符串。
状态 模型的当前状态,可以是 created(已创建)、failed(失败)或 training(训练中)。
时间戳 模型创建的日期和时间。
描述 用户提供的模型描述。
错误 解释模型处于失败状态的错误消息。
空间类型 模型训练所使用的空间类型,例如欧几里得或余弦。注意:此值可以在请求的顶层设置。
维度 此模型所设计的向量空间的维度。
引擎 用于创建模型的本地库,可以是 faissnmslib(已弃用)。

请求示例

以下示例演示了如何使用 k-NN 插件 API 检索特定模型的信息。

以下示例返回模型的所有可用信息

GET /_plugins/_knn/models/test-model?pretty
{
  "model_id" : "test-model",
  "model_blob" : "SXdGbIAAAAAAAAAAAA...",
  "state" : "created",
  "timestamp" : "2021-11-15T18:45:07.505369036Z",
  "description" : "Default",
  "error" : "",
  "space_type" : "l2",
  "dimension" : 128,
  "engine" : "faiss" 
}

以下示例演示了如何选择性地检索字段

GET /_plugins/_knn/models/test-model?pretty&filter_path=model_id,state
{
  "model_id" : "test-model",
  "state" : "created"
}

搜索模型

您可以使用 OpenSearch 查询在索引中搜索模型。请参阅以下使用示例。

请求示例

以下示例展示了如何在 OpenSearch 集群中搜索 k-NN 模型,以及如何检索这些模型的元数据,其中不包括可能很大的 model_blob 字段

GET/POST /_plugins/_knn/models/_search?pretty&_source_excludes=model_blob
{
    "query": {
         ...
     }
}

响应包含模型信息

{
    "took" : 0,
    "timed_out" : false,
    "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
    },
    "hits" : {
      "total" : {
          "value" : 1,
          "relation" : "eq"
      },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : ".opensearch-knn-models",
        "_id" : "test-model",
        "_score" : 1.0,
        "_source" : {
          "engine" : "faiss",
          "space_type" : "l2",
          "description" : "Default",
          "model_id" : "test-model",
          "state" : "created",
          "error" : "",
          "dimension" : 128,
          "timestamp" : "2021-11-15T18:45:07.505369036Z"
        }
      }
    ]
  }
}

删除模型

您可以使用 DELETE 操作删除集群中的模型。请参阅以下使用示例。

请求示例

以下示例展示了如何删除 k-NN 模型

DELETE /_plugins/_knn/models/{model_id}
{
  "model_id": {model_id},
  "acknowledged": true
}

训练模型

您可以创建并训练一个模型,该模型可用于在索引期间初始化 k-NN 本地库索引。此 API 从训练索引中的 knn_vector 字段中提取训练数据,创建并训练模型,然后将其序列化到模型系统索引。训练数据必须与请求正文中传递的维度匹配。此请求在训练开始时返回。要监控模型的状态,请使用 获取模型 API

查询参数

下表列出了可用的查询参数。

查询参数 描述
模型 ID 所获取模型的唯一标识符。如果未指定,则生成一个随机 ID。可选。
节点 ID 指定执行训练过程的首选节点。如果提供,并且指定节点具有必要的容量和可用资源,则将使用该节点进行训练。可选。

请求正文字段

下表列出了可用的请求正文字段。

请求字段 描述
训练索引 检索训练数据的索引。
训练字段 training_index 中检索训练数据的 knn_vector 字段。此字段的维度必须与此请求中传递的 dimension 匹配。
维度 正在训练的模型的维度。
最大训练向量计数 用于训练的训练索引中的最大向量数。默认为索引中的所有向量。可选。
搜索大小 训练数据使用滚动查询从训练索引中提取。此参数定义每个滚动查询返回的结果数量。默认为 10000。可选。
描述 用户提供的模型描述。可选。
方法 用于搜索操作的近似 k-NN 方法的配置。有关可用方法的更多信息,请参阅 方法和引擎。该方法需要训练才能生效。
空间类型 训练此模型的空间类型,例如欧几里得或余弦。注意:此值也可以在 method 参数中设置。

请求示例

以下示例展示了如何为 k-NN 模型启动训练过程

POST /_plugins/_knn/models/{model_id}/_train?preference={node_id}
{
    "training_index": "train-index-name",
    "training_field": "train-field-name",
    "dimension": 16,
    "max_training_vector_count": 1200,
    "search_size": 100,
    "description": "My model",
    "space_type": "l2",
    "method": {
        "name":"ivf",
        "engine":"faiss",
        "parameters":{
            "nlist":128,
            "encoder":{
                "name":"pq",
                "parameters":{
                    "code_size":8
                }
            }
        }
    }
}

POST /_plugins/_knn/models/_train?preference={node_id}
{
    "training_index": "train-index-name",
    "training_field": "train-field-name",
    "dimension": 16,
    "max_training_vector_count": 1200,
    "search_size": 100,
    "description": "My model",
    "space_type": "l2",
    "method": {
        "name":"ivf",
        "engine":"faiss",
        "parameters":{
            "nlist":128,
            "encoder":{
                "name":"pq",
                "parameters":{
                    "code_size":8
                }
            }
        }
    }
}

示例响应

{
    "model_id": "dcdwscddscsad"
}
剩余 350 字符

有问题?

想要贡献?