pub mod embeddings;
pub mod indexer;
pub mod reranker;
pub mod search;
pub mod setup;
pub const EMBEDDING_DIM: usize = 384;
const EMBEDDING_MODEL_CODE: &str = "Qdrant/bge-small-en-v1.5-onnx-Q";
const EMBEDDING_MODEL_FILE: &str = "model_optimized.onnx";
const RERANKER_MODEL_CODE: &str = "BAAI/bge-reranker-base";
const RERANKER_MODEL_FILE: &str = "onnx/model.onnx";
fn is_model_cached(model_code: &str, model_file: &str) -> bool {
let cache_dir = model_cache_dir();
let dir_name = format!("models--{}", model_code.replace('/', "--"));
let ref_path = cache_dir.join(&dir_name).join("refs").join("main");
let Ok(commit_hash) = std::fs::read_to_string(&ref_path) else {
return false;
};
let model_path = cache_dir
.join(&dir_name)
.join("snapshots")
.join(commit_hash.trim())
.join(model_file);
model_path.exists()
}
pub fn is_embedding_model_cached() -> bool {
is_model_cached(EMBEDDING_MODEL_CODE, EMBEDDING_MODEL_FILE)
}
pub fn is_reranker_model_cached() -> bool {
is_model_cached(RERANKER_MODEL_CODE, RERANKER_MODEL_FILE)
}
pub fn model_cache_dir() -> std::path::PathBuf {
if let Ok(dir) = std::env::var("FASTEMBED_CACHE_DIR") {
return std::path::PathBuf::from(dir);
}
if let Ok(xdg) = std::env::var("XDG_CACHE_HOME") {
return std::path::PathBuf::from(xdg).join("cartog").join("models");
}
if let Some(home) = home_dir() {
return home.join(".cache").join("cartog").join("models");
}
std::path::PathBuf::from(".fastembed_cache")
}
fn home_dir() -> Option<std::path::PathBuf> {
std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE")) .ok()
.map(std::path::PathBuf::from)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_model_cache_dir_is_not_local() {
let dir = model_cache_dir();
let dir_str = dir.to_string_lossy();
if std::env::var("FASTEMBED_CACHE_DIR").is_err() {
assert!(
dir_str.contains("cartog"),
"cache dir should contain 'cartog', got: {dir_str}"
);
assert!(
!dir_str.starts_with('.'),
"cache dir should be absolute, not relative: {dir_str}"
);
}
}
#[test]
fn test_model_cache_dir_ends_with_models() {
if std::env::var("FASTEMBED_CACHE_DIR").is_err() {
let dir = model_cache_dir();
assert!(
dir.ends_with("models"),
"cache dir should end with 'models', got: {}",
dir.display()
);
}
}
}