纯向量检索漏掉了「Transformer 为什么是大模型的基石」
一个真实的跨主题漏检:为什么语义近邻不等于答案就在附近,以及我最终为什么选择自研 BM25 + 向量加权融合 + Rerank,代价是什么、边界在哪里。
- 检索
- BM25
- 向量检索
- RAG
「语义检索比关键词检索更先进」这句话是对的,但它不等于「关键词检索可以丢掉」。DocWise 的检索层从纯向量改成混合检索,起因是一个很具体的失败:在 top-1 严格模式下,问题「Transformer 为什么是大模型的基石」被检索结果带偏了 —— 召回的第一条是语义相近的「大模型笔记」,而不是真正回答这个问题的内容。
这类问题有一个特点:肉眼很难发现,只有靠评测集逐题对比才暴露出来 —— 这也是我发现它的方式。下面的事实与测量方式来自项目记录,机制解释会标注为「分析」。
问题:不是崩溃,而是「看起来相关」
分析:向量的近邻是「语义相近」,不是「答案在这里」
- 主题相近会被拉近:两段都在讲「大模型」,在向量空间里天然相似 —— 即使其中一段并没有回答「为什么它是基石」。
- 精确词命中被稀释:问题里的关键实体(Transformer)只贡献了一部分相似度,不足以把真正相关的那段推到第一位。
BM25 的性质正好相反:它不关心语义,只关心词命中与词频。跨主题的精确词命中,恰恰是它的强项。我当时的判断也落在同一方向:BM25 的精确关键词命中能补上纯向量的跨主题漏检。(上面两条是分析,这一条结论来自项目记录。)
方案:两路召回 → 加权融合 → 精排
- BM25 一路:对查询做中文分词(jieba,可回退到零依赖方案),按关键词召回。
- 向量一路:用 bge-m3 生成嵌入,做语义召回。
- 加权融合:把两路得分归一化后加权相加 —— 权重可调、可解释。
- Rerank 精排:对融合后的候选做一次重排,把真正相关的推到最前。
text
query
├─ BM25(分词后的 query) → 候选 + 得分
└─ cosine(embed(query)) → 候选 + 得分
↓ 归一化 + 加权融合(去重、合并)
↓ Rerank
top-k → 组装 Prompt为什么我选自研,而不是引入检索框架
- 考虑过的三个方向:继续用纯向量检索并调参;引入现成的检索框架;自己实现 BM25 与向量的加权融合。
- 我最终选择的:自研轻量 BM25 + 向量混合检索,并加一层 Rerank。
- 理由是:BM25 的精确关键词命中能补上纯向量的跨主题漏检;自己实现之后,每一层的原理与权重都能讲清楚、能按评测结果调整。
- 代价是:需要自己维护检索实现与调参,而不是依赖框架的默认行为。
验证:同一套测试集下的前后对比
判断这次改动有没有用,我没有靠「感觉更准了」,而是用固定测试集对比:52 题 / 20 篇语料 / 85 块,四档检索配置,bge-m3 真实嵌入。
| 指标 | 结果 | 测量方式 |
|---|---|---|
| 检索命中率(top-1) | 纯向量 96.2% → 混合检索 98.1% | 52 题测试集 / 20 篇语料 / 85 块,bge-m3 真实嵌入,四档检索配置对比 |
| 单次问答耗时 | 约 1.9–2.3 s | 实测均值 |
边界:98.1% 之后我还留着什么
即使在混合检索之后,我仍然保留了 2 道所有检索配置都会漏的题,没有把它们从结果里删掉。把这些题写出来,比只展示成功案例更能说明方案的适用范围 —— 这也是我在项目里最想保留的一条习惯:边界要主动暴露。
复盘
- 我现在更坚持「先量化,再优化」:没有 52 题测试集,这个漏检只会停留在「感觉有时候答不准」。
- 两路召回是互补,不是折中:语义召回覆盖表达差异,关键词召回覆盖精确命中。
- 代价要提前写下来:自研检索意味着自己维护调参与正确性验证;如果只是演示级需求,用现成框架更省时间。
完整的检索链路(标题感知分块 800/100、Rerank、引用溯源、strict / chat 双模式)与实测数据在项目页里:查看 DocWise 项目详情。
韦坤计算机科学本科生 · 后端开发 / AI 应用开发方向
相关项目
上传文档即可问答的 RAG 平台:标题感知分块 + BM25/向量混合检索 + Rerank + SSE 流式回答,自带 52 题评测体系与 Agent 工具调用。
- Python 3.11+
- FastAPI(异步)
- httpx
- 还有 21 项技术
相关文章
忠实度 0.25 → 0.99:一次先怀疑评测、再怀疑模型的排查
复盘约 3 分钟忠实度只有 0.25,与人工观察明显不符。这是一次把嫌疑人先放在评测口径上的排查复盘:引用预览被截断污染了判分上下文,以及为什么我坚持给 RAG 项目先建可信的评测,再谈优化。