codemem_engine/consolidation/
forget.rs1use super::ConsolidationResult;
2use crate::CodememEngine;
3use codemem_core::{CodememError, GraphBackend, VectorBackend};
4use serde_json::json;
5
6impl CodememEngine {
7 pub fn consolidate_forget(
9 &self,
10 importance_threshold: Option<f64>,
11 target_tags: Option<&[String]>,
12 max_access_count: Option<u32>,
13 ) -> Result<ConsolidationResult, CodememError> {
14 let importance_threshold = importance_threshold.unwrap_or(0.1);
15 let max_access_count = max_access_count.unwrap_or(0);
16
17 let ids = match target_tags {
20 Some(tags) if !tags.is_empty() => {
21 self.find_forgettable_by_tags(importance_threshold, tags, max_access_count)?
22 }
23 _ if max_access_count > 0 => {
24 let all = self.storage.list_memories_filtered(None, None)?;
26 all.into_iter()
27 .filter(|m| {
28 m.importance < importance_threshold && m.access_count <= max_access_count
29 })
30 .map(|m| m.id)
31 .collect()
32 }
33 _ => self.storage.find_forgettable(importance_threshold)?,
34 };
35
36 let deleted = ids.len();
37
38 for batch in ids.chunks(100) {
42 let batch_refs: Vec<&str> = batch.iter().map(|s| s.as_str()).collect();
43 if let Err(e) = self.storage.delete_memories_batch_cascade(&batch_refs) {
44 tracing::warn!(
45 "Failed to batch-delete {} memories during forget consolidation: {e}",
46 batch.len()
47 );
48 }
49
50 let mut graph = self.lock_graph()?;
52 let mut vector = self.lock_vector()?;
53 let mut bm25 = self.lock_bm25()?;
54 for id in batch {
55 if let Err(e) = graph.remove_node(id) {
56 tracing::warn!(
57 "Failed to remove {id} from graph during forget consolidation: {e}"
58 );
59 }
60 if let Err(e) = vector.remove(id) {
61 tracing::warn!(
62 "Failed to remove {id} from vector index during forget consolidation: {e}"
63 );
64 }
65 bm25.remove_document(id);
66 }
67 drop(bm25);
68 drop(vector);
69 drop(graph);
70 }
71
72 if deleted > 0 {
74 let mut vector = self.lock_vector()?;
75 self.rebuild_vector_index_internal(&mut vector);
76 drop(vector);
77 }
78
79 self.save_index();
80
81 if let Err(e) = self.storage.insert_consolidation_log("forget", deleted) {
82 tracing::warn!("Failed to log forget consolidation: {e}");
83 }
84
85 Ok(ConsolidationResult {
86 cycle: "forget".to_string(),
87 affected: deleted,
88 details: json!({
89 "threshold": importance_threshold,
90 }),
91 })
92 }
93}