use std::path::Path;
use candle_core::Device;
use tokenizers::Encoding;
use crate::error::Result;
use crate::registry::rerank::RerankInput;
use crate::tokenizer::EncodedBatch;
use crate::tokenizer::PadToken;
use crate::tokenizer::PairTruncationPolicy;
use crate::tokenizer::PromptTokenizer;
use crate::tokenizer::TextTokenizer;
use crate::tokenizer::WindowedTokenizer;
pub(crate) enum InputTokenizer {
Rows(RowTokenizer),
Windowed(WindowedTokenizer),
}
pub(crate) enum RowTokenizer {
Pair {
tokenizer: TextTokenizer,
truncation: PairTruncationPolicy,
},
Prompt {
tokenizer: PromptTokenizer,
default_instruction: String,
},
}
impl InputTokenizer {
pub(crate) fn from_file(
input: &RerankInput,
path: &Path,
max_length: usize,
pad: PadToken,
) -> Result<Self> {
Ok(match input {
RerankInput::Pair { truncation } => InputTokenizer::Rows(RowTokenizer::Pair {
tokenizer: TextTokenizer::from_file_for_pairs(path, max_length, pad)?,
truncation: *truncation,
}),
RerankInput::Prompt {
template,
default_instruction,
} => InputTokenizer::Rows(RowTokenizer::Prompt {
tokenizer: PromptTokenizer::from_file(path, max_length, pad, *template)?,
default_instruction: default_instruction.to_string(),
}),
RerankInput::Windowed { query_cap, overlap } => InputTokenizer::Windowed(
WindowedTokenizer::from_file(path, max_length, pad, *query_cap, *overlap)?,
),
})
}
pub(crate) fn max_length(&self) -> usize {
match self {
InputTokenizer::Rows(RowTokenizer::Pair { tokenizer, .. }) => tokenizer.max_length(),
InputTokenizer::Rows(RowTokenizer::Prompt { tokenizer, .. }) => tokenizer.max_length(),
InputTokenizer::Windowed(tokenizer) => tokenizer.max_length(),
}
}
pub(crate) fn count(
&self,
instruction: Option<&str>,
pairs: &[(&str, &str)],
) -> Result<Vec<usize>> {
match self {
InputTokenizer::Rows(rows) => rows.count(instruction, pairs),
InputTokenizer::Windowed(tokenizer) => pairs
.iter()
.map(|&(query, document)| {
Ok(
tokenizer
.windows(query, document)?
.iter()
.map(Encoding::len)
.sum(),
)
})
.collect(),
}
}
pub(crate) fn window_count(&self, pairs: &[(&str, &str)]) -> Result<Vec<usize>> {
match self {
InputTokenizer::Rows(_) => Ok(vec![1; pairs.len()]),
InputTokenizer::Windowed(tokenizer) => pairs
.iter()
.map(|&(query, document)| Ok(tokenizer.windows(query, document)?.len()))
.collect(),
}
}
}
impl RowTokenizer {
pub(crate) fn encode(
&self,
instruction: Option<&str>,
pairs: &[(&str, &str)],
device: &Device,
) -> Result<EncodedBatch> {
match self {
RowTokenizer::Pair {
tokenizer,
truncation,
} => tokenizer.encode_pairs(pairs, *truncation, device),
RowTokenizer::Prompt {
tokenizer,
default_instruction,
} => tokenizer.encode(instruction.unwrap_or(default_instruction), pairs, device),
}
}
fn count(&self, instruction: Option<&str>, pairs: &[(&str, &str)]) -> Result<Vec<usize>> {
match self {
RowTokenizer::Pair {
tokenizer,
truncation,
} => tokenizer.count_pairs(pairs, *truncation),
RowTokenizer::Prompt {
tokenizer,
default_instruction,
} => tokenizer.count(instruction.unwrap_or(default_instruction), pairs),
}
}
}