mod ranker;
mod segment;
pub(crate) use ranker::RankMode;
const MIN_SEGMENTS: usize = 3;
const MAX_SEGMENTS: usize = 512;
#[cfg(feature = "embeddings")]
#[must_use]
pub(crate) fn rank_and_squeeze(
text: &str,
budget_chars: usize,
mode: RankMode,
anchor: Option<&str>,
) -> Option<String> {
let engine = crate::tools::ctx_knowledge::embeddings::embedding_engine_nonblocking()?;
let segs = segment::segment(text);
if segs.len() < MIN_SEGMENTS || segs.len() > MAX_SEGMENTS {
return None;
}
let texts: Vec<&str> = segs.iter().map(|s| s.text.as_str()).collect();
let embs = engine.embed_batch(&texts).ok()?;
if embs.len() != segs.len() {
return None;
}
let anchor_emb = match mode {
RankMode::Query => Some(engine.embed_query(anchor?).ok()?),
RankMode::Centrality => None,
};
let kept = ranker::select(&segs, &embs, mode, anchor_emb.as_deref(), budget_chars);
if kept.is_empty() {
return None;
}
let selected: Vec<&segment::Segment> = kept.iter().map(|&i| &segs[i]).collect();
let out = segment::reassemble(&selected);
(out.len() < text.len()).then_some(out)
}
#[cfg(not(feature = "embeddings"))]
#[must_use]
pub fn rank_and_squeeze(
_text: &str,
_budget_chars: usize,
_mode: RankMode,
_anchor: Option<&str>,
) -> Option<String> {
None
}
#[cfg(test)]
mod tests;