Elasticsearch 混合检索一句 `retriever.rrf`,把语义召回与关键词召回融合到极致

1. 为什么要混合检索

  • 全文检索(Lexical)

    BM25 基于词频 & 逆文档频率,适合 代码、SKU、专用名词 等需要精确匹配的场景。

  • 语义检索(Semantic)

    稀疏/稠密向量捕捉上下文与同义词,能理解 自然语言问题,召回"不含关键词但含同义含义"的文档。

痛点 :只用其中一种都容易漏召回或误召回;混合检索(Hybrid)把两种结果 加权融合,既保留精确命中,又能补充语义相关。

2. 先决条件与模型

组件 版本建议 作用
Elasticsearch ≥ 8.11 内置 semantic_text 字段 & RRF
ELSER v2 Inference API 默认稀疏向量模型,零样本即用
Kibana 同版本 Data Visualizer 上传 TSV

Serverless / Cloud 已默认带 Inference Endpoint;自托管需先 POST _ml/inference/<model_id>

3. 创建"双通道"Mapping

http 复制代码
PUT /semantic-embeddings
{
  "mappings": {
    "properties": {
      "semantic_text": {           # 语义向量通道
        "type": "semantic_text"
      },
      "content": {                 # 原文关键词通道
        "type": "text",
        "copy_to": "semantic_text" # 自动送进向量流水线
      }
    }
  }
}
  • semantic_text 字段写入即异步调用 Inference 生成 稀疏向量
  • copy_to 可保留原文供 BM25,也让模型见到完整上下文

4. 数据落盘:上传 MS MARCO 子集

  1. 下载 msmarco-passagetest2019-top1000.tsv
  2. Kibana ➜ Machine Learning ➜ Data Visualizer
  3. Override settings :第一列 id,第二列 content
  4. Import 为 test-data(≈ 18 万行)

5. reindex 批量补嵌入

http 复制代码
POST /_reindex?wait_for_completion=false
{
  "source": {
    "index": "test-data",
    "size" : 500                # 小 batch 快速观察
  },
  "dest": { "index": "semantic-embeddings" }
}
  • 拿到 task_id,可 GET _tasks/<id> 实时看进度
  • 数据量大可先小批量测试,确认 OK 再全量

提示 :老索引若已在生产,可零停机开一个临时别名,用 reindex + alias swap 平滑切换。


6. Query DSL:RRF 融合

http 复制代码
GET /semantic-embeddings/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        {                   # 1⃣ 关键词 BM25
          "standard": {
            "query": {
              "match": {
                "content": "How to avoid muscle soreness while running?"
              }
            }
          }
        },
        {                   # 2⃣ 语义稀疏向量
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_text",
                "query": "How to avoid muscle soreness while running?"
              }
            }
          }
        }
      ],
      "rank_constant": 60   # 可选,默认 60,调大则更强调高位文档
    }
  },
  "size": 10                # 返回融合后前 10
}

返回字段亮点

jsonc 复制代码
"_score": 0.0328,     // RRF 加权得分
"_rank" : 1,          // 融合后排名
"semantic_text.inference.embeddings": { ... } // 稀疏向量局部

7. ES|QL 写法简例

esql 复制代码
FROM semantic-embeddings
| RETRIEVE RRF(
    STANDARD(match(content, "muscle soreness running")),
    STANDARD(semantic(semantic_text, "muscle soreness running"))
  )
| LIMIT 10

ES|QL 的 RETRIEVE RRF() 语法目前仍在 8.x 试验标志下,若未开启可继续用 DSL。

8. 常见坑 & 调优

问题 解决方案
语义结果不佳 确认写入是否触发 Inference;ELSER 支持 ml.inference_id 显式指定
rank_constant 怎么调? 一般 10--100 之间实验: • 调大 ➜ 关键词靠前 • 调小 ➜ 语义影响更大
条目多但 _score 很低 属 RRF 正常特性,可忽略,但排序仍正确
reindex 太慢 利用 pipeline + max_docs 分段;或先临时 alias 新写旧读,后台慢迁移

9. 小结

混合搜索流程三步走:

  1. 双字段索引 ------ content 做 BM25,semantic_text 存稀疏向量
  2. 批量重建嵌入 ------ 用 reindex 触发 Inference Pipeline
  3. RRF 融合查询 ------ retriever.rrf 同时喂 BM25 与语义查询

这样即可在 Elastic Stack 中零依赖外部向量库,享受 "含义 + 关键词" 一拍即合的搜索体验。试试把你公司的 FAQ、文档、产品描述喂给它,你会惊喜发现搜索结果瞬间「既准又全」!

相关推荐
lisw051 天前
AIoT(人工智能物联网):融合范式下的技术演进、系统架构与产业变革
大数据·人工智能·物联网·机器学习·软件工程
mtouch3331 天前
GIS+VR地理信息虚拟现实XR MR AR
大数据·人工智能·ar·无人机·xr·vr·mr
数据智能老司机1 天前
数据工程设计模式——实时摄取与处理
大数据·设计模式·架构
Hello.Reader1 天前
Flink 内置 Watermark 生成器单调递增与有界乱序怎么选?
大数据·flink
工作中的程序员1 天前
flink UTDF函数
大数据·flink
工作中的程序员1 天前
flink keyby使用与总结 基础片段梳理
大数据·flink
Hy行者勇哥1 天前
数据中台的数据源与数据处理流程
大数据·前端·人工智能·学习·个人开发
00后程序员张1 天前
RabbitMQ核心机制
java·大数据·分布式
AutoMQ1 天前
10.17 上海 Google Meetup:从数据出发,解锁 AI 助力增长的新边界
大数据·人工智能