Skip to main content

ai_agents_reasoning/
metadata.rs

1use serde::{Deserialize, Serialize};
2
3use crate::evaluation::{EvaluationResult, ReflectionAttempt};
4use crate::mode::ReasoningMode;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ReasoningMetadata {
8    pub mode_used: ReasoningMode,
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub thinking: Option<String>,
11    pub iterations: u32,
12    pub auto_detected: bool,
13}
14
15impl ReasoningMetadata {
16    pub fn new(mode_used: ReasoningMode) -> Self {
17        Self {
18            mode_used,
19            thinking: None,
20            iterations: 1,
21            auto_detected: false,
22        }
23    }
24
25    pub fn with_thinking(mut self, thinking: impl Into<String>) -> Self {
26        self.thinking = Some(thinking.into());
27        self
28    }
29
30    pub fn with_iterations(mut self, iterations: u32) -> Self {
31        self.iterations = iterations;
32        self
33    }
34
35    pub fn with_auto_detected(mut self, auto_detected: bool) -> Self {
36        self.auto_detected = auto_detected;
37        self
38    }
39
40    pub fn has_thinking(&self) -> bool {
41        self.thinking.is_some()
42    }
43}
44
45impl Default for ReasoningMetadata {
46    fn default() -> Self {
47        Self::new(ReasoningMode::None)
48    }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct ReflectionMetadata {
53    pub attempts: u32,
54    pub final_evaluation: EvaluationResult,
55    pub history: Vec<ReflectionAttempt>,
56}
57
58impl ReflectionMetadata {
59    pub fn new(final_evaluation: EvaluationResult) -> Self {
60        Self {
61            attempts: 1,
62            final_evaluation,
63            history: Vec::new(),
64        }
65    }
66
67    pub fn with_attempts(mut self, attempts: u32) -> Self {
68        self.attempts = attempts;
69        self
70    }
71
72    pub fn with_history(mut self, history: Vec<ReflectionAttempt>) -> Self {
73        self.history = history;
74        self
75    }
76
77    pub fn add_attempt(&mut self, attempt: ReflectionAttempt) {
78        self.history.push(attempt);
79        self.attempts = self.history.len() as u32;
80    }
81
82    pub fn passed(&self) -> bool {
83        self.final_evaluation.passed
84    }
85
86    pub fn required_retries(&self) -> bool {
87        self.attempts > 1
88    }
89}
90
91impl Default for ReflectionMetadata {
92    fn default() -> Self {
93        Self {
94            attempts: 0,
95            final_evaluation: EvaluationResult::default(),
96            history: Vec::new(),
97        }
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use crate::evaluation::CriterionResult;
105
106    #[test]
107    fn test_reasoning_metadata_creation() {
108        let metadata = ReasoningMetadata::new(ReasoningMode::CoT);
109        assert_eq!(metadata.mode_used, ReasoningMode::CoT);
110        assert!(metadata.thinking.is_none());
111        assert_eq!(metadata.iterations, 1);
112        assert!(!metadata.auto_detected);
113    }
114
115    #[test]
116    fn test_reasoning_metadata_with_thinking() {
117        let metadata = ReasoningMetadata::new(ReasoningMode::CoT)
118            .with_thinking("Step 1: Analyze the problem\nStep 2: Find solution");
119
120        assert!(metadata.has_thinking());
121        assert!(metadata.thinking.unwrap().contains("Step 1"));
122    }
123
124    #[test]
125    fn test_reasoning_metadata_auto_detected() {
126        let metadata = ReasoningMetadata::new(ReasoningMode::Auto)
127            .with_auto_detected(true)
128            .with_iterations(3);
129
130        assert!(metadata.auto_detected);
131        assert_eq!(metadata.iterations, 3);
132    }
133
134    #[test]
135    fn test_reasoning_metadata_default() {
136        let metadata = ReasoningMetadata::default();
137        assert_eq!(metadata.mode_used, ReasoningMode::None);
138        assert!(!metadata.has_thinking());
139        assert_eq!(metadata.iterations, 1);
140    }
141
142    #[test]
143    fn test_reflection_metadata_creation() {
144        let evaluation = EvaluationResult::new(true, 0.95);
145        let metadata = ReflectionMetadata::new(evaluation);
146
147        assert!(metadata.passed());
148        assert_eq!(metadata.attempts, 1);
149        assert!(metadata.history.is_empty());
150    }
151
152    #[test]
153    fn test_reflection_metadata_with_history() {
154        let eval1 = EvaluationResult::new(false, 0.5);
155        let attempt1 = ReflectionAttempt::new("First response", eval1);
156
157        let eval2 = EvaluationResult::new(true, 0.9);
158        let attempt2 = ReflectionAttempt::new("Second response", eval2.clone());
159
160        let metadata = ReflectionMetadata::new(eval2)
161            .with_attempts(2)
162            .with_history(vec![attempt1, attempt2]);
163
164        assert!(metadata.passed());
165        assert!(metadata.required_retries());
166        assert_eq!(metadata.history.len(), 2);
167    }
168
169    #[test]
170    fn test_reflection_metadata_add_attempt() {
171        let eval = EvaluationResult::new(false, 0.4);
172        let mut metadata = ReflectionMetadata::default();
173
174        metadata.add_attempt(ReflectionAttempt::new("Response 1", eval.clone()));
175        assert_eq!(metadata.attempts, 1);
176
177        metadata.add_attempt(ReflectionAttempt::new("Response 2", eval));
178        assert_eq!(metadata.attempts, 2);
179    }
180
181    #[test]
182    fn test_reflection_metadata_default() {
183        let metadata = ReflectionMetadata::default();
184        assert_eq!(metadata.attempts, 0);
185        assert!(!metadata.passed());
186        assert!(metadata.history.is_empty());
187    }
188
189    #[test]
190    fn test_reasoning_metadata_serde() {
191        let metadata = ReasoningMetadata::new(ReasoningMode::React)
192            .with_thinking("Thought process")
193            .with_iterations(5)
194            .with_auto_detected(true);
195
196        let json = serde_json::to_string(&metadata).unwrap();
197        let parsed: ReasoningMetadata = serde_json::from_str(&json).unwrap();
198
199        assert_eq!(parsed.mode_used, ReasoningMode::React);
200        assert_eq!(parsed.thinking, Some("Thought process".to_string()));
201        assert_eq!(parsed.iterations, 5);
202        assert!(parsed.auto_detected);
203    }
204
205    #[test]
206    fn test_reflection_metadata_serde() {
207        let criteria = vec![CriterionResult::pass("Clear response")];
208        let evaluation = EvaluationResult::new(true, 0.85).with_criteria(criteria);
209        let metadata = ReflectionMetadata::new(evaluation).with_attempts(2);
210
211        let json = serde_json::to_string(&metadata).unwrap();
212        let parsed: ReflectionMetadata = serde_json::from_str(&json).unwrap();
213
214        assert!(parsed.passed());
215        assert_eq!(parsed.attempts, 2);
216        assert_eq!(parsed.final_evaluation.criteria_results.len(), 1);
217    }
218}