1pub mod consolidation;
25pub mod episodic;
26pub mod semantic;
27pub mod working;
28
29pub use consolidation::{ConsolidationConfig, SleepConsolidation};
30pub use episodic::{Episode, EpisodeQuery, EpisodicMemory};
31pub use semantic::{Concept, ConceptGraph, SemanticMemory};
32pub use working::{WorkingMemory, WorkingMemoryConfig};
33
34use ronn_core::tensor::Tensor;
35use std::time::{SystemTime, UNIX_EPOCH};
36use thiserror::Error;
37
38#[derive(Error, Debug)]
40pub enum MemoryError {
41 #[error("Working memory error: {0}")]
42 WorkingMemory(String),
43
44 #[error("Episodic memory error: {0}")]
45 EpisodicMemory(String),
46
47 #[error("Semantic memory error: {0}")]
48 SemanticMemory(String),
49
50 #[error("Consolidation error: {0}")]
51 Consolidation(String),
52
53 #[error("Core error: {0}")]
54 Core(#[from] ronn_core::error::CoreError),
55}
56
57pub type Result<T> = std::result::Result<T, MemoryError>;
58
59pub struct MultiTierMemory {
61 working: WorkingMemory,
62 episodic: EpisodicMemory,
63 semantic: SemanticMemory,
64 consolidation: SleepConsolidation,
65}
66
67impl MultiTierMemory {
68 pub fn new() -> Self {
70 Self {
71 working: WorkingMemory::new(WorkingMemoryConfig::default()),
72 episodic: EpisodicMemory::new(),
73 semantic: SemanticMemory::new(),
74 consolidation: SleepConsolidation::new(ConsolidationConfig::default()),
75 }
76 }
77
78 pub fn store(&mut self, data: Tensor, importance: f64) -> Result<MemoryId> {
80 let id = self.working.store(data, importance)?;
82
83 if importance > 0.7 {
85 let tensor = self.working.get(id)?;
86 let episode = Episode {
87 id,
88 data: tensor,
89 timestamp: current_timestamp(),
90 importance,
91 };
92 self.episodic.store_episode(episode)?;
93 }
94
95 Ok(id)
96 }
97
98 pub fn retrieve(&self, id: MemoryId) -> Result<Option<Tensor>> {
100 if let Ok(tensor) = self.working.get(id) {
102 return Ok(Some(tensor));
103 }
104
105 if let Some(episode) = self.episodic.get_episode(id) {
107 return Ok(Some(episode.data));
108 }
109
110 Ok(None)
111 }
112
113 pub fn search_similar(&self, query: &Tensor, limit: usize) -> Result<Vec<MemoryId>> {
115 self.working.search_similar(query, limit)
117 }
118
119 pub async fn consolidate(&mut self) -> Result<ConsolidationResult> {
121 let working_items = self.working.drain_old_items()?;
123 let items_count = working_items.len();
124
125 for (id, tensor, importance) in working_items {
126 if importance > 0.5 {
127 let episode = Episode {
128 id,
129 data: tensor,
130 timestamp: current_timestamp(),
131 importance,
132 };
133 self.episodic.store_episode(episode)?;
134 }
135 }
136
137 let patterns = self.consolidation.extract_patterns(&self.episodic).await?;
139 let patterns_count = patterns.len();
140
141 for concept in patterns {
142 self.semantic.store_concept(concept)?;
143 }
144
145 Ok(ConsolidationResult {
146 episodes_consolidated: items_count,
147 patterns_extracted: patterns_count,
148 })
149 }
150
151 pub fn stats(&self) -> MemoryStats {
153 MemoryStats {
154 working_items: self.working.len(),
155 episodic_episodes: self.episodic.len(),
156 semantic_concepts: self.semantic.len(),
157 }
158 }
159}
160
161impl Default for MultiTierMemory {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167pub type MemoryId = u64;
169
170#[derive(Debug, Clone)]
172pub struct ConsolidationResult {
173 pub episodes_consolidated: usize,
174 pub patterns_extracted: usize,
175}
176
177#[derive(Debug, Clone)]
179pub struct MemoryStats {
180 pub working_items: usize,
181 pub episodic_episodes: usize,
182 pub semantic_concepts: usize,
183}
184
185pub fn current_timestamp() -> u64 {
187 SystemTime::now()
188 .duration_since(UNIX_EPOCH)
189 .unwrap()
190 .as_millis() as u64
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196 use ronn_core::types::{DataType, TensorLayout};
197
198 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
199
200 #[test]
201 fn test_memory_creation() {
202 let memory = MultiTierMemory::new();
203 let stats = memory.stats();
204
205 assert_eq!(stats.working_items, 0);
206 assert_eq!(stats.episodic_episodes, 0);
207 assert_eq!(stats.semantic_concepts, 0);
208 }
209
210 #[test]
211 fn test_store_and_retrieve() -> Result<()> {
212 let mut memory = MultiTierMemory::new();
213
214 let data = vec![1.0f32, 2.0, 3.0, 4.0];
215 let tensor = Tensor::from_data(data, vec![1, 4], DataType::F32, TensorLayout::RowMajor)?;
216
217 let id = memory.store(tensor.clone(), 0.3)?;
219
220 let retrieved = memory.retrieve(id)?;
222 assert!(retrieved.is_some());
223
224 Ok(())
225 }
226
227 #[test]
228 fn test_high_importance_storage() -> Result<()> {
229 let mut memory = MultiTierMemory::new();
230
231 let data = vec![1.0f32, 2.0, 3.0, 4.0];
232 let tensor = Tensor::from_data(data, vec![1, 4], DataType::F32, TensorLayout::RowMajor)?;
233
234 let id = memory.store(tensor, 0.9)?;
236
237 let stats = memory.stats();
238 assert_eq!(stats.working_items, 1);
239 assert_eq!(stats.episodic_episodes, 1); Ok(())
242 }
243
244 #[tokio::test]
245 async fn test_consolidation() -> Result<()> {
246 let mut memory = MultiTierMemory::new();
247
248 for i in 0..5 {
250 let data = vec![i as f32; 4];
251 let tensor =
252 Tensor::from_data(data, vec![1, 4], DataType::F32, TensorLayout::RowMajor)?;
253 memory.store(tensor, 0.6)?;
254 }
255
256 let result = memory.consolidate().await?;
258
259 assert!(result.episodes_consolidated >= 0);
261 assert!(result.patterns_extracted >= 0);
262
263 Ok(())
264 }
265}