use crate::memory::score::embed::{cosine_similarity, Embedder};
use super::types::RetrievalHit;
pub(crate) async fn rerank_by_semantic_similarity(
embedder: &dyn Embedder,
query: &str,
hits: Vec<RetrievalHit>,
embeddings: Vec<Option<Vec<f32>>>,
) -> Vec<RetrievalHit> {
debug_assert_eq!(hits.len(), embeddings.len());
let query_vec = match embedder.embed(query).await {
Ok(v) => v,
Err(_) => return hits,
};
let mut decorated: Vec<(f32, bool, RetrievalHit)> = hits
.into_iter()
.zip(embeddings)
.map(|(h, emb)| match emb {
Some(v) if v.len() == query_vec.len() => {
let sim = cosine_similarity(&query_vec, &v);
(sim, true, h)
}
_ => (f32::NEG_INFINITY, false, h),
})
.collect();
decorated.sort_by(|a, b| match (a.1, b.1) {
(true, false) => std::cmp::Ordering::Less,
(false, true) => std::cmp::Ordering::Greater,
_ => {
b.0.partial_cmp(&a.0)
.unwrap_or(std::cmp::Ordering::Equal)
.then_with(|| b.2.time_range_end.cmp(&a.2.time_range_end))
}
});
decorated.into_iter().map(|(_, _, h)| h).collect()
}