1use crate::config::Config;
7use crate::core::*;
8use crate::database::{
9 GraphEdge, GraphNode, GraphQueryRequest, Vector, VectorGraphDB, VectorQueryRequest,
10};
11use crate::error::{MemoryError, Result};
12use chrono::{DateTime, Duration, Utc};
13use log::{debug, info, warn};
14use serde::{Deserialize, Serialize};
15use std::collections::HashMap;
16use std::sync::Arc;
17use tokio::sync::RwLock;
18
19#[derive(Debug)]
23pub struct MemoryManager {
24 db: Arc<VectorGraphDB>,
25 config: Config,
26 link_analyzer: LinkAnalyzer,
27 importance_calculator: ImportanceCalculator,
28 evolution_engine: EvolutionEngine,
29 retrieval_engine: RetrievalEngine,
30 stats: Arc<RwLock<MemoryStats>>,
31}
32
33#[derive(Debug, Clone, Default, Serialize, Deserialize)]
35pub struct MemoryStats {
36 pub total_memories: u64,
37 pub total_connections: u64,
38 pub average_importance: f32,
39 pub retrieval_count: u64,
40 pub creation_count: u64,
41 pub evolution_count: u64,
42 pub last_updated: DateTime<Utc>,
43}
44
45#[derive(Debug, Clone)]
49#[allow(dead_code)]
50pub struct LinkAnalyzer {
51 semantic_threshold: f32,
53 temporal_window: Duration,
55 causal_patterns: Vec<String>,
57 thematic_keywords: HashMap<String, Vec<String>>,
59}
60
61#[derive(Debug, Clone)]
65#[allow(dead_code)]
66pub struct ImportanceCalculator {
67 access_weight: f32,
69 recency_weight: f32,
71 connection_weight: f32,
73 feedback_weight: f32,
75 content_weight: f32,
77}
78
79#[derive(Debug, Clone)]
83#[allow(dead_code)]
84pub struct EvolutionEngine {
85 decay_factor: f32,
87 reinforcement_factor: f32,
89 pruning_threshold: f32,
91 evolution_interval: Duration,
93}
94
95#[derive(Debug, Clone)]
99#[allow(dead_code)]
100pub struct RetrievalEngine {
101 pagerank_config: PageRankConfig,
103 fusion_weights: QueryWeights,
105 personalization_cache: Arc<RwLock<PersonalizationVector>>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, Default)]
111pub struct PersonalizationVector {
112
113 pub preferences: HashMap<String, f32>,
114 pub interaction_history: Vec<InteractionRecord>,
115 pub last_updated: DateTime<Utc>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct InteractionRecord {
121 pub memory_id: MemoryId,
122 pub interaction_type: InteractionType,
123 pub timestamp: DateTime<Utc>,
124 pub feedback_score: Option<f32>,
125 pub dwell_time: Option<u64>, }
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct PageRankConfig {
131 pub damping_factor: f32,
132 pub max_iterations: usize,
133 pub convergence_threshold: f32,
134 pub personalization_weight: f32,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct RetrievalResult {
140 pub memory: Memory,
141 pub relevance_score: f32,
142 pub explanation: RetrievalExplanation,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct RetrievalExplanation {
148 pub semantic_score: f32,
149 pub temporal_score: f32,
150 pub importance_score: f32,
151 pub personalization_score: f32,
152 pub connection_paths: Vec<Vec<MemoryId>>,
153 pub reasoning: String,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct CreateMemoryRequest {
159 pub content: String,
160 pub context: Context,
161 pub attributes: Option<MemoryAttributes>,
162 pub force_connections: Option<Vec<MemoryId>>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct UpdateMemoryRequest {
168 pub memory_id: MemoryId,
169 pub updates: Vec<UpdateType>,
170 pub context: Context,
171}
172
173impl MemoryManager {
174 pub async fn new(db: Arc<VectorGraphDB>, config: Config) -> Result<Self> {
176 let link_analyzer = LinkAnalyzer::new(&config);
177 let importance_calculator = ImportanceCalculator::new(&config);
178 let evolution_engine = EvolutionEngine::new(&config);
179 let retrieval_engine = RetrievalEngine::new(&config).await?;
180
181 Ok(Self {
182 db,
183 config,
184 link_analyzer,
185 importance_calculator,
186 evolution_engine,
187 retrieval_engine,
188 stats: Arc::new(RwLock::new(MemoryStats::default())),
189 })
190 }
191
192 pub async fn create_memory_from_request(&self, request: CreateMemoryRequest) -> Result<Memory> {
194 info!(
195 "Creating new memory with content length: {}",
196 request.content.len()
197 );
198
199 let embedding = self.generate_embedding(&request.content).await?;
201
202 let attributes = if let Some(attrs) = request.attributes {
204 attrs
205 } else {
206 self.extract_attributes(&request.content, &request.context)
207 .await?
208 };
209
210 let memory_type = MemoryType::Knowledge; let mut memory = Memory::new(request.content, memory_type, embedding, attributes);
213
214 memory.attributes.importance = self
216 .importance_calculator
217 .calculate_initial_importance(&memory, &request.context)
218 .await?;
219
220 let vector = Vector {
222 id: memory.id.clone(),
223 embedding: memory.embedding.clone(),
224 metadata: self.memory_to_metadata(&memory)?,
225 created_at: memory.metadata.created_at,
226 updated_at: memory.metadata.updated_at,
227 };
228 self.db.insert_vector(&vector).await?;
229
230 let node = GraphNode {
232 id: memory.id.clone(),
233 node_type: "memory".to_string(),
234 properties: self.memory_to_properties(&memory)?,
235 created_at: memory.metadata.created_at,
236 updated_at: memory.metadata.updated_at,
237 };
238 self.db.insert_node(&node).await?;
239
240 let connections = self
242 .link_analyzer
243 .discover_connections(&memory, &request.context)
244 .await?;
245
246 if let Some(forced_connections) = request.force_connections {
248 for target_id in forced_connections {
249 let connection = Connection::new(
250 memory.id.clone(),
251 target_id,
252 ConnectionType::Custom("forced".to_string()),
253 1.0,
254 );
255 self.create_connection(&connection).await?;
256 }
257 }
258
259 for connection in connections {
261 self.create_connection(&connection).await?;
262 memory
263 .connections
264 .semantic_links
265 .push(connection.to_memory.clone());
266 }
267
268 self.update_stats(|stats| {
270 stats.total_memories += 1;
271 stats.creation_count += 1;
272 stats.last_updated = Utc::now();
273 })
274 .await;
275
276 info!("Successfully created memory with ID: {}", memory.id);
277 Ok(memory)
278 }
279
280 pub async fn create_memory(&self, memory: &Memory) -> Result<()> {
282 info!("Creating memory with ID: {}", memory.id);
283
284 let vector = Vector {
286 id: memory.id.clone(),
287 embedding: memory.embedding.clone(),
288 metadata: self.memory_to_metadata(memory)?,
289 created_at: memory.metadata.created_at,
290 updated_at: memory.metadata.updated_at,
291 };
292 self.db.insert_vector(&vector).await?;
293
294 let node = GraphNode {
296 id: memory.id.clone(),
297 node_type: "memory".to_string(),
298 properties: self.memory_to_properties(memory)?,
299 created_at: memory.metadata.created_at,
300 updated_at: memory.metadata.updated_at,
301 };
302 self.db.insert_node(&node).await?;
303
304 self.update_stats(|stats| {
306 stats.total_memories += 1;
307 stats.creation_count += 1;
308 stats.last_updated = Utc::now();
309 })
310 .await;
311
312 info!("Successfully created memory with ID: {}", memory.id);
313 Ok(())
314 }
315
316 pub async fn retrieve_memories(
318 &self,
319 query: &Query,
320 context: &Context,
321 ) -> Result<Vec<RetrievalResult>> {
322 debug!("Retrieving memories for query: {}", query.text);
323
324 let results = match query.query_type {
325 QueryType::Semantic => self.semantic_retrieval(query, context).await?,
326 QueryType::Temporal => self.temporal_retrieval(query, context).await?,
327 QueryType::Causal => self.causal_retrieval(query, context).await?,
328 QueryType::Thematic => self.thematic_retrieval(query, context).await?,
329 QueryType::Mixed => self.mixed_retrieval(query, context).await?,
330 QueryType::GraphTraversal => self.graph_traversal_retrieval(query, context).await?,
331 QueryType::PersonalizedPageRank => {
332 self.personalized_pagerank_retrieval(query, context).await?
333 }
334 };
335
336 self.update_stats(|stats| {
338 stats.retrieval_count += 1;
339 stats.last_updated = Utc::now();
340 })
341 .await;
342
343 debug!("Retrieved {} memories", results.len());
344 Ok(results)
345 }
346
347 async fn semantic_retrieval(
349 &self,
350 query: &Query,
351 _context: &Context,
352 ) -> Result<Vec<RetrievalResult>> {
353 let query_embedding = self.generate_embedding(&query.text).await?;
354
355 let vector_request = VectorQueryRequest {
356 query_vector: query_embedding,
357 limit: query.limit,
358 threshold: Some(self.config.vector.similarity_threshold),
359 filters: self.query_filters_to_metadata_filters(&query.filters)?,
360 };
361
362 let vector_results = self.db.query_vectors(&vector_request).await?;
363
364 let mut results = Vec::new();
365 for vector_result in vector_results {
366 let memory = self.metadata_to_memory(&vector_result.vector.metadata)?;
367
368 if !memory.matches_filters(&query.filters) {
370 continue;
371 }
372
373 let explanation = RetrievalExplanation {
374 semantic_score: vector_result.similarity,
375 temporal_score: 0.0,
376 importance_score: memory.attributes.importance,
377 personalization_score: 0.0,
378 connection_paths: Vec::new(),
379 reasoning: format!("Semantic similarity: {:.3}", vector_result.similarity),
380 };
381
382 results.push(RetrievalResult {
383 memory,
384 relevance_score: vector_result.similarity,
385 explanation,
386 });
387 }
388
389 Ok(results)
390 }
391
392 async fn temporal_retrieval(
394 &self,
395 query: &Query,
396 context: &Context,
397 ) -> Result<Vec<RetrievalResult>> {
398 let time_window = context
400 .time_window
401 .unwrap_or((Utc::now() - Duration::days(30), Utc::now()));
402
403 let mut semantic_results = self.semantic_retrieval(query, context).await?;
405
406 for result in &mut semantic_results {
408 let time_score = self
409 .calculate_temporal_relevance(&result.memory, &time_window, &query.text)
410 .await?;
411
412 result.explanation.temporal_score = time_score;
413 result.relevance_score = result.explanation.semantic_score
414 * query.weights.semantic_weight
415 + time_score * query.weights.temporal_weight;
416 }
417
418 semantic_results.sort_by(|a, b| b.relevance_score.partial_cmp(&a.relevance_score).unwrap());
420
421 Ok(semantic_results)
422 }
423
424 async fn causal_retrieval(
426 &self,
427 query: &Query,
428 context: &Context,
429 ) -> Result<Vec<RetrievalResult>> {
430 let causal_keywords = self.extract_causal_keywords(&query.text)?;
432
433 let graph_request = GraphQueryRequest {
434 start_nodes: context.recent_memories.clone(),
435 edge_types: Some(vec!["causal".to_string()]),
436 max_depth: Some(3),
437 limit: query.limit,
438 filters: self.query_filters_to_graph_filters(&query.filters)?,
439 };
440
441 let graph_results = self.db.query_graph(&graph_request).await?;
442
443 let mut results = Vec::new();
444 for node in graph_results.nodes {
445 if let Ok(memory) = self.properties_to_memory(&node.properties) {
446 let causal_score = self
447 .calculate_causal_relevance(&memory, &causal_keywords)
448 .await?;
449
450 if causal_score > 0.1 {
451 let explanation = RetrievalExplanation {
452 semantic_score: 0.0,
453 temporal_score: 0.0,
454 importance_score: memory.attributes.importance,
455 personalization_score: 0.0,
456 connection_paths: Vec::new(),
457 reasoning: format!("Causal relevance: {:.3}", causal_score),
458 };
459
460 results.push(RetrievalResult {
461 memory,
462 relevance_score: causal_score,
463 explanation,
464 });
465 }
466 }
467 }
468
469 results.sort_by(|a, b| b.relevance_score.partial_cmp(&a.relevance_score).unwrap());
470 Ok(results)
471 }
472
473 async fn thematic_retrieval(
475 &self,
476 query: &Query,
477 _context: &Context,
478 ) -> Result<Vec<RetrievalResult>> {
479 let themes = self.extract_themes(&query.text)?;
480
481 let graph_request = GraphQueryRequest {
482 start_nodes: Vec::new(),
483 edge_types: Some(vec!["thematic".to_string()]),
484 max_depth: Some(2),
485 limit: query.limit,
486 filters: self.create_theme_filters(&themes)?,
487 };
488
489 let graph_results = self.db.query_graph(&graph_request).await?;
490
491 let mut results = Vec::new();
492 for node in graph_results.nodes {
493 if let Ok(memory) = self.properties_to_memory(&node.properties) {
494 let theme_score = self.calculate_thematic_relevance(&memory, &themes).await?;
495
496 let explanation = RetrievalExplanation {
497 semantic_score: 0.0,
498 temporal_score: 0.0,
499 importance_score: memory.attributes.importance,
500 personalization_score: 0.0,
501 connection_paths: Vec::new(),
502 reasoning: format!("Thematic relevance: {:.3}", theme_score),
503 };
504
505 results.push(RetrievalResult {
506 memory,
507 relevance_score: theme_score,
508 explanation,
509 });
510 }
511 }
512
513 results.sort_by(|a, b| b.relevance_score.partial_cmp(&a.relevance_score).unwrap());
514 Ok(results)
515 }
516
517 async fn mixed_retrieval(
519 &self,
520 query: &Query,
521 context: &Context,
522 ) -> Result<Vec<RetrievalResult>> {
523 let semantic_results = self.semantic_retrieval(query, context).await?;
525 let temporal_results = self.temporal_retrieval(query, context).await?;
526 let causal_results = self.causal_retrieval(query, context).await?;
527
528 let fused_results = self
530 .fuse_retrieval_results(
531 vec![semantic_results, temporal_results, causal_results],
532 &query.weights,
533 )
534 .await?;
535
536 Ok(fused_results)
537 }
538
539 async fn graph_traversal_retrieval(
541 &self,
542 query: &Query,
543 context: &Context,
544 ) -> Result<Vec<RetrievalResult>> {
545 let start_nodes = if context.recent_memories.is_empty() {
546 let semantic_results = self.semantic_retrieval(query, context).await?;
548 semantic_results
549 .into_iter()
550 .take(3)
551 .map(|r| r.memory.id)
552 .collect()
553 } else {
554 context.recent_memories.clone()
555 };
556
557 let graph_request = GraphQueryRequest {
558 start_nodes,
559 edge_types: None,
560 max_depth: Some(self.config.graph.traversal.max_depth),
561 limit: query.limit,
562 filters: self.query_filters_to_graph_filters(&query.filters)?,
563 };
564
565 let graph_results = self.db.query_graph(&graph_request).await?;
566
567 let mut results = Vec::new();
568 for (i, node) in graph_results.nodes.iter().enumerate() {
569 if let Ok(memory) = self.properties_to_memory(&node.properties) {
570 let path_score = 1.0 / (i as f32 + 1.0); let explanation = RetrievalExplanation {
573 semantic_score: 0.0,
574 temporal_score: 0.0,
575 importance_score: memory.attributes.importance,
576 personalization_score: 0.0,
577 connection_paths: graph_results.paths.clone(),
578 reasoning: format!("Graph traversal score: {:.3}", path_score),
579 };
580
581 results.push(RetrievalResult {
582 memory,
583 relevance_score: path_score,
584 explanation,
585 });
586 }
587 }
588
589 Ok(results)
590 }
591
592 async fn personalized_pagerank_retrieval(
594 &self,
595 query: &Query,
596 context: &Context,
597 ) -> Result<Vec<RetrievalResult>> {
598 let personalization_vector = self
600 .retrieval_engine
601 .get_personalization_vector()
602 .await?;
603
604 let pagerank_scores = self
606 .compute_personalized_pagerank(&personalization_vector, &query.text)
607 .await?;
608
609 let semantic_results = self.semantic_retrieval(query, context).await?;
611
612 let mut results = Vec::new();
613 for semantic_result in semantic_results {
614 let pagerank_score = pagerank_scores
615 .get(&semantic_result.memory.id)
616 .unwrap_or(&0.0);
617
618 let combined_score = semantic_result.relevance_score * query.weights.semantic_weight
619 + pagerank_score * query.weights.personalization_weight;
620
621 let mut explanation = semantic_result.explanation;
622 explanation.personalization_score = *pagerank_score;
623 explanation.reasoning = format!(
624 "Combined score: semantic={:.3}, pagerank={:.3}",
625 semantic_result.relevance_score, pagerank_score
626 );
627
628 results.push(RetrievalResult {
629 memory: semantic_result.memory,
630 relevance_score: combined_score,
631 explanation,
632 });
633 }
634
635 results.sort_by(|a, b| b.relevance_score.partial_cmp(&a.relevance_score).unwrap());
636 Ok(results)
637 }
638
639 pub async fn update_memory(&self, request: UpdateMemoryRequest) -> Result<Memory> {
641 info!("Updating memory: {}", request.memory_id);
642
643 let mut memory = self.get_memory(&request.memory_id).await?;
645
646 for update in request.updates {
648 match update {
649 UpdateType::ImportanceAdjustment(new_importance) => {
650 memory.attributes.importance = new_importance.clamp(0.0, 1.0);
651 }
652 UpdateType::ConnectionAdded(connection) => {
653 self.create_connection(&connection).await?;
654 memory.connections.semantic_links.push(connection.to_memory);
655 }
656 UpdateType::ConnectionRemoved(connection_id) => {
657 self.remove_connection(&connection_id).await?;
658 }
659 UpdateType::AttributeUpdate(key, value) => {
660 memory.attributes.custom_attributes.insert(key, value);
661 }
662 UpdateType::ContentUpdate(new_content) => {
663 memory.content = new_content;
664 memory.embedding = self.generate_embedding(&memory.content).await?;
665 }
666 UpdateType::TagUpdate(new_tags) => {
667 memory.attributes.tags = new_tags;
668 }
669 UpdateType::MetadataUpdate(metadata) => {
670 for (key, value) in metadata {
671 memory.metadata.custom_metadata.insert(key, value);
672 }
673 }
674 }
675 }
676
677 memory.metadata.updated_at = Utc::now();
679 memory.metadata.version += 1;
680
681 self.save_memory(&memory).await?;
683
684 info!("Successfully updated memory: {}", request.memory_id);
685 Ok(memory)
686 }
687
688 pub async fn delete_memory(&self, memory_id: &MemoryId, soft_delete: bool) -> Result<()> {
690 info!("Deleting memory: {} (soft: {})", memory_id, soft_delete);
691
692 if soft_delete {
693 let mut memory = self.get_memory(memory_id).await?;
695 memory.metadata.is_deleted = true;
696 memory.metadata.deleted_at = Some(Utc::now());
697 self.save_memory(&memory).await?;
698 } else {
699 return Err(MemoryError::Internal {
702 message: "Hard delete not implemented".to_string(),
703 });
704 }
705
706 self.update_stats(|stats| {
708 if stats.total_memories > 0 {
709 stats.total_memories -= 1;
710 }
711 stats.last_updated = Utc::now();
712 })
713 .await;
714
715 info!("Successfully deleted memory: {}", memory_id);
716 Ok(())
717 }
718
719 pub async fn evolve_memories(&self, trigger: EvolutionTrigger) -> Result<u64> {
721 info!("Starting memory evolution with trigger: {:?}", trigger);
722
723 let evolved_count = self.evolution_engine.evolve(&trigger, &self.db).await?;
724
725 self.update_stats(|stats| {
727 stats.evolution_count += evolved_count;
728 stats.last_updated = Utc::now();
729 })
730 .await;
731
732 info!("Evolution completed. {} memories evolved", evolved_count);
733 Ok(evolved_count)
734 }
735
736 pub async fn get_stats(&self) -> MemoryStats {
738 self.stats.read().await.clone()
739 }
740
741 pub async fn generate_embedding(&self, text: &str) -> Result<Vec<f32>> {
744 use model2vec_rs::model::StaticModel;
745 use std::sync::OnceLock;
746 use std::sync::{Arc, Mutex};
747
748 static MODEL: OnceLock<Option<Arc<Mutex<StaticModel>>>> = OnceLock::new();
750
751 let model = MODEL
752 .get_or_init(|| {
753 match StaticModel::from_pretrained(
754 "minishlab/potion-multilingual-128M", None, None, None, ) {
759 Ok(m) => Some(Arc::new(Mutex::new(m))),
760 Err(_) => None,
761 }
762 })
763 .as_ref()
764 .ok_or_else(|| MemoryError::Internal {
765 message: "Failed to load embedding model".to_string(),
766 })?;
767
768 let model_guard = model.lock().map_err(|e| MemoryError::Internal {
769 message: format!("Failed to acquire model lock: {}", e),
770 })?;
771
772 let sentences = vec![text.to_string()];
774 let embeddings = model_guard.encode(&sentences);
775
776 if embeddings.is_empty() {
777 return Err(MemoryError::Internal {
778 message: "Failed to generate embedding: empty result".to_string(),
779 });
780 }
781
782 Ok(embeddings[0].clone())
783 }
784
785 async fn extract_attributes(
786 &self,
787 content: &str,
788 context: &Context,
789 ) -> Result<MemoryAttributes> {
790 let words: Vec<&str> = content.split_whitespace().collect();
792 let keywords = words.iter().take(5).map(|s| s.to_string()).collect();
793
794 Ok(MemoryAttributes {
795 keywords,
796 tags: Vec::new(),
797 context: context.current_topic.clone().unwrap_or_default(),
798 importance: 0.5,
799 emotion: None,
800 source: None,
801 confidence: 1.0,
802 language: Some("zh".to_string()),
803 custom_attributes: HashMap::new(),
804 })
805 }
806
807 pub async fn create_connection(&self, connection: &Connection) -> Result<()> {
808 let edge = GraphEdge {
809 id: connection.id.clone(),
810 from_node: connection.from_memory.clone(),
811 to_node: connection.to_memory.clone(),
812 edge_type: format!("{:?}", connection.connection_type),
813 weight: connection.strength,
814 properties: connection.properties.clone(),
815 created_at: connection.created_at,
816 updated_at: connection.updated_at,
817 };
818
819 self.db.insert_edge(&edge).await?;
820
821 self.update_stats(|stats| {
823 stats.total_connections += 1;
824 stats.last_updated = Utc::now();
825 })
826 .await;
827
828 Ok(())
829 }
830
831 async fn remove_connection(&self, connection_id: &ConnectionId) -> Result<()> {
832 warn!("Connection removal not implemented: {}", connection_id);
834 Ok(())
835 }
836
837 async fn get_memory(&self, memory_id: &MemoryId) -> Result<Memory> {
838 let vector = self.db.get_vector(memory_id).await.map_err(|e| {
839 if let MemoryError::Database(_) = e {
840 MemoryError::MemoryNotFound { id: memory_id.clone() }
841 } else {
842 e
843 }
844 })?;
845
846 let mut memory = self.metadata_to_memory(&vector.metadata)?;
847 memory.embedding = vector.embedding;
848
849 memory.connections.semantic_links = self.get_connections(memory_id).await?.into_iter().map(|c| c.to_memory).collect();
851
852 Ok(memory)
853 }
854
855 async fn save_memory(&self, memory: &Memory) -> Result<()> {
856 let vector = Vector {
857 id: memory.id.clone(),
858 embedding: memory.embedding.clone(),
859 metadata: self.memory_to_metadata(memory)?,
860 created_at: memory.metadata.created_at,
861 updated_at: memory.metadata.updated_at,
862 };
863 self.db.update_vector(&vector).await?;
864
865 let node = GraphNode {
866 id: memory.id.clone(),
867 node_type: "memory".to_string(),
868 properties: self.memory_to_properties(memory)?,
869 created_at: memory.metadata.created_at,
870 updated_at: memory.metadata.updated_at,
871 };
872 self.db.update_node(&node).await?;
873
874 Ok(())
875 }
876
877 pub async fn record_interaction(&self, interaction: &Interaction) -> Result<()> {
879 debug!("Recording interaction: {:?}", interaction.interaction_type);
880
881 for memory_id in &interaction.retrieved_memories {
883 info!("Updated access stats for memory: {}", memory_id);
885 }
886
887 self.update_stats(|stats| {
889 stats.last_updated = Utc::now();
890 })
891 .await;
892
893 Ok(())
894 }
895
896 pub async fn get_connections(&self, memory_id: &MemoryId) -> Result<Vec<Connection>> {
898 debug!("Getting connections for memory: {}", memory_id);
899
900 let graph_request = GraphQueryRequest {
901 start_nodes: vec![memory_id.clone()],
902 edge_types: None,
903 max_depth: Some(1),
904 limit: Some(100),
905 filters: None,
906 };
907
908 let graph_results = self.db.query_graph(&graph_request).await?;
909
910 let mut connections = Vec::new();
911 for edge in graph_results.edges {
912 let connection = Connection {
913 id: edge.id,
914 from_memory: edge.from_node,
915 to_memory: edge.to_node,
916 connection_type: ConnectionType::Semantic, strength: edge.weight,
918 created_at: edge.created_at,
919 updated_at: edge.updated_at,
920 properties: edge.properties,
921 bidirectional: false,
922 };
923 connections.push(connection);
924 }
925
926 Ok(connections)
927 }
928
929 async fn update_stats<F>(&self, updater: F)
930 where
931 F: FnOnce(&mut MemoryStats),
932 {
933 let mut stats = self.stats.write().await;
934 updater(&mut stats);
935 }
936
937 fn memory_to_metadata(&self, memory: &Memory) -> Result<HashMap<String, serde_json::Value>> {
940 let mut metadata = HashMap::new();
941
942 metadata.insert(
944 "id".to_string(),
945 serde_json::Value::String(memory.id.clone()),
946 );
947 metadata.insert(
948 "content".to_string(),
949 serde_json::Value::String(memory.content.clone()),
950 );
951 metadata.insert(
952 "memory_type".to_string(),
953 serde_json::Value::String(format!("{:?}", memory.memory_type)),
954 );
955
956 let embedding_array: Vec<serde_json::Value> = memory
958 .embedding
959 .iter()
960 .map(|&f| serde_json::Value::Number(serde_json::Number::from_f64(f as f64).unwrap()))
961 .collect();
962 metadata.insert(
963 "embedding".to_string(),
964 serde_json::Value::Array(embedding_array),
965 );
966
967 metadata.insert(
969 "importance".to_string(),
970 serde_json::Value::Number(
971 serde_json::Number::from_f64(memory.attributes.importance as f64).unwrap(),
972 ),
973 );
974 metadata.insert(
975 "keywords".to_string(),
976 serde_json::Value::Array(
977 memory
978 .attributes
979 .keywords
980 .iter()
981 .map(|k| serde_json::Value::String(k.clone()))
982 .collect(),
983 ),
984 );
985 metadata.insert(
986 "tags".to_string(),
987 serde_json::Value::Array(
988 memory
989 .attributes
990 .tags
991 .iter()
992 .map(|t| serde_json::Value::String(t.clone()))
993 .collect(),
994 ),
995 );
996 metadata.insert(
997 "context".to_string(),
998 serde_json::Value::String(memory.attributes.context.clone()),
999 );
1000 metadata.insert(
1001 "confidence".to_string(),
1002 serde_json::Value::Number(
1003 serde_json::Number::from_f64(memory.attributes.confidence as f64).unwrap(),
1004 ),
1005 );
1006
1007 if let Some(ref source) = memory.attributes.source {
1008 metadata.insert(
1009 "source".to_string(),
1010 serde_json::Value::String(source.clone()),
1011 );
1012 }
1013
1014 if let Some(ref language) = memory.attributes.language {
1015 metadata.insert(
1016 "language".to_string(),
1017 serde_json::Value::String(language.clone()),
1018 );
1019 }
1020
1021 metadata.insert(
1023 "created_at".to_string(),
1024 serde_json::Value::String(memory.metadata.created_at.to_rfc3339()),
1025 );
1026 metadata.insert(
1027 "updated_at".to_string(),
1028 serde_json::Value::String(memory.metadata.updated_at.to_rfc3339()),
1029 );
1030 metadata.insert(
1031 "access_count".to_string(),
1032 serde_json::Value::Number(serde_json::Number::from(memory.metadata.access_count)),
1033 );
1034 metadata.insert(
1035 "last_accessed".to_string(),
1036 serde_json::Value::String(memory.metadata.last_accessed.to_rfc3339()),
1037 );
1038 metadata.insert(
1039 "version".to_string(),
1040 serde_json::Value::Number(serde_json::Number::from(memory.metadata.version)),
1041 );
1042
1043
1044
1045 metadata.insert(
1046 "is_deleted".to_string(),
1047 serde_json::Value::Bool(memory.metadata.is_deleted),
1048 );
1049
1050 Ok(metadata)
1051 }
1052
1053 fn memory_to_properties(&self, memory: &Memory) -> Result<HashMap<String, serde_json::Value>> {
1054 self.memory_to_metadata(memory)
1055 }
1056
1057 fn metadata_to_memory(&self, metadata: &HashMap<String, serde_json::Value>) -> Result<Memory> {
1058 let id = metadata
1060 .get("id")
1061 .and_then(|v| v.as_str())
1062 .ok_or_else(|| MemoryError::Internal {
1063 message: "Missing memory id in metadata".to_string(),
1064 })?
1065 .to_string();
1066
1067 let content = metadata
1068 .get("content")
1069 .and_then(|v| v.as_str())
1070 .ok_or_else(|| MemoryError::Internal {
1071 message: "Missing content in metadata".to_string(),
1072 })?
1073 .to_string();
1074
1075 let memory_type_str = metadata
1076 .get("memory_type")
1077 .and_then(|v| v.as_str())
1078 .unwrap_or("Knowledge");
1079 let memory_type = match memory_type_str {
1080 "Knowledge" => MemoryType::Knowledge,
1081 "Event" => MemoryType::Event,
1082 "Task" => MemoryType::Task,
1083 "Conversation" => MemoryType::Conversation,
1084 "Reflection" => MemoryType::Reflection,
1085 "Goal" => MemoryType::Goal,
1086 "Habit" => MemoryType::Habit,
1087 "Emotion" => MemoryType::Emotion,
1088 _ => MemoryType::Knowledge,
1089 };
1090
1091 let embedding = metadata
1092 .get("embedding")
1093 .and_then(|v| v.as_array())
1094 .map(|arr| {
1095 arr.iter()
1096 .filter_map(|v| v.as_f64().map(|f| f as f32))
1097 .collect()
1098 })
1099 .unwrap_or_else(|| vec![0.0; self.config.vector.dimension]);
1100
1101 let importance = metadata
1102 .get("importance")
1103 .and_then(|v| v.as_f64())
1104 .unwrap_or(0.5) as f32;
1105
1106 let keywords = metadata
1107 .get("keywords")
1108 .and_then(|v| v.as_array())
1109 .map(|arr| {
1110 arr.iter()
1111 .filter_map(|v| v.as_str().map(|s| s.to_string()))
1112 .collect()
1113 })
1114 .unwrap_or_default();
1115
1116 let tags = metadata
1117 .get("tags")
1118 .and_then(|v| v.as_array())
1119 .map(|arr| {
1120 arr.iter()
1121 .filter_map(|v| v.as_str().map(|s| s.to_string()))
1122 .collect()
1123 })
1124 .unwrap_or_default();
1125
1126 let created_at = metadata
1127 .get("created_at")
1128 .and_then(|v| v.as_str())
1129 .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
1130 .map(|dt| dt.with_timezone(&Utc))
1131 .unwrap_or_else(Utc::now);
1132
1133 let updated_at = metadata
1134 .get("updated_at")
1135 .and_then(|v| v.as_str())
1136 .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
1137 .map(|dt| dt.with_timezone(&Utc))
1138 .unwrap_or_else(Utc::now);
1139
1140 let attributes = MemoryAttributes {
1141 keywords,
1142 tags,
1143 context: metadata
1144 .get("context")
1145 .and_then(|v| v.as_str())
1146 .unwrap_or("")
1147 .to_string(),
1148 importance,
1149 emotion: None,
1150 source: metadata
1151 .get("source")
1152 .and_then(|v| v.as_str())
1153 .map(|s| s.to_string()),
1154 confidence: metadata
1155 .get("confidence")
1156 .and_then(|v| v.as_f64())
1157 .unwrap_or(1.0) as f32,
1158 language: metadata
1159 .get("language")
1160 .and_then(|v| v.as_str())
1161 .map(|s| s.to_string()),
1162 custom_attributes: HashMap::new(),
1163 };
1164
1165 let metadata_obj = MemoryMetadata {
1166 created_at,
1167 updated_at,
1168 access_count: metadata
1169 .get("access_count")
1170 .and_then(|v| v.as_u64())
1171 .unwrap_or(0),
1172 last_accessed: metadata
1173 .get("last_accessed")
1174 .and_then(|v| v.as_str())
1175 .and_then(|s| DateTime::parse_from_rfc3339(s).ok())
1176 .map(|dt| dt.with_timezone(&Utc))
1177 .unwrap_or_else(Utc::now),
1178 version: metadata
1179 .get("version")
1180 .and_then(|v| v.as_u64())
1181 .unwrap_or(1) as u32,
1182
1183 is_deleted: metadata
1184 .get("is_deleted")
1185 .and_then(|v| v.as_bool())
1186 .unwrap_or(false),
1187 deleted_at: None,
1188 custom_metadata: HashMap::new(),
1189 };
1190
1191 let connections = MemoryConnections {
1192 semantic_links: Vec::new(),
1193 temporal_links: Vec::new(),
1194 causal_links: Vec::new(),
1195 thematic_links: Vec::new(),
1196 custom_links: HashMap::new(),
1197 };
1198
1199 Ok(Memory {
1200 id,
1201 content,
1202 memory_type,
1203 embedding,
1204 attributes,
1205 connections,
1206 metadata: metadata_obj,
1207 })
1208 }
1209
1210 fn properties_to_memory(
1211 &self,
1212 properties: &HashMap<String, serde_json::Value>,
1213 ) -> Result<Memory> {
1214 self.metadata_to_memory(properties)
1215 }
1216
1217 fn query_filters_to_metadata_filters(
1218 &self,
1219 _filters: &QueryFilters,
1220 ) -> Result<Option<HashMap<String, serde_json::Value>>> {
1221 Ok(None)
1223 }
1224
1225 fn query_filters_to_graph_filters(
1226 &self,
1227 filters: &QueryFilters,
1228 ) -> Result<Option<HashMap<String, serde_json::Value>>> {
1229 self.query_filters_to_metadata_filters(filters)
1230 }
1231
1232 async fn calculate_temporal_relevance(
1233 &self,
1234 memory: &Memory,
1235 time_window: &(DateTime<Utc>, DateTime<Utc>),
1236 _query: &str,
1237 ) -> Result<f32> {
1238 let memory_time = memory.metadata.created_at;
1240 if memory_time >= time_window.0 && memory_time <= time_window.1 {
1241 let window_duration = time_window.1 - time_window.0;
1242 let memory_offset = memory_time - time_window.0;
1243 Ok(1.0 - (memory_offset.num_seconds() as f32 / window_duration.num_seconds() as f32))
1244 } else {
1245 Ok(0.0)
1246 }
1247 }
1248
1249 fn extract_causal_keywords(&self, text: &str) -> Result<Vec<String>> {
1250 let causal_words = vec!["因为", "所以", "导致", "引起", "造成", "由于", "结果"];
1251 let keywords = causal_words
1252 .into_iter()
1253 .filter(|word| text.contains(word))
1254 .map(|s| s.to_string())
1255 .collect();
1256 Ok(keywords)
1257 }
1258
1259 async fn calculate_causal_relevance(
1260 &self,
1261 memory: &Memory,
1262 keywords: &[String],
1263 ) -> Result<f32> {
1264 let content_lower = memory.content.to_lowercase();
1265 let matches = keywords
1266 .iter()
1267 .filter(|k| content_lower.contains(&k.to_lowercase()))
1268 .count();
1269 Ok(matches as f32 / keywords.len().max(1) as f32)
1270 }
1271
1272 fn extract_themes(&self, text: &str) -> Result<Vec<String>> {
1273 let words: Vec<String> = text
1275 .split_whitespace()
1276 .filter(|w| w.len() > 3)
1277 .take(10)
1278 .map(|s| s.to_string())
1279 .collect();
1280 Ok(words)
1281 }
1282
1283 fn create_theme_filters(
1284 &self,
1285 themes: &[String],
1286 ) -> Result<Option<HashMap<String, serde_json::Value>>> {
1287 let mut filters = HashMap::new();
1288 filters.insert(
1289 "themes".to_string(),
1290 serde_json::Value::Array(
1291 themes
1292 .iter()
1293 .map(|t| serde_json::Value::String(t.clone()))
1294 .collect(),
1295 ),
1296 );
1297 Ok(Some(filters))
1298 }
1299
1300 async fn calculate_thematic_relevance(
1301 &self,
1302 memory: &Memory,
1303 themes: &[String],
1304 ) -> Result<f32> {
1305 let content_lower = memory.content.to_lowercase();
1306 let matches = themes
1307 .iter()
1308 .filter(|theme| content_lower.contains(&theme.to_lowercase()))
1309 .count();
1310 Ok(matches as f32 / themes.len().max(1) as f32)
1311 }
1312
1313 async fn fuse_retrieval_results(
1314 &self,
1315 results_list: Vec<Vec<RetrievalResult>>,
1316 weights: &QueryWeights,
1317 ) -> Result<Vec<RetrievalResult>> {
1318 let mut fused_results = HashMap::new();
1319
1320 for (i, results) in results_list.iter().enumerate() {
1321 let weight = match i {
1322 0 => weights.semantic_weight,
1323 1 => weights.temporal_weight,
1324 2 => weights.importance_weight,
1325 _ => 0.1,
1326 };
1327
1328 for result in results {
1329 let entry = fused_results
1330 .entry(result.memory.id.clone())
1331 .or_insert_with(|| result.clone());
1332 entry.relevance_score += result.relevance_score * weight;
1333 }
1334 }
1335
1336 let mut final_results: Vec<RetrievalResult> = fused_results.into_values().collect();
1337 final_results.sort_by(|a, b| b.relevance_score.partial_cmp(&a.relevance_score).unwrap());
1338
1339 Ok(final_results)
1340 }
1341
1342 async fn compute_personalized_pagerank(
1343 &self,
1344 personalization: &PersonalizationVector,
1345 query: &str,
1346 ) -> Result<HashMap<MemoryId, f32>> {
1347 let mut scores = HashMap::new();
1349
1350 for (preference, weight) in &personalization.preferences {
1352 if query.contains(preference) {
1353 scores.insert(format!("memory_{}", preference), *weight);
1354 }
1355 }
1356
1357 Ok(scores)
1358 }
1359}
1360
1361impl LinkAnalyzer {
1364 fn new(config: &Config) -> Self {
1365 Self {
1366 semantic_threshold: config.vector.similarity_threshold,
1367 temporal_window: Duration::hours(24),
1368 causal_patterns: vec!["因为".to_string(), "所以".to_string(), "导致".to_string()],
1369 thematic_keywords: HashMap::new(),
1370 }
1371 }
1372
1373 async fn discover_connections(
1374 &self,
1375 memory: &Memory,
1376 context: &Context,
1377 ) -> Result<Vec<Connection>> {
1378 let mut connections = Vec::new();
1379
1380 for recent_memory_id in &context.recent_memories {
1382 if recent_memory_id != &memory.id {
1383 let connection = Connection::new(
1384 memory.id.clone(),
1385 recent_memory_id.clone(),
1386 ConnectionType::Temporal,
1387 0.7,
1388 );
1389 connections.push(connection);
1390 }
1391 }
1392
1393 Ok(connections)
1394 }
1395}
1396
1397impl ImportanceCalculator {
1398 fn new(_config: &Config) -> Self {
1399 Self {
1400 access_weight: 0.3,
1401 recency_weight: 0.2,
1402 connection_weight: 0.2,
1403 feedback_weight: 0.2,
1404 content_weight: 0.1,
1405 }
1406 }
1407
1408 async fn calculate_initial_importance(
1409 &self,
1410 memory: &Memory,
1411 context: &Context,
1412 ) -> Result<f32> {
1413 let mut importance = 0.5; let content_factor = (memory.content.len() as f32 / 1000.0).min(1.0);
1417 importance += content_factor * self.content_weight;
1418
1419 match context.priority {
1421 Priority::Critical => importance += 0.3,
1422 Priority::High => importance += 0.2,
1423 Priority::Normal => {}
1424 Priority::Low => importance -= 0.1,
1425 }
1426
1427 Ok(importance.clamp(0.0, 1.0))
1428 }
1429}
1430
1431impl EvolutionEngine {
1432 fn new(config: &Config) -> Self {
1433 Self {
1434 decay_factor: config.learning.importance_decay_factor,
1435 reinforcement_factor: 1.05,
1436 pruning_threshold: 0.1,
1437 evolution_interval: Duration::hours(config.learning.learning_interval_hours as i64),
1438 }
1439 }
1440
1441 async fn evolve(&self, trigger: &EvolutionTrigger, _db: &VectorGraphDB) -> Result<u64> {
1442 match trigger {
1443 EvolutionTrigger::TimeDecay => {
1444 Ok(0)
1446 }
1447 EvolutionTrigger::UserFeedback(_memory_id, _score) => {
1448 Ok(1)
1450 }
1451 _ => Ok(0),
1452 }
1453 }
1454}
1455
1456impl RetrievalEngine {
1457 async fn new(config: &Config) -> Result<Self> {
1458 Ok(Self {
1459 pagerank_config: PageRankConfig {
1460 damping_factor: config.graph.pagerank.damping_factor,
1461 max_iterations: config.graph.pagerank.max_iterations,
1462 convergence_threshold: config.graph.pagerank.convergence_threshold,
1463 personalization_weight: config.graph.pagerank.personalization_weight,
1464 },
1465 fusion_weights: QueryWeights::default(),
1466 personalization_cache: Arc::new(RwLock::new(PersonalizationVector::default())),
1467 })
1468 }
1469
1470 async fn get_personalization_vector(&self) -> Result<PersonalizationVector> {
1471 let cache = self.personalization_cache.read().await;
1472 Ok(cache.clone())
1473 }
1474}
1475
1476#[cfg(test)]
1477mod tests {
1478 use super::*;
1479 use crate::database::VectorGraphDB;
1480 use tempfile::NamedTempFile;
1481
1482 async fn create_test_memory_manager() -> MemoryManager {
1483 let temp_file = NamedTempFile::new().unwrap();
1484 let db_url = format!("sqlite://{}", temp_file.path().display());
1485
1486 let config = Config {
1487 database: crate::config::DatabaseConfig {
1488 url: db_url,
1489 ..Default::default()
1490 },
1491 vector: crate::config::VectorConfig {
1492 similarity_threshold: 0.0, ..Default::default()
1494 },
1495 ..Default::default()
1496 };
1497
1498 let db = Arc::new(VectorGraphDB::new(config.clone()).await.unwrap());
1499 MemoryManager::new(db, config).await.unwrap()
1500 }
1501
1502 #[tokio::test]
1503 async fn test_create_memory() {
1504 let manager = create_test_memory_manager().await;
1505
1506 let request = CreateMemoryRequest {
1507 content: "这是一个测试记忆".to_string(),
1508 context: Context::default(),
1509 attributes: None,
1510 force_connections: None,
1511 };
1512
1513 let memory = manager.create_memory_from_request(request).await.unwrap();
1514 assert_eq!(memory.content, "这是一个测试记忆");
1515 assert!(!memory.id.is_empty());
1516 assert!(!memory.embedding.is_empty());
1517 }
1518
1519 #[tokio::test]
1520 async fn test_semantic_retrieval() {
1521 let manager = create_test_memory_manager().await;
1522
1523 let request = CreateMemoryRequest {
1525 content: "人工智能的发展历程".to_string(),
1526 context: Context::default(),
1527 attributes: None,
1528 force_connections: None,
1529 };
1530 manager.create_memory_from_request(request).await.unwrap();
1531
1532 let query = Query {
1534 text: "AI发展".to_string(),
1535 query_type: QueryType::Semantic,
1536 filters: QueryFilters::default(),
1537 limit: Some(10),
1538 offset: None,
1539 sort_by: None,
1540 weights: QueryWeights::default(),
1541 };
1542
1543 let results = manager
1544 .retrieve_memories(&query, &Context::default())
1545 .await
1546 .unwrap();
1547 assert!(!results.is_empty());
1548 }
1549
1550 #[tokio::test]
1551 async fn test_memory_stats() {
1552 let manager = create_test_memory_manager().await;
1553
1554 let initial_stats = manager.get_stats().await;
1555 assert_eq!(initial_stats.total_memories, 0);
1556
1557 let request = CreateMemoryRequest {
1559 content: "测试统计".to_string(),
1560 context: Context::default(),
1561 attributes: None,
1562 force_connections: None,
1563 };
1564 manager.create_memory_from_request(request).await.unwrap();
1565
1566 let updated_stats = manager.get_stats().await;
1567 assert_eq!(updated_stats.total_memories, 1);
1568 assert_eq!(updated_stats.creation_count, 1);
1569 }
1570}