use std::cmp::Ordering;
use ahash::{AHashMap, AHashSet};
pub const DEFAULT_RRF_K: f32 = 60.0;
pub const WEIGHT_EXACT: f32 = 2.0;
pub const WEIGHT_VECTOR: f32 = 1.0;
pub const WEIGHT_KEYWORD: f32 = 1.0;
pub const LANE_EXACT: &str = "exact";
pub const LANE_VECTOR: &str = "vector";
pub const LANE_KEYWORD: &str = "keyword";
pub struct FusionLane<'a> {
pub name: &'static str,
pub chunk_ids: &'a [String],
pub weight: f32,
}
impl<'a> FusionLane<'a> {
pub fn new(name: &'static str, chunk_ids: &'a [String], weight: f32) -> Self {
Self {
name,
chunk_ids,
weight,
}
}
}
pub struct FusedHit {
pub chunk_id: String,
pub score: f32,
pub lane_ranks: Vec<(&'static str, u32)>,
}
pub fn rrf_fuse_detailed(lanes: &[FusionLane<'_>], k: f32) -> Vec<FusedHit> {
#[derive(Default)]
struct Acc {
score: f32,
lane_ranks: Vec<(&'static str, u32)>,
}
let mut acc: AHashMap<&str, Acc> = AHashMap::new();
for lane in lanes {
let mut seen_in_lane: AHashSet<&str> = AHashSet::new();
for (rank0, chunk_id) in lane.chunk_ids.iter().enumerate() {
if !seen_in_lane.insert(chunk_id.as_str()) {
continue;
}
let rank = (rank0 + 1) as u32;
let entry = acc.entry(chunk_id.as_str()).or_default();
entry.score += lane.weight / (k + rank as f32);
entry.lane_ranks.push((lane.name, rank));
}
}
let mut fused: Vec<FusedHit> = acc
.into_iter()
.map(|(id, a)| FusedHit {
chunk_id: id.to_string(),
score: a.score,
lane_ranks: a.lane_ranks,
})
.collect();
fused.sort_by(|a, b| {
b.score
.partial_cmp(&a.score)
.unwrap_or(Ordering::Equal)
.then_with(|| a.chunk_id.cmp(&b.chunk_id))
});
fused
}
pub fn rrf_fuse(lanes: &[FusionLane<'_>], k: f32) -> Vec<(String, f32)> {
rrf_fuse_detailed(lanes, k)
.into_iter()
.map(|h| (h.chunk_id, h.score))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn ids(v: &[&str]) -> Vec<String> {
v.iter().map(|s| s.to_string()).collect()
}
#[test]
fn agreeing_lanes_rank_the_shared_top_first() {
let a = ids(&["h:1", "h:2", "h:3"]);
let b = ids(&["h:1", "h:3", "h:4"]);
let fused = rrf_fuse(
&[
FusionLane::new(LANE_KEYWORD, &a, 1.0),
FusionLane::new(LANE_VECTOR, &b, 1.0),
],
DEFAULT_RRF_K,
);
assert_eq!(fused[0].0, "h:1");
assert!(fused[0].1 > fused[1].1);
let uniq: std::collections::HashSet<&str> = fused.iter().map(|(id, _)| id.as_str()).collect();
assert_eq!(uniq.len(), 4);
}
#[test]
fn weight_boosts_a_lane_that_ranks_a_chunk() {
let exact = ids(&["h:def"]);
let keyword = ids(&["h:other", "h:def"]);
let fused = rrf_fuse(
&[
FusionLane::new(LANE_EXACT, &exact, WEIGHT_EXACT),
FusionLane::new(LANE_KEYWORD, &keyword, WEIGHT_KEYWORD),
],
DEFAULT_RRF_K,
);
assert_eq!(fused[0].0, "h:def", "exact-lane rank-1 with 2x weight must win");
}
#[test]
fn duplicate_within_lane_counts_once() {
let dupe = ids(&["h:1", "h:1", "h:1"]);
let single = ids(&["h:1"]);
let a = rrf_fuse(&[FusionLane::new(LANE_KEYWORD, &dupe, 1.0)], DEFAULT_RRF_K);
let b = rrf_fuse(&[FusionLane::new(LANE_KEYWORD, &single, 1.0)], DEFAULT_RRF_K);
assert_eq!(a.len(), 1);
assert_eq!(a[0].1, b[0].1, "repeats of a chunk within a lane must not stack");
}
#[test]
fn empty_lanes_produce_empty_output() {
let empty: Vec<String> = Vec::new();
assert!(rrf_fuse(&[FusionLane::new(LANE_KEYWORD, &empty, 1.0)], DEFAULT_RRF_K).is_empty());
assert!(rrf_fuse(&[], DEFAULT_RRF_K).is_empty());
}
#[test]
fn equal_scores_break_ties_by_chunk_id_ascending() {
let a = ids(&["h:zzz"]);
let b = ids(&["h:aaa"]);
let fused = rrf_fuse(
&[
FusionLane::new(LANE_KEYWORD, &a, 1.0),
FusionLane::new(LANE_VECTOR, &b, 1.0),
],
DEFAULT_RRF_K,
);
assert_eq!(fused[0].0, "h:aaa");
assert_eq!(fused[1].0, "h:zzz");
}
#[test]
fn detailed_fusion_records_per_lane_ranks_in_lane_order() {
let exact = ids(&["h:9", "h:1"]);
let keyword = ids(&["h:1"]);
let fused = rrf_fuse_detailed(
&[
FusionLane::new(LANE_EXACT, &exact, WEIGHT_EXACT),
FusionLane::new(LANE_KEYWORD, &keyword, WEIGHT_KEYWORD),
],
DEFAULT_RRF_K,
);
let h1 = fused.iter().find(|h| h.chunk_id == "h:1").expect("h:1 present");
assert_eq!(h1.lane_ranks, vec![(LANE_EXACT, 2), (LANE_KEYWORD, 1)]);
let h9 = fused.iter().find(|h| h.chunk_id == "h:9").expect("h:9 present");
assert_eq!(
h9.lane_ranks,
vec![(LANE_EXACT, 1)],
"single-lane hit records only that lane"
);
}
}