lean_ctx/core/ocla/builtin/
efficiency_analyzer.rs1use crate::core::ocla::traits::{EfficiencyAnalyzer, OclaService};
8use crate::core::ocla::types::{
9 EfficiencyAnalysis, EfficiencySample, OclaCapability, OclaCapabilityKind, OclaResult,
10};
11use crate::core::{io_boundary, tokens};
12use std::path::Path;
13
14pub struct BuiltinEfficiencyAnalyzer;
15
16impl BuiltinEfficiencyAnalyzer {
17 pub fn new() -> Self {
18 Self
19 }
20}
21
22impl Default for BuiltinEfficiencyAnalyzer {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl OclaService for BuiltinEfficiencyAnalyzer {
29 fn capability(&self) -> OclaCapability {
30 OclaCapability::available(OclaCapabilityKind::EfficiencyAnalyzer)
31 }
32}
33
34impl EfficiencyAnalyzer for BuiltinEfficiencyAnalyzer {
35 fn analyze_efficiency(&self, sample: EfficiencySample) -> OclaResult<EfficiencyAnalysis> {
36 let original_tokens = measured_original_tokens(&sample);
37 let etpao = if sample.accepted == Some(true) && sample.delivered_tokens > 0 {
38 Some(sample.delivered_tokens.saturating_mul(1000) / original_tokens.max(1))
39 } else {
40 None
41 };
42
43 let compression_rate = if original_tokens > 0 {
44 let savings = original_tokens.saturating_sub(sample.delivered_tokens);
45 #[allow(clippy::cast_possible_truncation)]
46 let ratio = (savings.saturating_mul(1000) / original_tokens).min(1000) as u16;
47 ratio
48 } else {
49 0
50 };
51
52 #[allow(clippy::cast_possible_truncation)]
53 let cache_hit_rate = sample
54 .cache_hits
55 .saturating_mul(1000)
56 .checked_div(sample.cache_reads)
57 .unwrap_or(0)
58 .min(1000) as u16;
59
60 #[allow(clippy::cast_possible_truncation)]
61 let duplicate_ratio = sample
62 .cache_hits
63 .saturating_mul(1000)
64 .checked_div(sample.cache_reads)
65 .unwrap_or(0)
66 .min(1000) as u16;
67
68 let mut recommendation_refs = Vec::new();
69 if compression_rate < 300 {
70 recommendation_refs.push("increase_compression_aggressiveness".into());
71 }
72 if cache_hit_rate > 800 {
73 recommendation_refs.push("leverage_high_cache_hit_rate".into());
74 }
75 if matches!(etpao, Some(value) if value > 0 && value < 500) {
76 recommendation_refs.push("review_low_etpao_reads".into());
77 }
78
79 Ok(EfficiencyAnalysis {
80 etpao_milli: etpao,
81 duplicate_ratio_milli: duplicate_ratio,
82 compression_rate_milli: compression_rate,
83 cache_hit_rate_milli: cache_hit_rate,
84 recommendation_refs,
85 })
86 }
87}
88
89fn measured_original_tokens(sample: &EfficiencySample) -> u64 {
90 let path = sample
91 .context
92 .content_ref
93 .strip_prefix("file:")
94 .unwrap_or(&sample.context.content_ref);
95 if Path::new(path).is_file()
96 && let Ok(content) = io_boundary::read_file_lossy(path)
97 {
98 return tokens::count_tokens(&content) as u64;
99 }
100 sample.original_tokens
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use crate::core::ocla::types::OclaRequestContext;
107
108 fn sample(original: u64, delivered: u64, accepted: Option<bool>) -> EfficiencySample {
109 EfficiencySample {
110 context: OclaRequestContext {
111 request_id: "r1".into(),
112 session_id: "s1".into(),
113 agent_id: "agent-test".into(),
114 content_ref: "ref:test".into(),
115 tenant_id: None,
116 trace_id: "tr-unit".into(),
117 },
118 original_tokens: original,
119 delivered_tokens: delivered,
120 accepted,
121 cache_hits: 0,
122 cache_reads: 0,
123 }
124 }
125
126 #[test]
127 fn etpao_computed_when_accepted() {
128 let analyzer = BuiltinEfficiencyAnalyzer::new();
129 let result = analyzer
130 .analyze_efficiency(sample(1000, 300, Some(true)))
131 .unwrap();
132 assert_eq!(result.etpao_milli, Some(300));
133 }
134
135 #[test]
136 fn etpao_none_when_rejected() {
137 let analyzer = BuiltinEfficiencyAnalyzer::new();
138 let result = analyzer
139 .analyze_efficiency(sample(1000, 300, Some(false)))
140 .unwrap();
141 assert_eq!(result.etpao_milli, None);
142 }
143
144 #[test]
145 fn duplicate_ratio() {
146 let analyzer = BuiltinEfficiencyAnalyzer::new();
147 let mut input = sample(1000, 250, Some(true));
148 input.cache_hits = 3;
149 input.cache_reads = 4;
150
151 let result = analyzer.analyze_efficiency(input).unwrap();
152
153 assert_eq!(result.duplicate_ratio_milli, 750);
154 assert_eq!(result.compression_rate_milli, 750);
155 }
156
157 #[test]
158 fn recommendations_follow_efficiency_thresholds() {
159 let mut input = sample(1000, 800, Some(true));
160 input.cache_hits = 9;
161 input.cache_reads = 10;
162
163 let result = BuiltinEfficiencyAnalyzer::new()
164 .analyze_efficiency(input)
165 .unwrap();
166
167 assert_eq!(
168 result.recommendation_refs,
169 vec![
170 "increase_compression_aggressiveness",
171 "leverage_high_cache_hit_rate",
172 ]
173 );
174
175 let result = BuiltinEfficiencyAnalyzer::new()
176 .analyze_efficiency(sample(1000, 100, Some(true)))
177 .unwrap();
178 assert_eq!(result.recommendation_refs, vec!["review_low_etpao_reads"]);
179 }
180
181 #[test]
182 fn registry_with_builtins_analyzes_efficiency() {
183 let registry = crate::core::ocla::OclaRegistry::with_builtins();
184 let result = registry
185 .efficiency_analyzer
186 .analyze_efficiency(sample(1000, 200, Some(true)))
187 .unwrap();
188
189 assert_eq!(result.etpao_milli, Some(200));
190 assert_eq!(result.compression_rate_milli, 800);
191 }
192
193 #[test]
194 fn cache_hit_rate_uses_observed_reads() {
195 let analyzer = BuiltinEfficiencyAnalyzer::new();
196 let mut input = sample(1000, 400, Some(true));
197 input.cache_hits = 3;
198 input.cache_reads = 4;
199
200 let result = analyzer.analyze_efficiency(input).unwrap();
201
202 assert_eq!(result.cache_hit_rate_milli, 750);
203 }
204
205 #[test]
206 fn original_tokens_are_measured_from_file_content() {
207 let dir = tempfile::tempdir().unwrap();
208 let path = dir.path().join("sample.rs");
209 std::fs::write(&path, "hello world").unwrap();
210 let mut input = sample(1000, 1, Some(true));
211 input.context.content_ref = format!("file:{}", path.display());
212
213 let result = BuiltinEfficiencyAnalyzer::new()
214 .analyze_efficiency(input)
215 .unwrap();
216
217 assert_eq!(result.etpao_milli, Some(500));
218 assert_eq!(result.compression_rate_milli, 500);
219 }
220}