Skip to main content

ai00_mem/
utils.rs

1//! 工具模块
2//!
3//! 提供记忆系统的实用工具函数,包括向量操作、文本处理、时间处理、
4//! 序列化/反序列化、缓存管理等。
5
6use crate::core::*;
7use crate::error::{MemoryError, Result};
8use chrono::{DateTime, Duration, Timelike, Utc};
9use flate2::{read::GzDecoder, write::GzEncoder, Compression};
10use serde::{Deserialize, Serialize};
11use sha2::{Digest, Sha256};
12use std::collections::{HashMap, HashSet};
13use std::io::{Read, Write};
14use uuid::Uuid;
15
16/// 向量工具
17pub struct VectorUtils;
18
19/// 文本工具
20pub struct TextUtils;
21
22/// 时间工具
23pub struct TimeUtils;
24
25/// 序列化工具
26pub struct SerializationUtils;
27
28/// 缓存工具
29pub struct CacheUtils;
30
31/// 哈希工具
32pub struct HashUtils;
33
34/// ID生成器
35pub struct IdGenerator;
36
37/// 相似度计算结果
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct SimilarityResult {
40    pub score: f32,
41    pub method: SimilarityMethod,
42    pub details: HashMap<String, f32>,
43}
44
45/// 相似度计算方法
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum SimilarityMethod {
48    Cosine,
49    Euclidean,
50    Manhattan,
51    Jaccard,
52    Semantic,
53    Hybrid,
54}
55
56/// 文本统计信息
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct TextStats {
59    pub char_count: usize,
60    pub word_count: usize,
61    pub sentence_count: usize,
62    pub paragraph_count: usize,
63    pub language: Option<String>,
64    pub complexity_score: f32,
65    pub readability_score: f32,
66}
67
68/// 时间范围
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct TimeRange {
71    pub start: DateTime<Utc>,
72    pub end: DateTime<Utc>,
73}
74
75/// 压缩结果
76#[derive(Debug, Clone)]
77pub struct CompressionResult {
78    pub compressed_data: Vec<u8>,
79    pub original_size: usize,
80    pub compressed_size: usize,
81    pub compression_ratio: f32,
82}
83
84/// 缓存统计信息
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct CacheStats {
87    pub hit_count: u64,
88    pub miss_count: u64,
89    pub hit_rate: f32,
90    pub total_size: usize,
91    pub entry_count: usize,
92    pub last_cleanup: Option<DateTime<Utc>>,
93}
94
95impl VectorUtils {
96    /// 计算余弦相似度
97    pub fn cosine_similarity(a: &[f32], b: &[f32]) -> Result<f32> {
98        if a.len() != b.len() {
99            return Err(MemoryError::InvalidVectorDimension {
100                expected: a.len(),
101                actual: b.len(),
102            });
103        }
104
105        if a.is_empty() {
106            return Ok(0.0);
107        }
108
109        let dot_product: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
110        let norm_a: f32 = a.iter().map(|x| x * x).sum::<f32>().sqrt();
111        let norm_b: f32 = b.iter().map(|x| x * x).sum::<f32>().sqrt();
112
113        if norm_a == 0.0 || norm_b == 0.0 {
114            return Ok(0.0);
115        }
116
117        Ok(dot_product / (norm_a * norm_b))
118    }
119
120    /// 计算欧几里得距离
121    pub fn euclidean_distance(a: &[f32], b: &[f32]) -> Result<f32> {
122        if a.len() != b.len() {
123            return Err(MemoryError::InvalidVectorDimension {
124                expected: a.len(),
125                actual: b.len(),
126            });
127        }
128
129        let distance: f32 = a
130            .iter()
131            .zip(b.iter())
132            .map(|(x, y)| (x - y).powi(2))
133            .sum::<f32>()
134            .sqrt();
135
136        Ok(distance)
137    }
138
139    /// 计算曼哈顿距离
140    pub fn manhattan_distance(a: &[f32], b: &[f32]) -> Result<f32> {
141        if a.len() != b.len() {
142            return Err(MemoryError::InvalidVectorDimension {
143                expected: a.len(),
144                actual: b.len(),
145            });
146        }
147
148        let distance: f32 = a.iter().zip(b.iter()).map(|(x, y)| (x - y).abs()).sum();
149
150        Ok(distance)
151    }
152
153    /// 向量归一化
154    pub fn normalize(vector: &mut [f32]) -> Result<()> {
155        let norm: f32 = vector.iter().map(|x| x * x).sum::<f32>().sqrt();
156
157        if norm == 0.0 {
158            return Err(MemoryError::Internal {
159                message: "Cannot normalize zero vector".to_string(),
160            });
161        }
162
163        for value in vector.iter_mut() {
164            *value /= norm;
165        }
166
167        Ok(())
168    }
169
170    /// 向量加权平均
171    pub fn weighted_average(vectors: &[Vec<f32>], weights: &[f32]) -> Result<Vec<f32>> {
172        if vectors.is_empty() {
173            return Err(MemoryError::Internal {
174                message: "No vectors provided".to_string(),
175            });
176        }
177
178        if vectors.len() != weights.len() {
179            return Err(MemoryError::Internal {
180                message: "Vector and weight count mismatch".to_string(),
181            });
182        }
183
184        let dim = vectors[0].len();
185        if !vectors.iter().all(|v| v.len() == dim) {
186            return Err(MemoryError::Internal {
187                message: "Inconsistent vector dimensions".to_string(),
188            });
189        }
190
191        let weight_sum: f32 = weights.iter().sum();
192        if weight_sum == 0.0 {
193            return Err(MemoryError::Internal {
194                message: "Zero weight sum".to_string(),
195            });
196        }
197
198        let mut result = vec![0.0; dim];
199        for (vector, &weight) in vectors.iter().zip(weights.iter()) {
200            for (i, &value) in vector.iter().enumerate() {
201                result[i] += value * weight / weight_sum;
202            }
203        }
204
205        Ok(result)
206    }
207
208    /// 计算向量中心点
209    pub fn centroid(vectors: &[Vec<f32>]) -> Result<Vec<f32>> {
210        if vectors.is_empty() {
211            return Err(MemoryError::Internal {
212                message: "No vectors provided".to_string(),
213            });
214        }
215
216        let weights = vec![1.0; vectors.len()];
217        Self::weighted_average(vectors, &weights)
218    }
219
220    /// 向量量化(减少精度以节省空间)
221    pub fn quantize(vector: &[f32], levels: u8) -> Vec<u8> {
222        let min_val = vector.iter().fold(f32::INFINITY, |a, &b| a.min(b));
223        let max_val = vector.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
224        let range = max_val - min_val;
225
226        if range == 0.0 {
227            return vec![0; vector.len()];
228        }
229
230        let scale = (levels - 1) as f32 / range;
231
232        vector
233            .iter()
234            .map(|&val| ((val - min_val) * scale).round() as u8)
235            .collect()
236    }
237
238    /// 反量化
239    pub fn dequantize(quantized: &[u8], min_val: f32, max_val: f32, levels: u8) -> Vec<f32> {
240        let range = max_val - min_val;
241        let scale = range / (levels - 1) as f32;
242
243        quantized
244            .iter()
245            .map(|&val| min_val + val as f32 * scale)
246            .collect()
247    }
248}
249
250impl TextUtils {
251    /// 计算文本统计信息
252    pub fn analyze_text(text: &str) -> TextStats {
253        let char_count = text.chars().count();
254        let word_count = text.split_whitespace().count();
255        // 改进句子计数逻辑,支持中英文标点符号
256        let sentence_count = if text.trim().is_empty() {
257            0
258        } else {
259            // 支持中英文标点符号
260            let english_count = text.matches(&['.', '!', '?'][..]).count();
261            let chinese_count = text.matches(&['。', '!', '?'][..]).count();
262            let total_count = english_count + chinese_count;
263            if total_count == 0 {
264                1 // 如果没有句子结束符,认为是一个句子
265            } else {
266                total_count
267            }
268        };
269        let paragraph_count = text
270            .split("\n\n")
271            .filter(|p| !p.trim().is_empty())
272            .count()
273            .max(1);
274
275        let complexity_score = Self::calculate_complexity(text);
276        let readability_score = Self::calculate_readability(text, word_count, sentence_count);
277        let language = Self::detect_language(text);
278
279        TextStats {
280            char_count,
281            word_count,
282            sentence_count,
283            paragraph_count,
284            language,
285            complexity_score,
286            readability_score,
287        }
288    }
289
290    /// 计算文本复杂度
291    fn calculate_complexity(text: &str) -> f32 {
292        let words: Vec<&str> = text.split_whitespace().collect();
293        if words.is_empty() {
294            return 0.0;
295        }
296
297        let avg_word_length: f32 = words
298            .iter()
299            .map(|word| word.chars().count() as f32)
300            .sum::<f32>()
301            / words.len() as f32;
302
303        let unique_words: HashSet<&str> = words.iter().cloned().collect();
304        let vocabulary_diversity = unique_words.len() as f32 / words.len() as f32;
305
306        // 简化的复杂度计算
307        (avg_word_length / 10.0 + vocabulary_diversity) / 2.0
308    }
309
310    /// 计算可读性分数(简化的Flesch Reading Ease)
311    fn calculate_readability(text: &str, word_count: usize, sentence_count: usize) -> f32 {
312        if word_count == 0 || sentence_count == 0 {
313            return 0.0;
314        }
315
316        let syllable_count = Self::estimate_syllables(text);
317        let avg_sentence_length = word_count as f32 / sentence_count as f32;
318        let avg_syllables_per_word = syllable_count as f32 / word_count as f32;
319
320        // 简化的Flesch公式
321        206.835 - (1.015 * avg_sentence_length) - (84.6 * avg_syllables_per_word)
322    }
323
324    /// 估算音节数
325    fn estimate_syllables(text: &str) -> usize {
326        let vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
327        let mut syllable_count = 0;
328
329        for word in text.split_whitespace() {
330            let word = word.to_lowercase();
331            let mut word_syllables = 0;
332            let mut prev_was_vowel = false;
333
334            for ch in word.chars() {
335                let is_vowel = vowels.contains(&ch);
336                if is_vowel && !prev_was_vowel {
337                    word_syllables += 1;
338                }
339                prev_was_vowel = is_vowel;
340            }
341
342            // 每个单词至少有一个音节
343            syllable_count += word_syllables.max(1);
344        }
345
346        syllable_count
347    }
348
349    /// 简单的语言检测
350    fn detect_language(text: &str) -> Option<String> {
351        let chinese_chars = text
352            .chars()
353            .filter(|c| {
354                let code = *c as u32;
355                (0x4E00..=0x9FFF).contains(&code) // CJK统一汉字
356            })
357            .count();
358
359        let total_chars = text.chars().filter(|c| c.is_alphabetic()).count();
360
361        if total_chars == 0 {
362            return None;
363        }
364
365        if chinese_chars as f32 / total_chars as f32 > 0.3 {
366            Some("zh".to_string())
367        } else {
368            Some("en".to_string())
369        }
370    }
371
372    /// 提取关键词(简单实现)
373    pub fn extract_keywords(text: &str, max_keywords: usize) -> Vec<String> {
374        let stop_words: HashSet<&str> = [
375            "the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with",
376            "by", "is", "are", "was", "were", "be", "been", "have", "has", "had", "do", "does",
377            "did", "will", "would", "could", "should", "的", "了", "在", "是", "我", "你", "他",
378            "她", "它", "们", "这", "那", "有", "和", "与", "或", "但", "如果", "因为", "所以",
379            "然后", "现在", "一个", "多个", "包含", "还有",
380        ]
381        .iter()
382        .cloned()
383        .collect();
384
385        let mut word_freq: HashMap<String, usize> = HashMap::new();
386
387        // 处理中文文本,按字符分割
388        let chinese_chars = text
389            .chars()
390            .filter(|c| {
391                let code = *c as u32;
392                (0x4E00..=0x9FFF).contains(&code)
393            })
394            .count();
395
396        if chinese_chars > text.chars().count() / 3 {
397            // 中文文本处理
398            for word in text.split_whitespace() {
399                let cleaned = word
400                    .chars()
401                    .filter(|c| c.is_alphanumeric())
402                    .collect::<String>();
403
404                if cleaned.len() >= 2 && !stop_words.contains(cleaned.as_str()) {
405                    *word_freq.entry(cleaned).or_insert(0) += 1;
406                }
407            }
408        } else {
409            // 英文文本处理
410            for word in text.split_whitespace() {
411                let word = word
412                    .to_lowercase()
413                    .trim_matches(|c: char| !c.is_alphanumeric())
414                    .to_string();
415
416                if word.len() > 2 && !stop_words.contains(word.as_str()) {
417                    *word_freq.entry(word).or_insert(0) += 1;
418                }
419            }
420        }
421
422        let mut keywords: Vec<(String, usize)> = word_freq.into_iter().collect();
423        keywords.sort_by(|a, b| b.1.cmp(&a.1));
424
425        keywords
426            .into_iter()
427            .take(max_keywords)
428            .map(|(word, _)| word)
429            .collect()
430    }
431
432    /// 计算Jaccard相似度
433    pub fn jaccard_similarity(text1: &str, text2: &str) -> f32 {
434        let words1: HashSet<&str> = text1.split_whitespace().collect();
435        let words2: HashSet<&str> = text2.split_whitespace().collect();
436
437        if words1.is_empty() && words2.is_empty() {
438            return 1.0;
439        }
440
441        let intersection = words1.intersection(&words2).count();
442        let union = words1.union(&words2).count();
443
444        if union == 0 {
445            0.0
446        } else {
447            intersection as f32 / union as f32
448        }
449    }
450
451    /// 文本摘要(简单实现)
452    pub fn summarize(text: &str, max_sentences: usize) -> String {
453        let sentences: Vec<&str> = text
454            .split(&['.', '!', '?'][..])
455            .filter(|s| !s.trim().is_empty())
456            .collect();
457
458        if sentences.len() <= max_sentences {
459            return text.to_string();
460        }
461
462        // 简单地取前几句
463        sentences
464            .iter()
465            .take(max_sentences)
466            .map(|s| s.trim())
467            .collect::<Vec<_>>()
468            .join(". ")
469            + "."
470    }
471}
472
473impl TimeUtils {
474    /// 创建时间范围
475    pub fn create_range(start: DateTime<Utc>, end: DateTime<Utc>) -> Result<TimeRange> {
476        if start > end {
477            return Err(MemoryError::Internal {
478                message: "Start time must be before end time".to_string(),
479            });
480        }
481
482        Ok(TimeRange { start, end })
483    }
484
485    /// 检查时间是否在范围内
486    pub fn is_in_range(time: DateTime<Utc>, range: &TimeRange) -> bool {
487        time >= range.start && time <= range.end
488    }
489
490    /// 计算时间衰减因子
491    pub fn calculate_decay_factor(timestamp: DateTime<Utc>, half_life: Duration) -> f32 {
492        let elapsed = Utc::now() - timestamp;
493        let half_life_seconds = half_life.num_seconds() as f64;
494        let elapsed_seconds = elapsed.num_seconds() as f64;
495
496        if half_life_seconds <= 0.0 {
497            return 1.0;
498        }
499
500        (0.5_f64.powf(elapsed_seconds / half_life_seconds)) as f32
501    }
502
503    /// 获取时间段描述
504    pub fn get_time_period_description(timestamp: DateTime<Utc>) -> String {
505        let now = Utc::now();
506        let diff = now - timestamp;
507
508        if diff < Duration::minutes(1) {
509            "刚刚".to_string()
510        } else if diff < Duration::hours(1) {
511            format!("{}分钟前", diff.num_minutes())
512        } else if diff < Duration::days(1) {
513            format!("{}小时前", diff.num_hours())
514        } else if diff < Duration::days(7) {
515            format!("{}天前", diff.num_days())
516        } else if diff < Duration::days(30) {
517            format!("{}周前", diff.num_weeks())
518        } else if diff < Duration::days(365) {
519            format!("{}个月前", diff.num_days() / 30)
520        } else {
521            format!("{}年前", diff.num_days() / 365)
522        }
523    }
524
525    /// 获取一天中的时间段
526    pub fn get_time_of_day_period(timestamp: DateTime<Utc>) -> String {
527        let hour = timestamp.hour();
528
529        match hour {
530            5..=11 => "上午".to_string(),
531            12..=17 => "下午".to_string(),
532            18..=22 => "晚上".to_string(),
533            _ => "深夜".to_string(),
534        }
535    }
536
537    /// 计算时间相似度
538    pub fn temporal_similarity(
539        time1: DateTime<Utc>,
540        time2: DateTime<Utc>,
541        window: Duration,
542    ) -> f32 {
543        let diff = (time1 - time2).abs();
544        let window_seconds = window.num_seconds() as f64;
545        let diff_seconds = diff.num_seconds() as f64;
546
547        if diff_seconds >= window_seconds {
548            0.0
549        } else {
550            1.0 - (diff_seconds / window_seconds) as f32
551        }
552    }
553}
554
555impl SerializationUtils {
556    /// 压缩数据
557    pub fn compress(data: &[u8]) -> Result<CompressionResult> {
558        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
559        encoder.write_all(data).map_err(MemoryError::Io)?;
560
561        let compressed_data = encoder.finish().map_err(MemoryError::Io)?;
562
563        let original_size = data.len();
564        let compressed_size = compressed_data.len();
565        let compression_ratio = if original_size > 0 {
566            compressed_size as f32 / original_size as f32
567        } else {
568            1.0
569        };
570
571        Ok(CompressionResult {
572            compressed_data,
573            original_size,
574            compressed_size,
575            compression_ratio,
576        })
577    }
578
579    /// 解压缩数据
580    pub fn decompress(compressed_data: &[u8]) -> Result<Vec<u8>> {
581        let mut decoder = GzDecoder::new(compressed_data);
582        let mut decompressed = Vec::new();
583
584        decoder
585            .read_to_end(&mut decompressed)
586            .map_err(MemoryError::Io)?;
587
588        Ok(decompressed)
589    }
590
591    /// 序列化为JSON
592    pub fn to_json<T: Serialize>(data: &T) -> Result<String> {
593        serde_json::to_string(data).map_err(MemoryError::Serialization)
594    }
595
596    /// 从JSON反序列化
597    pub fn from_json<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T> {
598        serde_json::from_str(json).map_err(MemoryError::Serialization)
599    }
600
601    /// 序列化为二进制
602    pub fn to_binary<T: Serialize + bincode::Encode>(data: &T) -> Result<Vec<u8>> {
603        bincode::encode_to_vec(data, bincode::config::standard()).map_err(|e| {
604            MemoryError::Internal {
605                message: format!("Binary serialization failed: {}", e),
606            }
607        })
608    }
609
610    /// 从二进制反序列化
611    pub fn from_binary<T: for<'de> Deserialize<'de> + bincode::Decode<()>>(
612        data: &[u8],
613    ) -> Result<T> {
614        bincode::decode_from_slice(data, bincode::config::standard())
615            .map(|(result, _)| result)
616            .map_err(|e| MemoryError::Internal {
617                message: format!("Binary deserialization failed: {}", e),
618            })
619    }
620}
621
622impl CacheUtils {
623    /// 计算缓存命中率
624    pub fn calculate_hit_rate(hit_count: u64, miss_count: u64) -> f32 {
625        let total = hit_count + miss_count;
626        if total == 0 {
627            0.0
628        } else {
629            hit_count as f32 / total as f32
630        }
631    }
632
633    /// 估算内存使用量
634    pub fn estimate_memory_usage<T>(items: &[T]) -> usize {
635        std::mem::size_of_val(items)
636    }
637
638    /// 生成缓存键
639    pub fn generate_cache_key(components: &[&str]) -> String {
640        let mut hasher = Sha256::new();
641        for component in components {
642            hasher.update(component.as_bytes());
643        }
644        format!("{:x}", hasher.finalize())
645    }
646
647    /// 检查缓存是否需要清理
648    pub fn should_cleanup(last_cleanup: Option<DateTime<Utc>>, interval: Duration) -> bool {
649        match last_cleanup {
650            Some(last) => Utc::now() - last > interval,
651            None => true,
652        }
653    }
654}
655
656impl HashUtils {
657    /// 计算字符串哈希
658    pub fn hash_string(input: &str) -> String {
659        let mut hasher = Sha256::new();
660        hasher.update(input.as_bytes());
661        format!("{:x}", hasher.finalize())
662    }
663
664    /// 计算数据哈希
665    pub fn hash_bytes(data: &[u8]) -> String {
666        let mut hasher = Sha256::new();
667        hasher.update(data);
668        format!("{:x}", hasher.finalize())
669    }
670
671    /// 生成短哈希(用于显示)
672    pub fn short_hash(input: &str, length: usize) -> String {
673        let full_hash = Self::hash_string(input);
674        full_hash
675            .chars()
676            .take(length.min(full_hash.len()))
677            .collect()
678    }
679
680    /// 验证哈希
681    pub fn verify_hash(input: &str, expected_hash: &str) -> bool {
682        Self::hash_string(input) == expected_hash
683    }
684}
685
686impl IdGenerator {
687    /// 生成记忆ID
688    pub fn generate_memory_id() -> MemoryId {
689        format!("mem_{}", Uuid::new_v4())
690    }
691
692    /// 生成连接ID
693    pub fn generate_connection_id() -> ConnectionId {
694        format!("conn_{}", Uuid::new_v4())
695    }
696
697    /// 生成会话ID
698    pub fn generate_session_id() -> String {
699        format!("session_{}", Uuid::new_v4())
700    }
701
702    /// 生成查询ID
703    pub fn generate_query_id() -> String {
704        format!("query_{}", Uuid::new_v4())
705    }
706
707    /// 生成交互ID
708    pub fn generate_interaction_id() -> String {
709        format!("interaction_{}", Uuid::new_v4())
710    }
711
712
713
714    /// 从时间戳生成ID
715    pub fn generate_time_based_id(prefix: &str) -> String {
716        let timestamp = Utc::now().timestamp_millis();
717        let uuid = Uuid::new_v4();
718        format!("{}_{:x}_{}", prefix, timestamp, uuid.simple())
719    }
720
721    /// 生成短ID(用于显示)
722    pub fn generate_short_id(length: usize) -> String {
723        let uuid = Uuid::new_v4();
724        uuid.simple().to_string().chars().take(length).collect()
725    }
726}
727
728/// 批处理工具
729pub struct BatchUtils;
730
731impl BatchUtils {
732    /// 将数据分批处理
733    pub fn chunk<T: Clone>(data: Vec<T>, chunk_size: usize) -> Vec<Vec<T>> {
734        if chunk_size == 0 {
735            return vec![data];
736        }
737
738        data.chunks(chunk_size)
739            .map(|chunk| chunk.to_vec())
740            .collect()
741    }
742
743    /// 并行处理批次
744    pub async fn process_batches<T, F, R>(batches: Vec<Vec<T>>, processor: F) -> Vec<Result<R>>
745    where
746        T: Send + 'static,
747        F: Fn(Vec<T>) -> Result<R> + Send + Sync + 'static + Clone,
748        R: Send + 'static,
749    {
750        let mut handles = Vec::new();
751
752        for batch in batches {
753            let processor = processor.clone();
754            let handle = tokio::spawn(async move { processor(batch) });
755            handles.push(handle);
756        }
757
758        let mut results = Vec::new();
759        for handle in handles {
760            match handle.await {
761                Ok(result) => results.push(result),
762                Err(e) => results.push(Err(MemoryError::Internal {
763                    message: e.to_string(),
764                })),
765            }
766        }
767
768        results
769    }
770}
771
772/// 性能监控工具
773pub struct PerformanceUtils;
774
775impl PerformanceUtils {
776    /// 测量执行时间
777    pub async fn measure_time<F, T>(operation: F) -> (T, Duration)
778    where
779        F: std::future::Future<Output = T>,
780    {
781        let start = Utc::now();
782        let result = operation.await;
783        let duration = Utc::now() - start;
784        (result, duration)
785    }
786
787    /// 创建性能报告
788    pub fn create_performance_report(
789        operation_name: &str,
790        duration: Duration,
791        items_processed: usize,
792    ) -> HashMap<String, serde_json::Value> {
793        let mut report = HashMap::new();
794
795        report.insert(
796            "operation".to_string(),
797            serde_json::Value::String(operation_name.to_string()),
798        );
799        report.insert(
800            "duration_ms".to_string(),
801            serde_json::Value::Number(duration.num_milliseconds().into()),
802        );
803        report.insert(
804            "items_processed".to_string(),
805            serde_json::Value::Number(items_processed.into()),
806        );
807
808        if items_processed > 0 && duration.num_milliseconds() > 0 {
809            let throughput = items_processed as f64 / (duration.num_milliseconds() as f64 / 1000.0);
810            report.insert(
811                "throughput_per_second".to_string(),
812                serde_json::Value::Number(
813                    serde_json::Number::from_f64(throughput).unwrap_or_else(|| 0.into()),
814                ),
815            );
816        }
817
818        report
819    }
820}
821
822#[cfg(test)]
823mod tests {
824    use super::*;
825
826    #[test]
827    fn test_vector_cosine_similarity() {
828        let a = vec![1.0, 2.0, 3.0];
829        let b = vec![4.0, 5.0, 6.0];
830
831        let similarity = VectorUtils::cosine_similarity(&a, &b).unwrap();
832        assert!(similarity > 0.9); // 应该很相似
833    }
834
835    #[test]
836    fn test_vector_normalization() {
837        let mut vector = vec![3.0, 4.0];
838        VectorUtils::normalize(&mut vector).unwrap();
839
840        let norm: f32 = vector.iter().map(|x| x * x).sum::<f32>().sqrt();
841        assert!((norm - 1.0).abs() < 1e-6);
842    }
843
844    #[test]
845    fn test_text_analysis() {
846        let text = "这是一个测试文本。它包含多个句子!还有问号吗?";
847        let stats = TextUtils::analyze_text(text);
848
849        assert!(stats.char_count > 0);
850        assert!(stats.word_count > 0);
851        assert_eq!(stats.sentence_count, 3);
852        assert_eq!(stats.language, Some("zh".to_string()));
853    }
854
855    #[test]
856    fn test_keyword_extraction() {
857        let text = "机器学习是人工智能的一个重要分支。深度学习是机器学习的子领域。";
858        let keywords = TextUtils::extract_keywords(text, 3);
859
860        assert!(!keywords.is_empty());
861        assert!(keywords.len() > 0);
862    }
863
864    #[test]
865    fn test_time_decay() {
866        let now = Utc::now();
867        let past = now - Duration::hours(1);
868        let half_life = Duration::hours(2);
869
870        let decay = TimeUtils::calculate_decay_factor(past, half_life);
871        assert!(decay > 0.7 && decay < 0.8); // 应该约为0.707
872    }
873
874    #[test]
875    fn test_compression() {
876        // 使用更长的重复文本以确保压缩效果
877        let data = "这是一些测试数据,应该可以被压缩。重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容重复的内容。".as_bytes();
878        let result = SerializationUtils::compress(data).unwrap();
879
880        // 对于重复内容,压缩应该有效果
881        assert!(result.compressed_size <= result.original_size);
882        assert!(result.compression_ratio <= 1.0);
883
884        let decompressed = SerializationUtils::decompress(&result.compressed_data).unwrap();
885        assert_eq!(data, decompressed.as_slice());
886    }
887
888    #[test]
889    fn test_hash_generation() {
890        let input = "测试字符串";
891        let hash1 = HashUtils::hash_string(input);
892        let hash2 = HashUtils::hash_string(input);
893
894        assert_eq!(hash1, hash2); // 相同输入应该产生相同哈希
895        assert_eq!(hash1.len(), 64); // SHA256产生64字符的十六进制字符串
896
897        let short_hash = HashUtils::short_hash(input, 8);
898        assert_eq!(short_hash.len(), 8);
899    }
900
901    #[test]
902    fn test_id_generation() {
903        let memory_id = IdGenerator::generate_memory_id();
904        let connection_id = IdGenerator::generate_connection_id();
905
906        assert!(memory_id.starts_with("mem_"));
907        assert!(connection_id.starts_with("conn_"));
908
909        // 确保生成的ID是唯一的
910        let id1 = IdGenerator::generate_memory_id();
911        let id2 = IdGenerator::generate_memory_id();
912        assert_ne!(id1, id2);
913    }
914
915    #[test]
916    fn test_batch_chunking() {
917        let data: Vec<i32> = (1..=10).collect();
918        let chunks = BatchUtils::chunk(data, 3);
919
920        assert_eq!(chunks.len(), 4); // 10个元素,每批3个,应该有4批
921        assert_eq!(chunks[0], vec![1, 2, 3]);
922        assert_eq!(chunks[3], vec![10]); // 最后一批只有1个元素
923    }
924
925    #[test]
926    fn test_cache_hit_rate() {
927        let hit_rate = CacheUtils::calculate_hit_rate(80, 20);
928        assert_eq!(hit_rate, 0.8);
929
930        let hit_rate_zero = CacheUtils::calculate_hit_rate(0, 0);
931        assert_eq!(hit_rate_zero, 0.0);
932    }
933
934    #[tokio::test]
935    async fn test_performance_measurement() {
936        let (result, duration) = PerformanceUtils::measure_time(async {
937            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
938            42
939        })
940        .await;
941
942        assert_eq!(result, 42);
943        assert!(duration.num_milliseconds() >= 100);
944    }
945}