lmm_agent/cognition/learning/store.rs
1// Copyright 2026 Mahmoud Harmouch.
2//
3// Licensed under the MIT license
4// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
5// option. This file may not be copied, modified, or distributed
6// except according to those terms.
7
8//! # `LearningStore` - persistent serialisation of HELM learning state.
9//!
10//! `LearningStore` serialises and deserialises the complete `LearningEngine`
11//! state (Q-table, meta-prototypes, distiller fingerprints, elastic guard
12//! activation counts, PMI pair counts) to/from a JSON file on disk.
13//!
14//! This provides **long-term persistence** across process restarts: an agent
15//! that has been saved can be restored and continue learning from where it
16//! left off, fulfilling the *smart lifelong learning* requirement.
17//!
18//! ## Examples
19//!
20//! ```rust
21//! use lmm_agent::cognition::learning::store::LearningStore;
22//! use lmm_agent::cognition::learning::engine::LearningEngine;
23//! use lmm_agent::cognition::learning::config::LearningConfig;
24//!
25//! let engine = LearningEngine::new(LearningConfig::default());
26//! let path = std::env::temp_dir().join(format!("test_helm_store_{}.json", uuid::Uuid::new_v4()));
27//!
28//! LearningStore::save(&engine, &path).unwrap();
29//! let loaded = LearningStore::load(&path).unwrap();
30//! assert_eq!(loaded.q_table().state_count(), engine.q_table().state_count());
31//! ```
32
33use crate::cognition::learning::engine::LearningEngine;
34use anyhow::{Result, anyhow};
35use std::fs;
36use std::path::Path;
37
38/// Round-trip serialisation helper for [`LearningEngine`].
39pub struct LearningStore;
40
41impl LearningStore {
42 /// Serialises `engine` to a JSON file at `path`.
43 ///
44 /// Creates the file (and all parent directories) if they do not exist.
45 ///
46 /// # Errors
47 ///
48 /// Returns an error if serialisation fails or the file cannot be created.
49 ///
50 /// # Examples
51 ///
52 /// ```rust
53 /// use lmm_agent::cognition::learning::store::LearningStore;
54 /// use lmm_agent::cognition::learning::engine::LearningEngine;
55 /// use lmm_agent::cognition::learning::config::LearningConfig;
56 ///
57 /// let engine = LearningEngine::new(LearningConfig::default());
58 /// let path = std::env::temp_dir().join(format!("helm_doctest_{}.json", uuid::Uuid::new_v4()));
59 /// LearningStore::save(&engine, &path).unwrap();
60 /// ```
61 pub fn save(engine: &LearningEngine, path: &Path) -> Result<()> {
62 if let Some(parent) = path.parent()
63 && !parent.as_os_str().is_empty()
64 {
65 fs::create_dir_all(parent)
66 .map_err(|e| anyhow!("Cannot create dir {:?}: {e}", parent))?;
67 }
68 let json = serde_json::to_string_pretty(engine)
69 .map_err(|e| anyhow!("Serialisation error: {e}"))?;
70 fs::write(path, &json).map_err(|e| anyhow!("Cannot write {:?}: {e}", path))
71 }
72
73 /// Deserialises a [`LearningEngine`] from the JSON file at `path`.
74 ///
75 /// # Errors
76 ///
77 /// Returns an error if the file cannot be read or if the JSON is malformed.
78 ///
79 /// # Examples
80 ///
81 /// ```rust
82 /// use lmm_agent::cognition::learning::store::LearningStore;
83 /// use lmm_agent::cognition::learning::engine::LearningEngine;
84 /// use lmm_agent::cognition::learning::config::LearningConfig;
85 ///
86 /// let engine = LearningEngine::new(LearningConfig::default());
87 /// let path = std::env::temp_dir().join(format!("helm_load_doctest_{}.json", uuid::Uuid::new_v4()));
88 /// LearningStore::save(&engine, &path).unwrap();
89 /// let loaded = LearningStore::load(&path).unwrap();
90 /// assert_eq!(loaded.config().alpha, engine.config().alpha);
91 /// ```
92 pub fn load(path: &Path) -> Result<LearningEngine> {
93 let json = fs::read_to_string(path).map_err(|e| anyhow!("Cannot read {:?}: {e}", path))?;
94 serde_json::from_str(&json).map_err(|e| anyhow!("Deserialisation error in {:?}: {e}", path))
95 }
96}
97
98// Copyright 2026 Mahmoud Harmouch.
99//
100// Licensed under the MIT license
101// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
102// option. This file may not be copied, modified, or distributed
103// except according to those terms.