use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub type FeatureVector = Vec<f32>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Embedding {
pub vector: FeatureVector,
pub dim: usize,
}
impl Embedding {
pub fn new(vector: FeatureVector) -> Self {
let dim = vector.len();
Self { vector, dim }
}
pub fn zeros(dim: usize) -> Self {
Self {
vector: vec![0.0; dim],
dim,
}
}
pub fn cosine_similarity(&self, other: &Embedding) -> f32 {
if self.dim != other.dim {
return 0.0;
}
let dot: f32 = self
.vector
.iter()
.zip(other.vector.iter())
.map(|(a, b)| a * b)
.sum();
let norm_a: f32 = self.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
let norm_b: f32 = other.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
if norm_a == 0.0 || norm_b == 0.0 {
0.0
} else {
dot / (norm_a * norm_b)
}
}
pub fn l2_distance(&self, other: &Embedding) -> f32 {
if self.dim != other.dim {
return f32::MAX;
}
self.vector
.iter()
.zip(other.vector.iter())
.map(|(a, b)| (a - b).powi(2))
.sum::<f32>()
.sqrt()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pattern {
pub id: PatternId,
pub embedding: Embedding,
pub metadata: HashMap<String, String>,
pub created_at: u64,
}
pub type PatternId = [u8; 32];
pub fn pattern_id(data: &[u8]) -> PatternId {
use blake2::{Blake2b512, Digest};
let mut hasher = Blake2b512::new();
hasher.update(data);
let result = hasher.finalize();
let mut id = [0u8; 32];
id.copy_from_slice(&result[..32]);
id
}
#[derive(Debug, Clone)]
pub struct MemoryMatch {
pub pattern: Pattern,
pub similarity: f32,
pub source: MemorySource,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemorySource {
ShortTerm,
LongTerm,
}
#[derive(Debug, Clone)]
pub struct ProcessResult {
pub relevance: f32,
pub surprise: f32,
pub stored_long_term: bool,
pub anomaly: Option<AnomalyResult>,
}
#[derive(Debug, Clone)]
pub struct AnomalyResult {
pub is_anomaly: bool,
pub confidence: f32,
pub reason: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AiTransaction {
pub hash: [u8; 32],
pub timestamp: u64,
pub agent: [u8; 32],
pub entry_type: String,
pub data: Vec<u8>,
pub size: usize,
}
impl AiTransaction {
pub fn extract_features(&self) -> FeatureVector {
let mut features = Vec::with_capacity(16);
features.push((self.size as f32).ln().max(0.0) / 20.0);
let timestamp_secs = self.timestamp / 1000;
let hour = ((timestamp_secs / 3600) % 24) as f32 / 24.0;
features.push(hour);
let type_hash = pattern_id(self.entry_type.as_bytes());
for i in 0..4 {
features.push(type_hash[i] as f32 / 255.0);
}
for i in 0..4 {
features.push(self.agent[i] as f32 / 255.0);
}
if !self.data.is_empty() {
let mut byte_counts = [0u32; 256];
for &byte in &self.data {
byte_counts[byte as usize] += 1;
}
let len = self.data.len() as f32;
let entropy: f32 = byte_counts
.iter()
.filter(|&&c| c > 0)
.map(|&c| {
let p = c as f32 / len;
-p * p.ln()
})
.sum();
features.push(entropy / 8.0); } else {
features.push(0.0);
}
while features.len() < 16 {
features.push(0.0);
}
features
}
pub fn to_pattern(&self) -> Pattern {
let embedding = Embedding::new(self.extract_features());
Pattern {
id: self.hash,
embedding,
metadata: HashMap::new(),
created_at: self.timestamp,
}
}
}
#[derive(Debug, Clone)]
pub struct ValidationPrediction {
pub likely_valid: bool,
pub confidence: f32,
pub estimated_time_ms: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConsensusLevel {
Full,
Majority,
Quorum,
Local,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResourceCategory {
Abundant,
Normal,
Limited,
Critical,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_embedding_cosine_similarity() {
let a = Embedding::new(vec![1.0, 0.0, 0.0]);
let b = Embedding::new(vec![1.0, 0.0, 0.0]);
assert!((a.cosine_similarity(&b) - 1.0).abs() < 0.001);
let c = Embedding::new(vec![0.0, 1.0, 0.0]);
assert!(a.cosine_similarity(&c).abs() < 0.001);
}
#[test]
fn test_transaction_features() {
let tx = AiTransaction {
hash: [1u8; 32],
timestamp: 1702656000000, agent: [2u8; 32],
entry_type: "test_entry".to_string(),
data: vec![0, 1, 2, 3, 4, 5],
size: 6,
};
let features = tx.extract_features();
assert_eq!(features.len(), 16);
assert!(features.iter().all(|&f| f >= 0.0 && f <= 2.0));
}
}