lean_ctx/core/shadow/
recommendation.rs1use crate::core::{
4 shadow::baseline::accepted,
5 value_gate::{OutcomeSignal, cost_tracker::calculate_cost},
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ShadowTask {
10 pub task_id: String,
11 pub query: String,
12 pub raw_input_tokens: u64,
13 pub compressed_input_tokens: u64,
14 pub output_tokens: u64,
15 pub model_used: String,
16 pub outcome_signals: Vec<OutcomeSignal>,
17 pub duration_ms: u64,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct TreatmentMeasurement {
22 pub task_id: String,
23 pub input_tokens: u64,
24 pub output_tokens: u64,
25 pub model: String,
26 pub total_cost_micros: u64,
27 pub duration_ms: u64,
28 pub outcome_accepted: bool,
29 pub optimizations_applied: Vec<String>,
30}
31
32pub fn measure_treatment(task: &ShadowTask) -> TreatmentMeasurement {
33 let mut optimizations = Vec::new();
34 if task.compressed_input_tokens < task.raw_input_tokens {
36 optimizations.push("compression".into());
37 }
38 TreatmentMeasurement {
39 task_id: task.task_id.clone(),
40 input_tokens: task.compressed_input_tokens,
41 output_tokens: task.output_tokens,
42 model: task.model_used.clone(),
43 total_cost_micros: calculate_cost(
44 task.compressed_input_tokens,
45 task.output_tokens,
46 0,
47 &task.model_used,
48 ),
49 duration_ms: task.duration_ms,
50 outcome_accepted: accepted(&task.task_id, &task.outcome_signals),
51 optimizations_applied: optimizations,
52 }
53}