目录
[核心:一条 DSL 融合三路信号](#核心:一条 DSL 融合三路信号 "#t2")
[RRF 为什么有效](#RRF 为什么有效 "#t3")
[全链路都在 Elastic 里](#全链路都在 Elastic 里 "#t4")
用 Elasticsearch 的 RRF 融合检索,把矿物鉴定准确率从 36% 拉到 92%

一块石头引出的问题
地质队员在野外捡到一块石头,手里只有:一张照片、几条肉眼观察 ------ 颜色、条痕、硬度、晶系、光泽、比重。问它是 98 种矿物里的哪一种。
这题看着简单,坑在单一模态谁都不够:
- 只看照片:玛瑙、玉髓、碧玉长得几乎一样,光学特征高度重叠;
- 只看属性文字:「三方晶系 + 硬度 7 + 白条痕 + 玻璃光泽」这一串,被几十种矿物共享。
任何单路检索都会在某一类矿物上翻车。于是我把这题做成了一个可以公开验证的实验:同一套题、同一个判分器、同一个大模型,只改「喂给模型的检索证据」,看作答准确率怎么变。
结论一句话:

头条数字:公开榜单上的检索消融
50 道题,同一个 qwen-plus,只变检索配置,四个方案同台 PK:
| 检索配置 | 作答准确率 | vs 闭卷 |
|---|---|---|
| 闭卷(裸 Qwen,无检索) | 36.0% | --- |
| 图像单路(jina-clip-v2 kNN) | 48.0% | +12 |
| BM25 单路(属性文字) | 56.0% | +20 |
| RRF 融合(BM25 + 图像 kNN + 硬度过滤) | 92.0% | +56 ✅ |
▶ 这不是嘴上说说,是公开榜单可点进每个 case 看判分的 :
Mineral Identification from Field Observations · Trapstreet
上图为 trapstreet 公开榜实况:四行分别是闭卷 / 图像单路 / BM25 单路 / RRF 融合,按 SCORE 降序,RRF 融合 0.92 稳居第一。
再给一层不经过大模型的纯检索证据------2,749 条查询的检索命中率:
| 指标 | 图像单路 | 文本单路 | RRF 融合 |
|---|---|---|---|
| top-1 | 20.8% | 23.9% | 53.3% (+29.4) |
| top-3 | 37.9% | 28.0% | 77.5% |
两层数字互相印证:RRF 不是「多喂点上下文」的玄学,而是检索命中率实打实翻倍 → 作答准确率跟着抬升。
核心:一条 DSL 融合三路信号
这是整个方案里最想给 Elastic 团队看的部分。融合图像、文字、结构化过滤,在 Elasticsearch 里不需要自己写融合逻辑、不需要两套系统 ,一条 rrf retriever 就搞定:
bash
`
1. GET minerals-images/_search
2. {
3. "retriever": {
4. "rrf": {
5. "retrievers": [
6. {
7. "standard": {
8. "query": {
9. "multi_match": {
10. "query": "trigonal; hardness 7; white streak; vitreous luster",
11. "fields": ["props_text", "description", "name^2"]
12. }
13. }
14. }
15. },
16. {
17. "knn": {
18. "field": "image_vector",
19. "query_vector": [/* jina-clip-v2 1024 维查询向量 */],
20. "k": 100,
21. "num_candidates": 400
22. }
23. }
24. ],
25. "rank_window_size": 100,
26. "rank_constant": 20,
27. "filter": [
28. { "range": { "hardness_min": { "lte": 5.5 } } },
29. { "range": { "hardness_max": { "gte": 5.5 } } }
30. ]
31. }
32. }
33. }
`AI写代码
一个查询里同时做了三件事:
- BM25 文本召回:野外观察属性 → props_text 全文匹配;
- 跨模态图像 kNN:jina-clip-v2 把图像和文字编码到同一个 1024 维空间,所以文字线索能直接 kNN 搜标本照片;
- 结构化硬度过滤:hardness 区间做物理约束,把不可能的候选直接砍掉。
三路结果由 RRF 融合排序,rank_constant 和 rank_window_size 两个旋钮即可调融合行为。没有胶水代码,没有第二个向量库 。
RRF 为什么有效
Reciprocal Rank Fusion 的融合分只看排名、不看各路原始分数的量纲------这正是它稳的原因:BM25 的分数和向量余弦相似度根本不在一个尺度上,强行加权反而容易被某一路带偏。RRF 只问「你在每一路里排第几」:

其中
是 rank_constant(本项目取 20),
是文档
在第
路检索里的排名。
直觉:一个候选只要在多路里都排得靠前,融合分就高。玛瑙这种「图像混、文字也混」的难题,恰恰是在「图像一路排前 + 属性一路排前 + 硬度合法」三重同时命中时被 RRF 顶到第一------这就是单路做不到、融合能赢的地方。
全链路都在 Elastic 里
不只是检索。连大模型作答 都走 Elasticsearch 的 _inference 推理端点------检索、推理、评测一条链路,不出 Elastic 生态:


作答调用同样是一个 ES 请求:
bash
`
1. POST /_inference/completion/qwen-plus
2. { "input": "根据以下检索到的候选证据,判断矿物种名......" }
`AI写代码
本机零模型、零额外服务------检索引擎顺手把 LLM 推理也托管了。对做 Agent 的人来说,这意味着 RAG 的两半(检索 + 生成)可以在同一套鉴权、同一个端点里闭环。
完全可复现(欢迎大家了解下trapstreet亲自跑)
这套结果不是本地截图,是任何人都能重跑的。仓库已内置 trapstreet CLI 配置,克隆下来三行命令复现榜上任意一行:
bash
`
1. git clone https://github.com/Zhuaiz/elastic-mineral-hackson
2. cd elastic-mineral-hackson
3. cp .env.example .env # 已内置公开只读 ES 端点 + 限权 key
4. pip install -r trap/solutions/requirements.txt
6. tp run mineral-rrf # 满配 RRF → 0.92 (46/50)
7. tp run mineral-closed-book # 裸 Qwen → 0.36 (18/50)
8. tp run mineral-bm25 # BM25 单路 → 0.56 (28/50)
9. tp run mineral-image # 图像单路 → 0.48 (24/50)
`AI写代码
- 判分完全确定:committed 的作答文件就是榜上那批 run 的原始答案,无凭证即可本地重判出分毫不差的 36/48/56/92;
- 检索完全确定:题面、索引、图像查询向量都随仓库提交;
- 作答近似确定:qwen-plus 用 temperature=0 贪心解码,逐题重跑一致,个别 case 可能有模型侧 ±1~2 题的抖动------曲线形状(闭卷 < 单路 < RRF)稳定复现。
vbnet
`复现只依赖一个只读限权 key(read on minerals-* + monitor_inference),删不了写不了集群任何东西------公开安全。`AI写代码
小结
| 维度 | 这个方案怎么用 Elastic |
|---|---|
| 多模态融合 | 一条 RRF retriever 融合 BM25 + 图像 kNN + 结构化过滤 |
| 跨模态检索 | jina-clip-v2 图文共享同一向量空间,文字线索可直接检索图片 |
| 生成 | 使用 _inference/completion 端点托管 qwen-plus 生成回答 |
| 可信度 | 检索命中率 Top-1 翻倍(23.9% → 53.3%),下游问答准确率提升 56 个百分点 |
| 可复现 | 提供公开 Elasticsearch 端点,使用 tp run 可一键重现实验 |
总结 :矿物鉴定这题证明了 Elasticsearch 的 rrf 融合检索不是锦上添花,而是把一个单模态做不动的任务(36%)直接拉到可用级别(92%)的关键------而且整条 RAG 链路(检索 + 推理 + 评测)都能收在 Elastic 生态里闭环,如果样本量更多的话,结果应该会变得更好。感谢数据来源:www.mindat.org/。
🔗 项目地址:github.com/Zhuaiz/elas...
🏆 公开榜单:trapstreet.run/tasks/miner...
致敬 Elastic 布道的刘老师,提供交流学习的平台:
🔗 刘老师仓库:github.com/liu-xiao-gu...
