use tokenizers::Encoding;
use super::TextCrossEncoder;
use crate::error::CanddingError;
use crate::error::Result;
use crate::rerank::RerankScore;
use crate::tokenizer::WindowedTokenizer;
impl TextCrossEncoder {
pub(super) fn score_windows<S: AsRef<str>>(
&self,
tokenizer: &WindowedTokenizer,
query: &str,
documents: &[S],
batch_size: usize,
) -> Result<Vec<RerankScore>> {
let mut owners = Vec::new();
let mut windows: Vec<Encoding> = Vec::new();
for (index, document) in documents.iter().enumerate() {
let cut = tokenizer.windows(query, document.as_ref())?;
owners.extend(std::iter::repeat_n(index, cut.len()));
windows.extend(cut);
}
let mut scores: Vec<Vec<RerankScore>> = vec![Vec::new(); documents.len()];
for (owners, windows) in owners.chunks(batch_size).zip(windows.chunks(batch_size)) {
let batch = self.forward(|device| tokenizer.batch(windows, device))?;
for (&owner, score) in owners.iter().zip(batch) {
scores[owner].push(score);
}
}
scores.iter().map(|scores| best_window(scores)).collect()
}
}
fn best_window(scores: &[RerankScore]) -> Result<RerankScore> {
scores.iter().copied().max().ok_or_else(|| {
CanddingError::Tokenizer("a windowed document produced no window to score".to_string())
})
}