1use crate::{EmbeddingError, Embeddings};
7use async_trait::async_trait;
8
9pub struct MockEmbeddings {
14 dimension: usize,
15}
16
17impl MockEmbeddings {
18 pub fn new(dimension: usize) -> Self {
20 Self { dimension }
21 }
22}
23
24impl Default for MockEmbeddings {
25 fn default() -> Self {
26 Self::new(1536)
27 }
28}
29
30#[async_trait]
31impl Embeddings for MockEmbeddings {
32 async fn embed_query(&self, text: &str) -> Result<Vec<f32>, EmbeddingError> {
33 if text.trim().is_empty() {
34 return Err(EmbeddingError::EmptyInput);
35 }
36
37 let hash = Self::hash_text(text);
39 let mut embedding = Vec::with_capacity(self.dimension);
40
41 for i in 0..self.dimension {
42 let value = ((hash.wrapping_add(i as u64)) % 1000) as f32 / 1000.0 - 0.5;
44 embedding.push(value);
45 }
46
47 let norm: f32 = embedding.iter().map(|x| x * x).sum::<f32>().sqrt();
49 if norm > 0.0 {
50 for v in &mut embedding {
51 *v /= norm;
52 }
53 }
54
55 Ok(embedding)
56 }
57
58 fn dimension(&self) -> usize {
59 self.dimension
60 }
61
62 fn model_name(&self) -> &str {
63 "mock-embeddings"
64 }
65}
66
67impl MockEmbeddings {
68 fn hash_text(text: &str) -> u64 {
70 let mut hash: u64 = 0;
71 for (i, c) in text.chars().enumerate() {
72 hash = hash.wrapping_add((c as u64).wrapping_mul((i + 1) as u64));
73 }
74 hash
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[tokio::test]
83 async fn test_mock_embedding() {
84 let embeddings = MockEmbeddings::new(128);
85
86 let result = embeddings.embed_query("Hello, world!").await.unwrap();
87 assert_eq!(result.len(), 128);
88
89 let result2 = embeddings.embed_query("Hello, world!").await.unwrap();
91 assert_eq!(result, result2);
92
93 let result3 = embeddings.embed_query("Different text").await.unwrap();
95 assert_ne!(result, result3);
96 }
97
98 #[tokio::test]
99 async fn test_mock_embedding_empty() {
100 let embeddings = MockEmbeddings::new(128);
101
102 let result = embeddings.embed_query("").await;
103 assert!(result.is_err());
104 }
105
106 #[tokio::test]
107 async fn test_mock_embedding_normalized() {
108 let embeddings = MockEmbeddings::new(128);
109
110 let result = embeddings.embed_query("Test normalization").await.unwrap();
111
112 let norm: f32 = result.iter().map(|x| x * x).sum::<f32>().sqrt();
114 assert!((norm - 1.0).abs() < 0.0001);
115 }
116}