向量簇召回模式

更新时间:
复制 MD 格式

说明向量簇召回模式的 Collection 配置、中心向量注册和自动选片参数。功能定位、适用场景和模式选型见向量簇召回。

模式由创建参数 slice_strategy=vector_cluster 决定,创建后不能修改。已有 Collection 需要切换模式时,必须新建 Collection 并重新导入数据。通用管理与数据 API 见 API 参考,以下说明向量簇模式的配置、路由和注册差异。

创建 Collection

下面用 3 个手工构造的向量簇验证流程,默认查询 2 个候选簇、最多查询 3 个;这些取值只对应本例。生产环境应使用实际聚类结果,并根据召回率、延迟和资源开销确定候选簇数量。

PUT /_slice_collection/products
{
  "slice_strategy": "vector_cluster",
  "auto_create_slice": false,
  "settings": {
    "index.number_of_shards": 2,
    "index.number_of_replicas": 2
  },
  "mappings": {
    "properties": {
      "cluster_id": { "type": "keyword" },
      "name": { "type": "keyword" },
      "embedding": {
        "type": "dense_vector",
        "dims": 2,
        "index": true,
        "similarity": "cosine",
        "index_options": {
          "type": "bbq_disk"
        }
      }
    }
  },
  "config": {
    "routing_field": "cluster_id",
    "vector_dims": 2,
    "default_query_vector_path": "knn.query_vector",
    "default_query_slice_count": 2,
    "max_query_slice_count": 3
  }
}

config 是向量簇召回模式的必填参数:

config 参数

是否必填

说明

routing_field

否

从写入文档的顶层字段读取 Slice。暂不支持 a.b 形式的嵌套路径。

vector_dims

是

Slice 中心向量的维度,取值范围 1~4096。

default_query_vector_path

是

查询向量在请求中的路径,支持 knn.query_vector 或 knn.N.query_vector。

default_query_slice_count

否

默认候选 Slice 数,默认值为 128,取值范围 1~10000。设置为大于 max_query_slice_count(默认 512)的值时,必须在同一请求中一并调高 max_query_slice_count,否则返回 HTTP 400。

max_query_slice_count

否

单次查询允许的最大候选 Slice 数,默认值为 512,取值范围 1~10000,且不能小于 default_query_slice_count。

命名空间模式(exact)不接受非空 config,否则返回 HTTP 400。

vector_dims 约束中心向量,mappings 中的 dense_vector.dims 约束文档向量。自动选片时,query_vector_path 指向的查询向量必须与中心向量维度一致。本例使用同一个 knn.query_vector 完成选片和文档检索,因此两处维度都设为 2,并使用同一向量模型。仅修改 vector_dims 不会自动对向量降维。

其余创建参数(settings、mappings、容量参数等)与命名空间模式一致,见 Collection 管理参考。需要注意两项默认值差异:

参数

命名空间模式默认值

向量簇召回模式默认值

auto_create_slice

true

false

index.sliced_postings.enabled

true

false

auto_create_slice 默认关闭,是因为向量簇必须先注册中心向量才能参与自动选片;写入时自动创建的 Slice 没有中心向量,会成为无法被自动召回的数据。除非确认业务能接受这一点,建议保持 auto_create_slice=false,先注册中心向量再写入。

预创建 Backing(可选,推荐)

Backing 默认按需创建。批量导入前推荐预创建 5 个底层索引,让新向量簇的数据分散存放,并减少首次写入时创建索引的等待。生产环境应结合向量簇增长、数据量和分片资源调整数量。

PUT /_slice_collection/products/backings?count=5

确认 acknowledged=true,且 backings 包含 5 个索引。预创建不会迁移已有 Slice,也不会生成中心向量;补齐语义和分配策略变化见预创建 Backing。

注册 Slice 中心向量

参与自动选片的 Slice 必须有中心向量,这一步不能省略。中心向量检索固定使用 cosine 相似度和 bbq_disk 索引,执行的是近似检索;它不随文档向量字段的 similarity 配置改变。

注册单个向量簇中心

PUT /_slice_collection/products/slices/cluster-a
{
  "vector": [0.9, 0.1]
}

批量注册向量簇中心

离线聚类任务通常会同时生成多个向量簇中心,可以使用批量接口一次注册:

PUT /_slice_collection/products/slices
{
  "slices": [
    { "slice": "cluster-b", "vector": [0.1, 0.9] },
    { "slice": "cluster-c", "vector": [0.6, 0.4] }
  ]
}

每个 item 的 Slice 名可以使用 slice 或 slice_id,但同一个 item 中只能出现一个。一次最多注册 20480 个 Slice,请求内不能重名。

注册结果判断

单个和批量注册接口可能在 HTTP 200 中报告 item 级错误,包括中心向量维度与 config.vector_dims 不一致。除处理非 2xx 响应外,还必须检查顶层 errors 和每个 items 元素的 result:created 表示新建,updated 表示中心向量已更新,noop 表示内容未变化,failed 表示失败。失败 item 包含字符串 error,不包含成功 item 的 backing_index。HTTP 请求成功不代表所有向量簇都注册成功。

{
  "acknowledged": true,
  "errors": false,
  "items": [
    {
      "slice_id": "cluster-b",
      "result": "created",
      "backing_index": ".sc-products-...-00000"
    },
    {
      "slice_id": "cluster-c",
      "result": "created",
      "backing_index": ".sc-products-...-00001"
    }
  ]
}

每个中心向量的维度必须与 config.vector_dims 一致。没有中心向量的 Slice 仍可被显式访问,但不会参与候选 Slice 的自动选择。重新注册同名 Slice 时,中心向量发生变化返回 updated,未变化返回 noop;两种情况都不会移动已写入的文档。

写入向量数据

常规写入不应传 refresh,也不要在应用代码中调用 _refresh。 等待后台自动刷新使数据可搜索,同步等待的受限条件见 Refresh 与查询可见性。

配置 routing_field 后,系统可以从文档顶层字段读取 Slice,无需再传 _slice:

PUT /products/_doc/product-1
{
  "cluster_id": "cluster-a",
  "name": "example-product",
  "embedding": [0.92, 0.08]
}

也可以显式提供 _slice=cluster-a,兼容 API 还可以使用 routing=cluster-a。显式指定 Slice 时,该值必须与文档中 routing_field 对应字段(本例为 cluster_id)的值一致,否则返回 HTTP 400。

配置 routing_field 后,不支持 scripted update。只需修改部分字段时,可使用 _update 的 doc 请求体,并显式携带一致的 _slice。需要根据旧值计算新值时,由应用读取、计算后写回,同时使用 if_seq_no 和 if_primary_term 做并发控制,避免覆盖其他请求的更新。

未配置 routing_field 时,写入方式与命名空间模式一致:每个写请求或 Bulk item 必须显式给出 _slice。其余写入行为(Bulk、Refresh 可见性、_update_by_query、_delete_by_query 等)见 文档读写与查询。

Copy 和 Branch 都会保留文档中的 routing_field 值。后续向目标 Slice 写回文档时,应显式指定目标,并使写入文档中的路由字段与目标一致,避免写回源 Slice 或触发校验错误,见 Copy 数据语义。

自动选择候选 Slice

写入后等待约 5 秒,让后台自动刷新使数据可搜索;若结果尚未包含新数据,再等一个自动刷新周期后重试。

预热已知的候选 Slice(可选)

如果能预先判断将访问的簇,推荐先预热,以降低首次查询冷数据的延迟。本例仅向 cluster-a 写入了一条文档,可以对它做一次预热:

POST /products/_warm_slice?_slice=cluster-a&wait_for_completion=true&timeout=60s

确认请求成功且 _shards.failed=0。本例已写入数据;若 _shards.total=0,先确认查询分片可用,并用实际查询核对数据已可搜索,再按需重试预热。同步等待仅用于验证本例;生产环境应提前按可预测的访问范围异步预热并控制并发,不要在每次自动选簇查询前遍历预热全部簇。详见预热 Slice 缓存。

执行查询

使用查询向量自动选择候选 Slice:

POST /products/_search?query_slice_count=2
{
  "knn": {
    "field": "embedding",
    "query_vector": [0.91, 0.09],
    "k": 10,
    "num_candidates": 100
  }
}

确认 timed_out=false、_shards.failed=0,并在 hits.hits 中找到本例写入的 product-1。

自动选择候选 Slice 的参数:

参数

说明

query_slice_count

本次选择的候选 Slice 上限。省略或设置为 0 时使用 Collection 的 default_query_slice_count。

query_vector_path

覆盖 Collection 的默认查询向量路径,支持 knn.query_vector 或 knn.N.query_vector。其中 N 从 0 开始;knn.query_vector 等价于第一个 KNN 子句的查询向量。

一次请求只用配置路径选出的一个查询向量决定整个请求的候选 Slice。多个 KNN 子句不会分别选片再取并集;其他 KNN 或混合查询子句同样受这组候选 Slice 范围限制。

query_slice_count 显式取非零值时必须在 1~max_query_slice_count 范围内,否则返回 HTTP 400。

请求显式指定 _slice 或兼容参数 routing 时,按指定范围查询;自动选择候选 Slice 时,只考虑已注册中心向量的 Slice。

默认关闭集群设置 apack.slice_collection.search.default_to_all_slices 时,配置路径中没有查询向量会返回 HTTP 400,此时应显式指定 _slice。开启该设置后,缺少查询向量会回退为查询全部 Slice;生产常规查询建议保持关闭,不要依赖全 Slice 回退。非法路径、使用 query_vector_builder 或查询向量维度与 vector_dims 不符,仍会返回 HTTP 400,不能通过该设置忽略。开关说明见指定查询范围。

Count API(_count)请求体不包含这里所需的内联查询向量,无法自动选片;保持默认关闭全量回退时,需要显式提供 _slice。其他不含查询向量的查询也应显式指定范围,见指定查询范围。

配置 Slice 内的向量检索

query_slice_count 控制候选 Slice 数量;文档向量字段的索引类型、visit_percentage 和 num_candidates 控制选定范围内的 KNN。字段和查询参数见向量字段与 KNN,两种能力的分工与选型见与 DiskBBQ 的关系。