Skip to main content

aingle_ai/
types.rs

1// Copyright 2019-2026 Apilium Technologies OÜ. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0 OR Commercial
3
4//! Common types for the AI module
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9/// Feature vector for ML operations
10pub type FeatureVector = Vec<f32>;
11
12/// Embedding representation
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Embedding {
15    /// Vector representation
16    pub vector: FeatureVector,
17    /// Dimensionality
18    pub dim: usize,
19}
20
21impl Embedding {
22    /// Create a new embedding
23    pub fn new(vector: FeatureVector) -> Self {
24        let dim = vector.len();
25        Self { vector, dim }
26    }
27
28    /// Create a zero embedding of given dimension
29    pub fn zeros(dim: usize) -> Self {
30        Self {
31            vector: vec![0.0; dim],
32            dim,
33        }
34    }
35
36    /// Compute cosine similarity with another embedding
37    pub fn cosine_similarity(&self, other: &Embedding) -> f32 {
38        if self.dim != other.dim {
39            return 0.0;
40        }
41
42        let dot: f32 = self
43            .vector
44            .iter()
45            .zip(other.vector.iter())
46            .map(|(a, b)| a * b)
47            .sum();
48
49        let norm_a: f32 = self.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
50        let norm_b: f32 = other.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
51
52        if norm_a == 0.0 || norm_b == 0.0 {
53            0.0
54        } else {
55            dot / (norm_a * norm_b)
56        }
57    }
58
59    /// Compute L2 distance
60    pub fn l2_distance(&self, other: &Embedding) -> f32 {
61        if self.dim != other.dim {
62            return f32::MAX;
63        }
64
65        self.vector
66            .iter()
67            .zip(other.vector.iter())
68            .map(|(a, b)| (a - b).powi(2))
69            .sum::<f32>()
70            .sqrt()
71    }
72}
73
74/// Pattern extracted from transactions
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Pattern {
77    /// Pattern identifier
78    pub id: PatternId,
79    /// Feature embedding
80    pub embedding: Embedding,
81    /// Metadata
82    pub metadata: HashMap<String, String>,
83    /// Timestamp when pattern was created
84    pub created_at: u64,
85}
86
87/// Pattern identifier
88pub type PatternId = [u8; 32];
89
90/// Generate a pattern ID from bytes
91pub fn pattern_id(data: &[u8]) -> PatternId {
92    use blake2::{Blake2b512, Digest};
93    let mut hasher = Blake2b512::new();
94    hasher.update(data);
95    let result = hasher.finalize();
96    let mut id = [0u8; 32];
97    id.copy_from_slice(&result[..32]);
98    id
99}
100
101/// Memory match result
102#[derive(Debug, Clone)]
103pub struct MemoryMatch {
104    /// Matched pattern
105    pub pattern: Pattern,
106    /// Similarity score (0.0 - 1.0)
107    pub similarity: f32,
108    /// Source (short-term or long-term)
109    pub source: MemorySource,
110}
111
112/// Source of memory match
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum MemorySource {
115    /// From short-term memory
116    ShortTerm,
117    /// From long-term memory
118    LongTerm,
119}
120
121/// Result of processing a transaction through Titans memory
122#[derive(Debug, Clone)]
123pub struct ProcessResult {
124    /// Relevance score (0.0 - 1.0)
125    pub relevance: f32,
126    /// Surprise score (0.0 - 1.0)
127    pub surprise: f32,
128    /// Whether stored in long-term memory
129    pub stored_long_term: bool,
130    /// Anomaly detection result
131    pub anomaly: Option<AnomalyResult>,
132}
133
134/// Anomaly detection result
135#[derive(Debug, Clone)]
136pub struct AnomalyResult {
137    /// Is this an anomaly?
138    pub is_anomaly: bool,
139    /// Confidence level (0.0 - 1.0)
140    pub confidence: f32,
141    /// Explanation
142    pub reason: String,
143}
144
145/// Transaction type for AI processing
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct AiTransaction {
148    /// Transaction hash
149    pub hash: [u8; 32],
150    /// Timestamp
151    pub timestamp: u64,
152    /// Agent who created the transaction
153    pub agent: [u8; 32],
154    /// Entry type
155    pub entry_type: String,
156    /// Serialized entry data
157    pub data: Vec<u8>,
158    /// Entry size in bytes
159    pub size: usize,
160}
161
162impl AiTransaction {
163    /// Extract features from transaction
164    pub fn extract_features(&self) -> FeatureVector {
165        let mut features = Vec::with_capacity(16);
166
167        // Size feature (normalized)
168        features.push((self.size as f32).ln().max(0.0) / 20.0);
169
170        // Time features (hour of day, day of week)
171        let timestamp_secs = self.timestamp / 1000;
172        let hour = ((timestamp_secs / 3600) % 24) as f32 / 24.0;
173        features.push(hour);
174
175        // Entry type hash features (first 4 bytes as float)
176        let type_hash = pattern_id(self.entry_type.as_bytes());
177        for i in 0..4 {
178            features.push(type_hash[i] as f32 / 255.0);
179        }
180
181        // Agent features (first 4 bytes)
182        for i in 0..4 {
183            features.push(self.agent[i] as f32 / 255.0);
184        }
185
186        // Data entropy approximation (byte distribution)
187        if !self.data.is_empty() {
188            let mut byte_counts = [0u32; 256];
189            for &byte in &self.data {
190                byte_counts[byte as usize] += 1;
191            }
192            let len = self.data.len() as f32;
193            let entropy: f32 = byte_counts
194                .iter()
195                .filter(|&&c| c > 0)
196                .map(|&c| {
197                    let p = c as f32 / len;
198                    -p * p.ln()
199                })
200                .sum();
201            features.push(entropy / 8.0); // Normalize to ~1.0 for random data
202        } else {
203            features.push(0.0);
204        }
205
206        // Pad to 16 features
207        while features.len() < 16 {
208            features.push(0.0);
209        }
210
211        features
212    }
213
214    /// Convert to pattern
215    pub fn to_pattern(&self) -> Pattern {
216        let embedding = Embedding::new(self.extract_features());
217        Pattern {
218            id: self.hash,
219            embedding,
220            metadata: HashMap::new(),
221            created_at: self.timestamp,
222        }
223    }
224}
225
226/// Validation prediction result
227#[derive(Debug, Clone)]
228pub struct ValidationPrediction {
229    /// Likely to be valid?
230    pub likely_valid: bool,
231    /// Confidence (0.0 - 1.0)
232    pub confidence: f32,
233    /// Estimated validation time in milliseconds
234    pub estimated_time_ms: u64,
235}
236
237/// Consensus level for adaptive consensus
238#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub enum ConsensusLevel {
240    /// Full validation by all validators
241    Full,
242    /// 67% of validators (supermajority)
243    Majority,
244    /// 51% of validators (simple majority)
245    Quorum,
246    /// Local validation only
247    Local,
248}
249
250/// Resource category for auto-reconfiguration
251#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252pub enum ResourceCategory {
253    /// Abundant resources (server/cloud)
254    Abundant,
255    /// Normal resources (desktop)
256    Normal,
257    /// Limited resources (edge device)
258    Limited,
259    /// Critical resources (IoT sensor)
260    Critical,
261}
262
263#[cfg(test)]
264mod tests {
265    use super::*;
266
267    #[test]
268    fn test_embedding_cosine_similarity() {
269        let a = Embedding::new(vec![1.0, 0.0, 0.0]);
270        let b = Embedding::new(vec![1.0, 0.0, 0.0]);
271        assert!((a.cosine_similarity(&b) - 1.0).abs() < 0.001);
272
273        let c = Embedding::new(vec![0.0, 1.0, 0.0]);
274        assert!(a.cosine_similarity(&c).abs() < 0.001);
275    }
276
277    #[test]
278    fn test_transaction_features() {
279        let tx = AiTransaction {
280            hash: [1u8; 32],
281            timestamp: 1702656000000, // Example timestamp
282            agent: [2u8; 32],
283            entry_type: "test_entry".to_string(),
284            data: vec![0, 1, 2, 3, 4, 5],
285            size: 6,
286        };
287
288        let features = tx.extract_features();
289        assert_eq!(features.len(), 16);
290        assert!(features.iter().all(|&f| f >= 0.0 && f <= 2.0));
291    }
292}