# -*- coding: utf-8 -*- """RRF(Reciprocal Rank Fusion)融合多路排名。 RRF 只看「排名」不看「分数量纲」,天然解决 BM25 分数与余弦相似度不可比的问题: fused(d) = Σ_method w_method * 1 / (k + rank_method(d)) k 越大,头部名次的权重差异越平缓(经验默认 60)。 """ from __future__ import annotations def rrf(rankings: dict[str, list[str]], weights: dict[str, float], k: int = 60) -> list[tuple[str, float]]: """rankings: {method: [name 按相关性降序]};返回 [(name, fused_score)] 降序。""" score: dict[str, float] = {} for method, names in rankings.items(): w = weights.get(method, 1.0) for rank, name in enumerate(names, start=1): score[name] = score.get(name, 0.0) + w * (1.0 / (k + rank)) return sorted(score.items(), key=lambda kv: kv[1], reverse=True)