use crate::{
common::TokenizerFiles,
init::{HasMaxLength, InitOptionsWithLength},
pooling::Pooling,
EmbeddingModel, OutputKey, QuantizationMode,
};
use ort::{execution_providers::ExecutionProviderDispatch, session::Session};
use tokenizers::Tokenizer;
use super::DEFAULT_MAX_LENGTH;
impl HasMaxLength for EmbeddingModel {
const MAX_LENGTH: usize = DEFAULT_MAX_LENGTH;
}
pub type TextInitOptions = InitOptionsWithLength<EmbeddingModel>;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct InitOptionsUserDefined {
pub execution_providers: Vec<ExecutionProviderDispatch>,
pub max_length: usize,
pub intra_threads: Option<usize>,
pub disable_cpu_fallback: bool,
pub dimension_overrides: Vec<(String, i64)>,
}
impl InitOptionsUserDefined {
pub fn new() -> Self {
Self {
..Default::default()
}
}
pub fn with_execution_providers(
mut self,
execution_providers: Vec<ExecutionProviderDispatch>,
) -> Self {
self.execution_providers = execution_providers;
self
}
pub fn with_max_length(mut self, max_length: usize) -> Self {
self.max_length = max_length;
self
}
pub fn with_intra_threads(mut self, intra_threads: usize) -> Self {
self.intra_threads = Some(intra_threads);
self
}
pub fn with_disable_cpu_fallback(mut self, disable: bool) -> Self {
self.disable_cpu_fallback = disable;
self
}
pub fn with_dimension_override(mut self, name: impl Into<String>, size: i64) -> Self {
self.dimension_overrides.push((name.into(), size));
self
}
}
impl Default for InitOptionsUserDefined {
fn default() -> Self {
Self {
execution_providers: Default::default(),
max_length: DEFAULT_MAX_LENGTH,
intra_threads: None,
disable_cpu_fallback: false,
dimension_overrides: Vec::new(),
}
}
}
impl From<TextInitOptions> for InitOptionsUserDefined {
fn from(options: TextInitOptions) -> Self {
InitOptionsUserDefined {
execution_providers: options.execution_providers,
max_length: options.max_length,
intra_threads: options.intra_threads,
disable_cpu_fallback: false,
dimension_overrides: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UserDefinedEmbeddingModel {
pub onnx_file: Vec<u8>,
pub external_initializers: Vec<ExternalInitializerFile>,
pub tokenizer_files: TokenizerFiles,
pub pooling: Option<Pooling>,
pub quantization: QuantizationMode,
pub output_key: Option<OutputKey>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExternalInitializerFile {
pub file_name: String,
pub buffer: Vec<u8>,
}
impl UserDefinedEmbeddingModel {
pub fn new(onnx_file: Vec<u8>, tokenizer_files: TokenizerFiles) -> Self {
Self {
onnx_file,
external_initializers: Vec::new(),
tokenizer_files,
quantization: QuantizationMode::None,
pooling: None,
output_key: None,
}
}
pub fn with_quantization(mut self, quantization: QuantizationMode) -> Self {
self.quantization = quantization;
self
}
pub fn with_pooling(mut self, pooling: Pooling) -> Self {
self.pooling = Some(pooling);
self
}
pub fn with_external_initializer(mut self, file_name: String, buffer: Vec<u8>) -> Self {
self.external_initializers
.push(ExternalInitializerFile { file_name, buffer });
self
}
}
pub struct TextEmbedding {
pub tokenizer: Tokenizer,
pub(crate) pooling: Option<Pooling>,
pub(crate) session: Session,
pub(crate) need_token_type_ids: bool,
pub(crate) quantization: QuantizationMode,
pub(crate) output_key: Option<OutputKey>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn user_defined_session_controls_are_opt_in_and_composable() {
let defaults = InitOptionsUserDefined::default();
assert!(!defaults.disable_cpu_fallback);
assert!(defaults.dimension_overrides.is_empty());
let configured = InitOptionsUserDefined::new()
.with_disable_cpu_fallback(true)
.with_dimension_override("batch_size", 1)
.with_dimension_override("sequence_length", 512);
assert!(configured.disable_cpu_fallback);
assert_eq!(
configured.dimension_overrides,
[
("batch_size".to_string(), 1),
("sequence_length".to_string(), 512)
]
);
}
}