mirror of
https://github.com/samvallad33/vestige.git
synced 2026-04-25 00:36:22 +02:00
Merge pull request #22 from matthias-Q/fix_fastembed_cache
fix: specify cache location for fastembed_cache
This commit is contained in:
commit
0dd010a138
4 changed files with 40 additions and 18 deletions
|
|
@ -33,18 +33,26 @@ pub const BATCH_SIZE: usize = 32;
|
|||
/// Result type for model initialization
|
||||
static EMBEDDING_MODEL_RESULT: OnceLock<Result<Mutex<TextEmbedding>, String>> = OnceLock::new();
|
||||
|
||||
/// Get the default cache directory for fastembed models
|
||||
/// Uses FASTEMBED_CACHE_PATH env var, or falls back to platform cache directory
|
||||
fn get_cache_dir() -> std::path::PathBuf {
|
||||
/// Get the default cache directory for fastembed models.
|
||||
///
|
||||
/// Resolution order:
|
||||
/// 1. `FASTEMBED_CACHE_PATH` env var (explicit override)
|
||||
/// 2. Platform cache dir via `directories::ProjectDirs`
|
||||
/// - Linux: `$XDG_CACHE_HOME/vestige/fastembed` (typically `~/.cache/vestige/fastembed`)
|
||||
/// - macOS: `~/Library/Caches/vestige/fastembed`
|
||||
/// - Windows: `%LOCALAPPDATA%\vestige\cache\fastembed`
|
||||
/// 3. `~/.cache/vestige/fastembed` (home-dir fallback)
|
||||
/// 4. `.fastembed_cache` relative to CWD (absolute last resort, should never trigger)
|
||||
pub(crate) fn get_cache_dir() -> std::path::PathBuf {
|
||||
if let Ok(path) = std::env::var("FASTEMBED_CACHE_PATH") {
|
||||
return std::path::PathBuf::from(path);
|
||||
}
|
||||
|
||||
// Use platform-appropriate cache directory via directories crate
|
||||
// macOS: ~/Library/Caches/com.vestige.core/fastembed
|
||||
// Linux: ~/.cache/vestige/fastembed
|
||||
// Windows: %LOCALAPPDATA%\vestige\cache\fastembed
|
||||
if let Some(proj_dirs) = directories::ProjectDirs::from("com", "vestige", "core") {
|
||||
// qualifier="" produces a clean app-name-only path on Linux/Windows;
|
||||
// on macOS the qualifier is used for the bundle ID so we keep it empty
|
||||
// to get ~/Library/Caches/vestige/fastembed rather than
|
||||
// ~/Library/Caches/com.vestige.vestige/fastembed.
|
||||
if let Some(proj_dirs) = directories::ProjectDirs::from("", "vestige", "vestige") {
|
||||
return proj_dirs.cache_dir().join("fastembed");
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +61,7 @@ fn get_cache_dir() -> std::path::PathBuf {
|
|||
return base_dirs.home_dir().join(".cache/vestige/fastembed");
|
||||
}
|
||||
|
||||
// Last resort fallback (shouldn't happen)
|
||||
// Last resort fallback (shouldn't happen in practice)
|
||||
std::path::PathBuf::from(".fastembed_cache")
|
||||
}
|
||||
|
||||
|
|
@ -210,9 +218,7 @@ impl Default for EmbeddingService {
|
|||
impl EmbeddingService {
|
||||
/// Create a new embedding service
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_unused: (),
|
||||
}
|
||||
Self { _unused: () }
|
||||
}
|
||||
|
||||
/// Check if the model is ready
|
||||
|
|
@ -240,9 +246,13 @@ impl EmbeddingService {
|
|||
/// Get the model name
|
||||
pub fn model_name(&self) -> &'static str {
|
||||
#[cfg(feature = "nomic-v2")]
|
||||
{ "nomic-ai/nomic-embed-text-v2-moe" }
|
||||
{
|
||||
"nomic-ai/nomic-embed-text-v2-moe"
|
||||
}
|
||||
#[cfg(not(feature = "nomic-v2"))]
|
||||
{ "nomic-ai/nomic-embed-text-v1.5" }
|
||||
{
|
||||
"nomic-ai/nomic-embed-text-v1.5"
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the embedding dimensions
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ mod code;
|
|||
mod hybrid;
|
||||
mod local;
|
||||
|
||||
pub(crate) use local::get_cache_dir;
|
||||
pub use local::{
|
||||
cosine_similarity, dot_product, euclidean_distance, matryoshka_truncate, Embedding,
|
||||
EmbeddingError, EmbeddingService, BATCH_SIZE, EMBEDDING_DIMENSIONS, MAX_TEXT_LENGTH,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
//! Falls back to BM25-like term overlap scoring when the cross-encoder
|
||||
//! model is unavailable.
|
||||
|
||||
#[cfg(feature = "embeddings")]
|
||||
use crate::embeddings::get_cache_dir;
|
||||
#[cfg(feature = "embeddings")]
|
||||
use fastembed::{RerankInitOptions, RerankerModel, TextRerank};
|
||||
|
||||
|
|
@ -127,6 +129,7 @@ impl Reranker {
|
|||
}
|
||||
|
||||
let options = RerankInitOptions::new(RerankerModel::JINARerankerV1TurboEn)
|
||||
.with_cache_dir(get_cache_dir())
|
||||
.with_show_download_progress(true);
|
||||
|
||||
match TextRerank::try_new(options) {
|
||||
|
|
@ -163,7 +166,9 @@ impl Reranker {
|
|||
top_k: Option<usize>,
|
||||
) -> Result<Vec<RerankedResult<T>>, RerankerError> {
|
||||
if query.is_empty() {
|
||||
return Err(RerankerError::InvalidInput("Query cannot be empty".to_string()));
|
||||
return Err(RerankerError::InvalidInput(
|
||||
"Query cannot be empty".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if candidates.is_empty() {
|
||||
|
|
@ -190,7 +195,9 @@ impl Reranker {
|
|||
.collect();
|
||||
|
||||
results.sort_by(|a, b| {
|
||||
b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal)
|
||||
b.score
|
||||
.partial_cmp(&a.score)
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
});
|
||||
|
||||
if let Some(min_score) = self.config.min_score {
|
||||
|
|
@ -217,7 +224,11 @@ impl Reranker {
|
|||
})
|
||||
.collect();
|
||||
|
||||
results.sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal));
|
||||
results.sort_by(|a, b| {
|
||||
b.score
|
||||
.partial_cmp(&a.score)
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
});
|
||||
|
||||
if let Some(min_score) = self.config.min_score {
|
||||
results.retain(|r| r.score >= min_score);
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ async fn main() {
|
|||
if let Err(e) = s.init_embeddings() {
|
||||
error!("Failed to initialize embedding service: {}", e);
|
||||
error!("Smart ingest will fall back to regular ingest without deduplication");
|
||||
error!("Hint: Check FASTEMBED_CACHE_PATH or ensure ~/.fastembed_cache exists");
|
||||
error!("Hint: Check FASTEMBED_CACHE_PATH or ensure ~/.cache/vestige/fastembed is writable");
|
||||
} else {
|
||||
info!("Embedding service initialized successfully");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue