use crate::embeddings::{models::Reranker, RerankScore, RerankerStatus};
pub struct RerankStage {
inner: Option<Reranker>,
}
impl RerankStage {
pub fn try_new() -> Self {
match Reranker::new() {
Ok(r) => Self { inner: Some(r) },
Err(e) => {
tracing::warn!(
"reranker load failed; pipeline will run in ANN-only fallback mode: {}",
e
);
Self { inner: None }
}
}
}
pub fn is_active(&self) -> bool {
self.inner.is_some()
}
pub fn rerank(
&self,
query: &str,
documents: Vec<String>,
) -> (Vec<RerankScore>, RerankerStatus) {
let n = documents.len();
let Some(reranker) = &self.inner else {
return (ann_order(n), RerankerStatus::Fallback);
};
match reranker.rerank(query, documents) {
Ok(scores) => (scores, RerankerStatus::Active),
Err(e) => {
tracing::warn!("rerank inference failed; falling back to ANN order: {}", e);
(ann_order(n), RerankerStatus::Fallback)
}
}
}
}
fn ann_order(n: usize) -> Vec<RerankScore> {
(0..n)
.map(|i| RerankScore {
document_idx: i,
score: 0.0,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ann_order_empty_returns_empty() {
let result = ann_order(0);
assert!(result.is_empty());
}
#[test]
fn ann_order_returns_sequential_indices() {
let result = ann_order(5);
assert_eq!(result.len(), 5);
for (i, score) in result.iter().enumerate() {
assert_eq!(
score.document_idx, i,
"index {i} should map to document_idx {i}"
);
}
}
#[test]
fn ann_order_scores_are_all_zero() {
let result = ann_order(10);
for score in &result {
assert_eq!(score.score, 0.0, "fallback scores must be 0.0");
}
}
#[test]
fn ann_order_single_element() {
let result = ann_order(1);
assert_eq!(result.len(), 1);
assert_eq!(result[0].document_idx, 0);
assert_eq!(result[0].score, 0.0);
}
#[test]
fn rerank_stage_inactive_reports_false() {
let stage = RerankStage::try_new();
if !stage.is_active() {
let docs = vec!["doc1".to_string(), "doc2".to_string(), "doc3".to_string()];
let (scores, status) = stage.rerank("query", docs);
assert_eq!(status, RerankerStatus::Fallback);
assert_eq!(scores.len(), 3);
for (i, s) in scores.iter().enumerate() {
assert_eq!(s.document_idx, i);
assert_eq!(s.score, 0.0);
}
}
}
}