犀牛鸟 2026 研究笔记 estelledc.github.io

Ch25: RRF 融合与复合 Rerank——源码与调参

Part 8: WeKnora 源码走读 前置:Ch24 三路检索 后续:Ch26 知识图谱 PMI 源码


结论先行:RRF 解决 分数不可比;复合 Rerank 解决 排对了但还不够细。大师要能改 k、能解释三信号权重、能用 Ch20 证明改动有效。

一、RRF 源码心智模型

\[\text{RRF}(d) = \sum_{r \in \text{routes}} \frac{1}{k + \text{rank}_r(d)}\]

$k=60$ 时:排名第 1 得 $1/61$,排名靠后衰减;未召回的路不参与

func RRF(fused map[string]float64, chunkID string, rank int, k int) {
    if rank <= 0 { return }
    fused[chunkID] += 1.0 / float64(k+rank)
}

func Fuse(allRoutes [][]RetrievalHit, k int) []ScoredChunk {
    scores := map[string]float64{}
    for _, route := range allRoutes {
        for i, hit := range route {
            RRF(scores, hit.ChunkID, i+1, k)
        }
    }
    return sortByScore(scores)
}

调参直觉

k 效果
小 (20) 更信 top 排名,后排几乎无贡献
大 (60) 默认,平衡
更大 弱路排名靠后也有 voice

二、复合 Rerank 公式(源码对齐)

\[final = 0.6 \cdot s_{model} + 0.3 \cdot s_{base} + 0.1 \cdot s_{source}\]
信号 来源 防什么失败
$s_{model}$ Cross-Encoder 语义相关度
$s_{base}$ RRF 分归一化 Rerank 模型域外术语失误
$s_{source}$ 摄入元数据 论坛帖压过官方 doc

rerank/ 包时找 CompositeReranker.Score——确认权重是否可配置(feature 机会)。


三、常见 bug 模式

现象 可能根因
精确词查不到 BM25 未进 RRF / 分词丢词
相关但排后 Rerank 模型分低且 base 权重不够
旧文档排前 缺时效维度;source 未区分版本
三路结果重复计分 同 chunk 多路 rank 应 累加 RRF(正确)vs doc_id 去重策略错误

四、消融实验(大师必做)

k 或 Rerank 权重后,跑 Ch20 的 10 条 smoke:

# 伪 workflow
for config in baseline k40 k80 w0.5; do
  WEKNORA_RRF_K=... python eval_weknora_ragas.py
done

PR 描述必须带 Context Recall / Precision 变化表——评审认数字。


五、与加权融合(Dify)代码级对比

Dify 混合检索:score = w1*bm25 + w2*cosine —— 需归一化分数尺度。

RRF:只用 rank —— 对分数分布鲁棒,但丢失「第一名领先第二名多少」的信息。

WeKnora 用 RRF + Rerank 二级精排 = rank 融合 + 语义精排 分工。


章末 · 大师自检


延伸阅读