mod database;
pub mod models;
mod onnx;
mod similarity;
pub use database::{EmbeddingMetadata, EmbeddingsDatabase};
pub use models::{Config, ModelDefinition, ModelRegistry};
pub use onnx::OnnxEmbedder;
pub use similarity::{cosine_similarity, euclidean_distance};
use anyhow::Result;
pub trait EmbeddingEngine: Send {
fn embed(&mut self, text: &str) -> Result<Vec<f32>>;
fn embed_query(&mut self, text: &str) -> Result<Vec<f32>> {
self.embed(text)
}
fn embed_passage(&mut self, text: &str) -> Result<Vec<f32>> {
self.embed(text)
}
fn embed_batch(&mut self, texts: &[String]) -> Result<Vec<Vec<f32>>>;
fn dimension(&self) -> usize;
fn model_name(&self) -> &str;
}
pub fn create_embedder() -> Result<Box<dyn EmbeddingEngine>> {
create_embedder_from_config()
}
fn create_embedder_from_config() -> Result<Box<dyn EmbeddingEngine>> {
let config = Config::load()?;
let model_def = config.get_model_definition()?;
create_onnx_embedder(&model_def)
}
fn create_onnx_embedder(model_def: &ModelDefinition) -> Result<Box<dyn EmbeddingEngine>> {
let model_dir = crate::models::resolve_model_path(&model_def.name)?;
let model_path = model_dir.join("model.onnx");
let tokenizer_path = model_dir.join("tokenizer.json");
let model_path_quantized = model_dir.join("model_quantized.onnx");
let final_model_path = if model_path_quantized.exists() {
&model_path_quantized
} else {
&model_path
};
Ok(Box::new(OnnxEmbedder::new_from_paths(
final_model_path,
&tokenizer_path,
&model_def.name,
model_def.dimensions,
model_def.query_prefix.clone(),
model_def.passage_prefix.clone(),
)?))
}
pub fn get_current_model_name() -> Result<String> {
let config = Config::load()?;
Ok(config.embeddings.model)
}