use crate::config::Config;
use crate::index::Index;
use crate::rank::{cmp_score_desc, Hit};
const AGREEMENT_SLACK: f32 = 0.03;
pub fn is_ambiguous(hits: &[Hit], cfg: &Config) -> bool {
let Some(top) = hits.first() else {
return false;
};
if top.score < cfg.recall_floor {
return false; }
!confident_winner(hits, cfg)
}
pub fn confident_winner(hits: &[Hit], cfg: &Config) -> bool {
if hits.is_empty() {
return false;
}
let mut cos: Vec<f32> = hits.iter().map(|h| h.cosine).collect();
cos.sort_by(|a, b| cmp_score_desc(*a, *b));
let c1 = cos[0];
let c2 = cos.get(1).copied().unwrap_or(0.0);
c1 >= cfg.high_conf && (c1 - c2) >= cfg.clear_gap
}
pub fn rerank(hits: &[Hit], idx: &Index, prompt: &str, cfg: &Config) -> Option<Vec<Hit>> {
#[cfg(feature = "fastembed")]
{
fast::rerank(hits, idx, prompt, cfg)
}
#[cfg(not(feature = "fastembed"))]
{
let _ = (hits, idx, prompt, cfg);
None
}
}
pub fn passes(reranked: &[Hit], cfg: &Config) -> Vec<Hit> {
let floor = cfg.min_similarity - AGREEMENT_SLACK;
let eligible: Vec<&Hit> = reranked
.iter()
.filter(|h| h.stage1_score() >= floor)
.collect();
let best = eligible
.first()
.map(|h| h.score)
.unwrap_or(f32::NEG_INFINITY);
eligible
.into_iter()
.filter(|h| h.score >= cfg.rerank_min && h.score >= best - cfg.rerank_margin)
.cloned()
.collect()
}
#[cfg(feature = "fastembed")]
mod fast {
use super::*;
use fastembed::{RerankInitOptions, RerankerModel, TextRerank};
use std::sync::OnceLock;
fn model() -> Option<&'static TextRerank> {
static MODEL: OnceLock<Option<TextRerank>> = OnceLock::new();
MODEL
.get_or_init(|| {
TextRerank::try_new(
RerankInitOptions::new(RerankerModel::JINARerankerV1TurboEn)
.with_cache_dir(crate::paths::model_cache_dir())
.with_show_download_progress(false),
)
.ok()
})
.as_ref()
}
pub fn rerank(hits: &[Hit], idx: &Index, prompt: &str, cfg: &Config) -> Option<Vec<Hit>> {
let reranker = model()?;
let cands: Vec<&Hit> = hits.iter().take(cfg.rerank_top_k).collect();
if cands.is_empty() {
return None;
}
let docs: Vec<String> = cands
.iter()
.map(|h| {
idx.get(&h.id)
.map(crate::index::Entry::doc_text)
.unwrap_or_default()
})
.collect();
let results = reranker
.rerank(prompt.to_string(), docs, false, None)
.ok()?;
let out = results
.into_iter()
.map(|r| {
let src = cands[r.index];
Hit {
score: r.score,
..src.clone()
}
})
.collect();
Some(out)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn cfg() -> Config {
Config {
recall_floor: 0.45,
high_conf: 0.75,
clear_gap: 0.12,
rerank_min: -2.5,
rerank_margin: 2.0,
rerank_top_k: 12,
..Default::default()
}
}
fn hit(id: &str, score: f32) -> Hit {
Hit {
id: id.to_string(),
name: id.to_string(),
cosine: score,
context: 0.0,
file: 0.0,
project: 0.0,
keyword: 0.0,
phrase: 0.0,
score,
}
}
fn rhit(id: &str, logit: f32, cosine: f32) -> Hit {
Hit {
id: id.to_string(),
name: id.to_string(),
cosine,
context: 0.0,
file: 0.0,
project: 0.0,
keyword: 0.0,
phrase: 0.0,
score: logit,
}
}
#[test]
fn nothing_relevant_is_not_ambiguous() {
assert!(!is_ambiguous(&[hit("a", 0.40), hit("b", 0.38)], &cfg()));
}
#[test]
fn confident_lone_winner_is_not_ambiguous() {
assert!(!is_ambiguous(&[hit("a", 0.82), hit("b", 0.60)], &cfg()));
}
#[test]
fn clustered_peers_are_ambiguous() {
assert!(is_ambiguous(&[hit("a", 0.80), hit("b", 0.78)], &cfg()));
}
#[test]
fn muddy_band_is_ambiguous() {
assert!(is_ambiguous(&[hit("a", 0.62), hit("b", 0.55)], &cfg()));
}
#[test]
fn empty_is_not_ambiguous() {
assert!(!is_ambiguous(&[], &cfg()));
}
#[test]
fn passes_keeps_top_and_rejects_negatives() {
let reranked = vec![
rhit("a", 1.10, 0.80),
rhit("b", -0.30, 0.70),
rhit("c", -3.90, 0.65),
];
let got: Vec<String> = passes(&reranked, &cfg())
.into_iter()
.map(|h| h.id)
.collect();
assert_eq!(got, ["a", "b"]); }
#[test]
fn passes_drops_all_when_best_is_noise() {
let reranked = vec![rhit("a", -2.83, 0.70), rhit("b", -3.94, 0.66)];
assert!(passes(&reranked, &cfg()).is_empty()); }
#[test]
fn passes_rejects_subfloor_stage1_resurrection() {
let reranked = vec![rhit("ghost", 1.50, 0.20), rhit("real", 0.40, 0.72)];
let got: Vec<String> = passes(&reranked, &cfg())
.into_iter()
.map(|h| h.id)
.collect();
assert_eq!(got, ["real"]); }
#[test]
fn passes_subfloor_leader_does_not_drag_in_peers() {
let cfg = cfg(); let reranked = vec![rhit("ghost", 2.00, 0.20), rhit("real", -0.40, 0.72)];
let got: Vec<String> = passes(&reranked, &cfg).into_iter().map(|h| h.id).collect();
assert_eq!(got, ["real"]); }
}