Elasticsearch「kNN Retriever」把向量检索装进一条 \_search 管线

1. kNN retriever 是什么?

kNN retriever 是 Retriever 框架中的首阶段召回器 ,负责对一个向量字段做近邻搜索 ,返回 Top-K 文档。相比早期的 knn 顶级语法,Retriever 让我们能在一个请求里组合多种策略 (如 RRF/Rescorer/Linear/Rule 等),把复杂的检索流程收敛到单次 API 调用

最小示例:

http 复制代码
GET /restaurants/_search
{
  "retriever": {
    "knn": {
      "field": "vector",          // dense_vector 且开启 indexing
      "query_vector": [10, 22, 77],
      "k": 10,                    // 返回的近邻数量
      "num_candidates": 10        // 每个分片候选集大小(≥ k)
    }
  }
}

2. 必备前提

  • field 必须是 dense_vector 且开启 indexing(支持近似向量检索)。
  • query_vector 维度必须与字段一致;
    或者用 query_vector_builder(由模型在线生成查询向量),二者不可同用
  • 适配 Serverless/Stack 的 Retriever 语法(8.16+ 普遍 GA,细节随版本演进)。

3. 核心参数详解与实战建议

3.1 field(必填)

向量字段名。
建议:为该字段单独配置合适的近似索引(例如 HNSW 的 M/efConstruction),以平衡召回率与延迟。

3.2 query_vector / query_vector_builder(二选一)

  • query_vector:直接传浮点数组或十六进制字节(与字段维度一致)。
  • query_vector_builder:在查询期由模型构建向量(适合服务化 embedding)。

选择指南:

  • 线上 RAG/检索场景通常预先 embed,性能更稳;
  • 想用统一模型推理与多模态输入时,考虑 query_vector_builder

3.3 k(必填)

最终返回的 Top-K。
经验值 :终端排序/重排还会继续"洗牌",k 设得略大于展示位(如展示 10,可取 50~100)更稳。

3.4 num_candidates(必填/有默认)

每分片候选集大小,≥ k(或当未显式 k≥ size),且 ≤ 10000

默认:min(1.5 * k, 10_000)

调优要点

  • 更大num_candidates更高召回更准 Top-K,但延迟与内存占用上升;
  • 多分片时是分片级 采样:每个分片都先取 num_candidates,合并后再出全局 Top-K。

3.5 filter(可选:单个或数组)

在向量检索前先用结构化/倒排过滤

  • 限定类目、状态、时间、地理范围等;
  • 只有通过过滤的文档才进入 kNN 候选与排序。

建议 :尽量把能过滤的条件都放进来,先减集合后做向量检索,性能与相关性都会更好。

3.6 similarity(可选:浮点)

直接作用于"向量相似度"本体的阈值,不同度量解释不同:

  • l2_norm(欧氏距离):半径阈值 ,仅返回在"半径=similarity"的超球体内的向量;值越小越严格
  • cosine / dot_product / max_inner_product:只返回相似度 ≥ similarity 的向量;值越大越严格

和最终 _score 的区别:similarity原始向量相似度的门槛;命中后文档还会按 similarity 计分并应用 boost,然后进入 Top-K。

调参技巧

  • 若召回太多噪声 ,适当提高 cosine/dot_product 的阈值;
  • l2_norm 时注意尺度(embedding 是否归一化)。

4. 进阶:量化向量的重排(rescore_vector

版本:Stack 9.1.0(9.0.0 为 preview)

仅对量化后的 dense_vector 有意义;非量化字段会忽略该项。

动机 :量化索引的近似搜索极快,但初始得分可能受量化误差影响。
方案 :先用近似索引取候选,再用原始向量更小集合做精排。

配置项:

  • oversample(必填,浮点):对 k 做过采样倍率。工作流:

    1. 按近似索引取 num_candidates
    2. 选出 k * oversample 个候选,用原始向量重算相似度;
    3. 重算后的 Top-K 作为最终结果。

经验值oversample2.0~4.0 常见。过大提升有限但开销明显;建议压测找平衡点。

5. 组合示例

5.1 kNN + 过滤(类目 & 地理)

http 复制代码
GET /poi/_search
{
  "retriever": {
    "knn": {
      "field": "embedding",
      "query_vector": [/* 768 dims */],
      "k": 50,
      "num_candidates": 500,
      "filter": [
        { "term":  { "category": "restaurant" } },
        { "range": { "rating": { "gte": 4.0 } } },
        { "geo_distance": { "distance": "5km", "location": { "lat": 37.78, "lon": -122.42 } } }
      ],
      "similarity": 0.7  // 仅对 cosine/dot_product 有意义;举例值
    }
  }
}

5.2 量化向量 + 过采样重排

http 复制代码
GET /docs/_search
{
  "retriever": {
    "knn": {
      "field": "emb_q8",            // 量化后的 dense_vector
      "query_vector": "0A0B0C...",  // 也可用 hex 向量
      "k": 20,
      "num_candidates": 400,
      "rescore_vector": {
        "oversample": 3.0           // 先取 60 再用原始向量精排出最终 20
      }
    }
  }
}

5.3 与其他 Retriever 组合(示意)

  • 首阶段:knn 召回语义近邻
  • 另一支:standard 倒排匹配(BM25 / multi_match)
  • 融合:rrf / linear
  • 二阶段:rescorer(可接 LTR / 语义 re-ranker)

组合写法见 Retriever 文档,这里不赘述。把 kNN 放进统一管线的收益,就是一次请求完成多路召回与融合。

6. 调优清单(Checklist)

  1. 字段准备dense_vector + 索引参数合理(HNSW 的 M/ef*)。
  2. 维度一致query_vector 与字段维度严格对齐。
  3. 候选规模num_candidates = k 的 10~30 倍起步,根据延迟预算逐步调大。
  4. 过滤优先:能过滤先过滤(类目/状态/时间/地理/安全域),缩小向量检索集合。
  5. 相似度阈 :合理用 similarity 做噪声门槛(尤其 cosine/dot_product)。
  6. 量化精排 :量化场景开启 rescore_vector,用 oversample 控误差。
  7. 多分片意识 :Top-K 是全局合并num_candidates分片级采样。
  8. 观测 :记录 took、候选规模、最终 k、命中率与点击/转化,形成离线-在线闭环。

7. 常见报错与排查

  • illegal_argument_exception: dimensions mismatch
    → 检查向量维度;embedding 模型升级后维度变化是高频来源。
  • num_candidates too small / k > num_candidates
    → 调整参数,满足约束(且 ≤ 10000)。
  • 结果偏"飘" (语义不稳)
    → 提高 num_candidates、设置 similarity、或在量化场景开启 rescore_vector
  • 延迟过高
    → 降低 num_candidates、先做更严格 filter、或优化向量索引参数(M/efConstruction)。

8. 小结

  • kNN retriever 把向量近邻召回收敛进统一的检索管线,与倒排、RRF/LTR/Rescorer 等协同非常自然;
  • 三要素:候选规模(num_candidates)过滤(filter)相似度阈(similarity)
  • 量化场景配上 rescore_vector.oversample ,在准确度与延迟之间找最优点。