Skip to main content

mneme/embeddings/
mod.rs

1#[cfg(feature = "embeddings")]
2pub mod engine;
3#[cfg(feature = "embeddings")]
4pub mod rerank;
5#[cfg(feature = "embeddings")]
6pub mod similarity;
7#[cfg(feature = "embeddings")]
8pub mod store;
9
10// Stubs para compilar sin el feature embeddings
11#[cfg(not(feature = "embeddings"))]
12pub mod engine {
13    use std::path::Path;
14
15    /// Stub de EmbeddingEngine para compilacion sin feature embeddings.
16    pub struct EmbeddingEngine;
17
18    impl std::fmt::Debug for EmbeddingEngine {
19        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20            f.debug_struct("EmbeddingEngine")
21                .field("model_name", &"disabled")
22                .field("dimensions", &0)
23                .finish_non_exhaustive()
24        }
25    }
26
27    impl EmbeddingEngine {
28        /// Inicializa el motor (stub — retorna error).
29        pub async fn new(
30            _cache_dir: &Path,
31            _provider: &crate::config::settings::EmbeddingProvider,
32            _model: &str,
33        ) -> crate::error::Result<Self> {
34            Err(crate::error::MnemeError::EmbeddingsDisabled)
35        }
36
37        /// Genera el embedding de un texto (stub — retorna error).
38        pub async fn embed(&self, _text: &str) -> crate::error::Result<Vec<f32>> {
39            Err(crate::error::MnemeError::EmbeddingsDisabled)
40        }
41
42        /// Genera embeddings para un batch de textos (stub — retorna error).
43        pub async fn embed_batch(&self, _texts: &[String]) -> crate::error::Result<Vec<Vec<f32>>> {
44            Err(crate::error::MnemeError::EmbeddingsDisabled)
45        }
46
47        /// Convierte una memoria a texto para embedding.
48        pub fn memory_to_text(memory: &crate::store::memory::Memory) -> String {
49            let mut parts = vec![memory.title.clone(), memory.content.clone()];
50            if let Some(w) = &memory.what {
51                parts.push(w.clone());
52            }
53            if let Some(w) = &memory.why {
54                parts.push(w.clone());
55            }
56            if let Some(l) = &memory.learned {
57                parts.push(l.clone());
58            }
59            parts.join(" . ")
60        }
61
62        /// Retorna el nombre del modelo.
63        pub fn model_name(&self) -> &str {
64            "disabled"
65        }
66
67        /// Retorna las dimensiones del embedding.
68        pub fn dimensions(&self) -> usize {
69            0
70        }
71    }
72}
73
74#[cfg(not(feature = "embeddings"))]
75pub mod store {
76    use rusqlite::Connection;
77    use std::sync::{Arc, Mutex};
78    use uuid::Uuid;
79
80    /// Stub de EmbeddingStore para compilacion sin feature embeddings.
81    #[derive(Clone)]
82    pub struct EmbeddingStore {
83        _conn: Arc<Mutex<Connection>>,
84    }
85
86    impl EmbeddingStore {
87        /// Crea un nuevo EmbeddingStore.
88        pub fn new(conn: Arc<Mutex<Connection>>) -> Self {
89            Self { _conn: conn }
90        }
91
92        /// Guarda embedding de una memoria (stub — retorna error).
93        pub fn save(
94            &self,
95            _memory_id: Uuid,
96            _embedding: &[f32],
97            _model_name: &str,
98        ) -> crate::error::Result<()> {
99            Err(crate::error::MnemeError::EmbeddingsDisabled)
100        }
101
102        /// Carga embedding de una memoria (stub — retorna None).
103        pub fn load(&self, _memory_id: Uuid) -> crate::error::Result<Option<Vec<f32>>> {
104            Ok(None)
105        }
106
107        /// Carga todos los embeddings de un proyecto (stub — retorna vacio).
108        pub fn load_all_for_project(
109            &self,
110            _project: &str,
111        ) -> crate::error::Result<Vec<(Uuid, Vec<f32>)>> {
112            Ok(Vec::new())
113        }
114
115        /// Elimina el embedding de una memoria (stub — retorna error).
116        pub fn delete(&self, _memory_id: Uuid) -> crate::error::Result<()> {
117            Err(crate::error::MnemeError::EmbeddingsDisabled)
118        }
119
120        /// Lista IDs de memorias sin embedding (stub — retorna vacio).
121        pub fn find_unindexed(&self, _project: &str) -> crate::error::Result<Vec<Uuid>> {
122            Ok(Vec::new())
123        }
124
125        /// Serializa un vector de f32 a bytes little-endian.
126        pub fn serialize(v: &[f32]) -> Vec<u8> {
127            v.iter().flat_map(|f| f.to_le_bytes()).collect()
128        }
129
130        /// Deserializa bytes little-endian a un vector de f32.
131        pub fn deserialize(bytes: &[u8]) -> Vec<f32> {
132            bytes
133                .chunks_exact(4)
134                .map(|b| f32::from_le_bytes([b[0], b[1], b[2], b[3]]))
135                .collect()
136        }
137    }
138}
139
140#[cfg(not(feature = "embeddings"))]
141pub mod similarity {
142    use uuid::Uuid;
143
144    /// Resultado de coincidencia semantica.
145    #[derive(Debug, Clone)]
146    pub struct SemanticMatch {
147        /// ID de la memoria.
148        pub memory_id: Uuid,
149        /// Score de similitud coseno.
150        pub cosine_score: f32,
151        /// Score combinado (coseno * boost * decaimiento).
152        pub combined_score: f64,
153    }
154
155    /// Calcula similitud coseno entre dos vectores f32 (stub — retorna 0.0).
156    pub fn cosine_similarity(_a: &[f32], _b: &[f32]) -> f32 {
157        0.0
158    }
159
160    /// Ordena coincidencias semanticas por score combinado descendente.
161    pub fn rank_by_combined_score(matches: &mut [SemanticMatch]) {
162        matches.sort_by(|a, b| {
163            b.combined_score
164                .partial_cmp(&a.combined_score)
165                .unwrap_or(std::cmp::Ordering::Equal)
166        });
167    }
168}
169
170#[cfg(not(feature = "embeddings"))]
171pub mod rerank {
172    use crate::store::memory::SearchResult;
173    use crate::store::search::SearchWeights;
174
175    /// Stub: no-op reranker when embeddings are disabled.
176    pub fn rerank_search_results(
177        _query: &str,
178        _results: &mut Vec<SearchResult>,
179        _engine: Option<&std::sync::Arc<crate::embeddings::engine::EmbeddingEngine>>,
180        _weights: &SearchWeights,
181    ) {
182        // No-op
183    }
184}