anya_core/ml/
mod.rs

1//! Machine Learning module
2//!
3//! This module provides machine learning capabilities for the Anya system,
4//! including model management, training, prediction, and federated learning.
5
6use std::error::Error;
7// [AIR-3][AIS-3][BPC-3][RES-3] Import necessary dependencies for ML module
8// This follows official Bitcoin Improvement Proposals (BIPs) standards for ML operations
9use crate::{AnyaError, AnyaResult};
10// Re-export these types to make them public
11pub use crate::dao::{Proposal, ProposalMetrics, RiskMetrics};
12// Import MLModel trait from service module
13pub use crate::ml::service::MLModel;
14use std::collections::HashMap;
15use std::path::Path;
16use std::sync::{Arc, Mutex};
17
18mod service;
19pub use service::MLService;
20
21// ML agent system module
22pub mod agent_system;
23pub use agent_system::MLAgentSystem;
24
25/// Configuration options for ML functionality
26#[derive(Debug, Clone)]
27pub struct MLConfig {
28    /// Whether ML functionality is enabled
29    pub enabled: bool,
30    /// Path to model storage
31    pub model_path: Option<String>,
32    /// Whether to use GPU for ML
33    pub use_gpu: bool,
34    /// Whether to enable federated learning
35    pub federated_learning: bool,
36    /// Maximum model size in bytes
37    pub max_model_size: usize,
38}
39
40impl Default for MLConfig {
41    fn default() -> Self {
42        Self {
43            enabled: true,
44            model_path: Some("./data/models".to_string()),
45            use_gpu: true,
46            federated_learning: true,
47            max_model_size: 100 * 1024 * 1024, // 100 MB
48        }
49    }
50}
51
52/// Core ML system implementation
53pub struct MLSystem {
54    config: MLConfig,
55    service: MLService,
56    models: HashMap<String, Arc<Mutex<dyn MLModel>>>,
57}
58
59impl std::fmt::Debug for MLSystem {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        f.debug_struct("MLSystem")
62            .field("config", &self.config)
63            .field("service", &"<MLService>")
64            .field("models", &format!("{} models", self.models.len()))
65            .finish()
66    }
67}
68
69// Implement Send and Sync for MLSystem since its fields are all Send + Sync
70unsafe impl Send for MLSystem {}
71unsafe impl Sync for MLSystem {}
72
73impl MLSystem {
74    /// Create a new MLSystem with the given configuration
75    pub fn new(config: MLConfig) -> AnyaResult<Self> {
76        if !config.enabled {
77            return Ok(Self {
78                config,
79                service: MLService::new(),
80                models: HashMap::new(),
81            });
82        }
83
84        // Create model directory if it doesn't exist
85        if let Some(path) = &config.model_path {
86            if !Path::new(path).exists() {
87                std::fs::create_dir_all(path)
88                    .map_err(|e| AnyaError::ML(format!("Failed to create model directory: {e}")))?;
89            }
90        }
91
92        let ml_service = MLService::new();
93
94        Ok(Self {
95            config,
96            service: ml_service,
97            models: HashMap::new(),
98        })
99    }
100
101    /// Get the ML service
102    pub fn service(&self) -> &MLService {
103        &self.service
104    }
105
106    /// Register a model with the ML system
107    pub fn register_model<M: MLModel + 'static>(&mut self, name: &str, model: M) -> AnyaResult<()> {
108        self.models
109            .insert(name.to_string(), Arc::new(Mutex::new(model)));
110        Ok(())
111    }
112
113    /// Get a model by name
114    pub fn get_model(&self, name: &str) -> Option<Arc<Mutex<dyn MLModel>>> {
115        self.models.get(name).cloned()
116    }
117
118    /// Get health metrics for the ML system
119    pub fn get_health_metrics(&self) -> HashMap<String, f64> {
120        let mut metrics = HashMap::new();
121        metrics.insert("model_count".to_string(), self.models.len() as f64);
122        metrics.insert(
123            "enabled".to_string(),
124            if self.config.enabled { 1.0 } else { 0.0 },
125        );
126        metrics.insert(
127            "federated_learning".to_string(),
128            if self.config.federated_learning {
129                1.0
130            } else {
131                0.0
132            },
133        );
134
135        // Add more detailed metrics here if needed
136        metrics
137    }
138
139    /// List all registered models
140    pub fn list_models(&self) -> Vec<String> {
141        self.models.keys().cloned().collect()
142    }
143
144    /// Get health metrics for all models
145    pub fn get_model_health_metrics(&self) -> HashMap<String, HashMap<String, f64>> {
146        let mut metrics = HashMap::new();
147
148        // Add service metrics
149        metrics.insert("service".to_string(), self.service.get_health_metrics());
150
151        // Add model-specific metrics
152        for (name, model) in &self.models {
153            if let Ok(model_lock) = model.lock() {
154                metrics.insert(name.clone(), model_lock.get_health_metrics());
155            }
156        }
157
158        metrics
159    }
160}
161
162/// Trait for ML models (re-exported from service module)
163/// This is just a placeholder to avoid duplicate definitions
164pub trait MLModelPlaceholder {}
165
166/// ML model input
167#[derive(Debug, Clone)]
168pub struct MLInput {
169    /// Features for the model
170    pub features: Vec<f64>,
171    /// Label for supervised learning
172    pub label: f64,
173    /// Additional metadata
174    pub metadata: Option<HashMap<String, String>>,
175}
176
177/// ML model output
178#[derive(Debug, Clone)]
179pub struct MLOutput {
180    /// Model prediction
181    pub prediction: f64,
182    /// Model confidence
183    pub confidence: f64,
184    /// Additional information
185    pub additional_info: Option<HashMap<String, Vec<f64>>>,
186}
187
188/// Federated learning node
189pub struct FederatedNode {
190    /// Node identifier
191    pub id: String,
192    /// Node URL
193    pub url: String,
194    /// Public key for verification
195    pub public_key: Vec<u8>,
196}
197
198/// Federated learning manager
199#[allow(dead_code)]
200pub struct FederatedLearningManager {
201    /// Known nodes
202    nodes: Vec<FederatedNode>,
203    /// Aggregation method
204    aggregation_method: String,
205}
206
207impl Default for FederatedLearningManager {
208    fn default() -> Self {
209        Self::new()
210    }
211}
212
213impl FederatedLearningManager {
214    /// Create a new federated learning manager
215    pub fn new() -> Self {
216        Self {
217            nodes: Vec::new(),
218            aggregation_method: "average".to_string(),
219        }
220    }
221
222    /// Add a node to the federation
223    pub fn add_node(&mut self, node: FederatedNode) {
224        self.nodes.push(node);
225    }
226
227    /// Remove a node from the federation
228    pub fn remove_node(&mut self, node_id: &str) -> Result<(), Box<dyn Error>> {
229        self.nodes.retain(|n| n.id != node_id);
230        Ok(())
231    }
232
233    /// List all nodes in the federation
234    pub fn list_nodes(&self) -> &[FederatedNode] {
235        &self.nodes
236    }
237}
238
239// AIP-002: ML Module Integration
240// Exports ML-based agent checker functionality
241
242// Agent checker module
243pub mod agent_checker;
244
245// Re-exports for convenience
246pub use agent_checker::AgentChecker;
247pub use agent_checker::ComponentStatus;
248pub use agent_checker::SystemHealth;
249pub use agent_checker::SystemStage;
250
251// Development, Production, and Release thresholds
252pub const DEV_THRESHOLD: f64 = 0.60;
253pub const PROD_THRESHOLD: f64 = 0.90;
254pub const RELEASE_THRESHOLD: f64 = 0.99;
255
256/// Helper function to create an agent checker with default auto-save frequency (20)
257pub fn create_agent_checker() -> AgentChecker {
258    AgentChecker::new(20)
259}
260
261/// Helper function to determine if a system is ready for a given stage
262pub fn is_ready_for_stage(health: f64, stage: SystemStage) -> bool {
263    match stage {
264        SystemStage::Development => health >= DEV_THRESHOLD,
265        SystemStage::Production => health >= PROD_THRESHOLD,
266        SystemStage::Release => health >= RELEASE_THRESHOLD,
267        SystemStage::Unavailable => false,
268    }
269}
270
271pub mod agents;
272pub use agents::*;
273
274pub mod models;
275#[cfg(test)]
276mod tests {
277    use super::*;
278
279    #[test]
280    fn test_stage_readiness() -> Result<(), Box<dyn Error>> {
281        assert!(!is_ready_for_stage(0.55, SystemStage::Development));
282        assert!(is_ready_for_stage(0.65, SystemStage::Development));
283        assert!(!is_ready_for_stage(0.85, SystemStage::Production));
284        assert!(is_ready_for_stage(0.95, SystemStage::Production));
285        Ok(())
286    }
287}