Skip to main content

vil_context_optimizer/
semantic.rs

1//! Semantic types for Context Optimizer operations.
2//!
3//! These types follow VIL's process-oriented semantic model:
4//! - Events: immutable audit records (Data Lane)
5//! - Faults: error signals (Control Lane)
6//! - State: mutable tracked state (Data Lane)
7
8use serde::{Deserialize, Serialize};
9use vil_macros::{VilAiEvent, VilAiFault, VilAiState};
10
11// ── Events (Data Lane, immutable audit) ─────────────────────────────
12
13/// Emitted after every context optimization operation.
14#[derive(Clone, Debug, Serialize, Deserialize, VilAiEvent)]
15pub struct OptimizeEvent {
16    pub original_count: usize,
17    pub final_count: usize,
18    pub tokens_saved: usize,
19    pub compression_ratio: f32,
20    pub strategy: String,
21}
22
23// ── Faults (Control Lane, error signals) ────────────────────────────
24
25/// Classification of optimizer failure modes.
26#[derive(Clone, Debug, Serialize, Deserialize)]
27pub enum OptimizeFaultType {
28    BudgetExceeded,
29    EmptyInput,
30    TokenizerError,
31    InternalError,
32}
33
34/// Emitted when an optimization operation fails.
35#[derive(Clone, Debug, Serialize, Deserialize, VilAiFault)]
36pub struct OptimizeFault {
37    pub error_type: OptimizeFaultType,
38    pub message: String,
39}
40
41impl OptimizeFault {
42    pub fn internal(msg: impl Into<String>) -> Self {
43        Self {
44            error_type: OptimizeFaultType::InternalError,
45            message: msg.into(),
46        }
47    }
48
49    pub fn empty_input() -> Self {
50        Self {
51            error_type: OptimizeFaultType::EmptyInput,
52            message: "no chunks provided for optimization".into(),
53        }
54    }
55}
56
57// ── State (Data Lane, mutable tracked) ──────────────────────────────
58
59/// Tracks cumulative optimizer statistics.
60#[derive(Clone, Debug, Default, Serialize, Deserialize, VilAiState)]
61pub struct OptimizerState {
62    pub total_optimizations: u64,
63    pub total_tokens_saved: u64,
64    pub total_chunks_processed: u64,
65    pub avg_compression_ratio: f64,
66}
67
68impl OptimizerState {
69    pub fn record(&mut self, event: &OptimizeEvent) {
70        self.total_optimizations += 1;
71        self.total_tokens_saved += event.tokens_saved as u64;
72        self.total_chunks_processed += event.original_count as u64;
73        let n = self.total_optimizations as f64;
74        self.avg_compression_ratio =
75            self.avg_compression_ratio * (n - 1.0) / n + event.compression_ratio as f64 / n;
76    }
77}