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#[cfg(not(feature = "embeddings"))]
12pub mod engine {
13 use std::path::Path;
14
15 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 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 pub async fn embed(&self, _text: &str) -> crate::error::Result<Vec<f32>> {
39 Err(crate::error::MnemeError::EmbeddingsDisabled)
40 }
41
42 pub async fn embed_batch(&self, _texts: &[String]) -> crate::error::Result<Vec<Vec<f32>>> {
44 Err(crate::error::MnemeError::EmbeddingsDisabled)
45 }
46
47 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 pub fn model_name(&self) -> &str {
64 "disabled"
65 }
66
67 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 #[derive(Clone)]
82 pub struct EmbeddingStore {
83 _conn: Arc<Mutex<Connection>>,
84 }
85
86 impl EmbeddingStore {
87 pub fn new(conn: Arc<Mutex<Connection>>) -> Self {
89 Self { _conn: conn }
90 }
91
92 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 pub fn load(&self, _memory_id: Uuid) -> crate::error::Result<Option<Vec<f32>>> {
104 Ok(None)
105 }
106
107 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 pub fn delete(&self, _memory_id: Uuid) -> crate::error::Result<()> {
117 Err(crate::error::MnemeError::EmbeddingsDisabled)
118 }
119
120 pub fn find_unindexed(&self, _project: &str) -> crate::error::Result<Vec<Uuid>> {
122 Ok(Vec::new())
123 }
124
125 pub fn serialize(v: &[f32]) -> Vec<u8> {
127 v.iter().flat_map(|f| f.to_le_bytes()).collect()
128 }
129
130 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 #[derive(Debug, Clone)]
146 pub struct SemanticMatch {
147 pub memory_id: Uuid,
149 pub cosine_score: f32,
151 pub combined_score: f64,
153 }
154
155 pub fn cosine_similarity(_a: &[f32], _b: &[f32]) -> f32 {
157 0.0
158 }
159
160 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 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 }
184}