use std::sync::Arc;
use crate::store::memory::SearchResult;
use crate::store::search::SearchWeights;
pub fn rerank_search_results(
query: &str,
results: &mut Vec<SearchResult>,
engine: Option<&Arc<crate::embeddings::engine::EmbeddingEngine>>,
weights: &SearchWeights,
) {
if results.is_empty() {
return;
}
let engine = match engine {
Some(e) => e,
None => return, };
let query_embedding = if let Ok(rt) = tokio::runtime::Handle::try_current() {
let engine_clone = engine.clone();
let query_owned = query.to_string();
tokio::task::block_in_place(|| {
rt.block_on(async { engine_clone.embed(&query_owned).await })
})
} else {
if let Ok(rt) = tokio::runtime::Runtime::new() {
let engine_clone = engine.clone();
let query_owned = query.to_string();
rt.block_on(async { engine_clone.embed(&query_owned).await })
} else {
return;
}
};
let query_embedding = match query_embedding {
Ok(e) => e,
Err(_) => return,
};
for result in results.iter_mut() {
if let Some(cosine) = result.cosine_score {
let semantic_base = f64::from(cosine) * weights.semantic;
let title_text = &result.memory.title;
let content_text = &result.memory.content;
let refined_semantic = if let Some(ref engine) = engine {
if let Ok(content_embedding) = rt_block_on_embed(engine, content_text) {
let title_sim = crate::embeddings::similarity::cosine_similarity(
&query_embedding,
&content_embedding,
);
let blended = 0.3 * title_sim + 0.7 * cosine;
f64::from(blended) * weights.semantic
} else {
semantic_base
}
} else {
semantic_base
};
result.score = result.score * 0.4 + refined_semantic * 0.6;
}
}
results.sort_by(|a, b| {
b.score
.partial_cmp(&a.score)
.unwrap_or(std::cmp::Ordering::Equal)
});
}
fn rt_block_on_embed(engine: &crate::embeddings::engine::EmbeddingEngine, text: &str) -> Result<Vec<f32>, crate::error::MnemeError> {
if let Ok(rt) = tokio::runtime::Handle::try_current() {
let engine_clone = engine.clone();
let text_owned = text.to_string();
tokio::task::block_in_place(|| {
rt.block_on(async { engine_clone.embed(&text_owned).await })
})
} else if let Ok(rt) = tokio::runtime::Runtime::new() {
let engine_clone = engine.clone();
let text_owned = text.to_string();
rt.block_on(async { engine_clone.embed(&text_owned).await })
} else {
Err(crate::error::MnemeError::Embeddings("no tokio runtime".to_string()))
}
}