ai_agents_reasoning/
metadata.rs1use 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, Default)]
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
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use crate::evaluation::CriterionResult;
95
96 #[test]
97 fn test_reasoning_metadata_creation() {
98 let metadata = ReasoningMetadata::new(ReasoningMode::CoT);
99 assert_eq!(metadata.mode_used, ReasoningMode::CoT);
100 assert!(metadata.thinking.is_none());
101 assert_eq!(metadata.iterations, 1);
102 assert!(!metadata.auto_detected);
103 }
104
105 #[test]
106 fn test_reasoning_metadata_with_thinking() {
107 let metadata = ReasoningMetadata::new(ReasoningMode::CoT)
108 .with_thinking("Step 1: Analyze the problem\nStep 2: Find solution");
109
110 assert!(metadata.has_thinking());
111 assert!(metadata.thinking.unwrap().contains("Step 1"));
112 }
113
114 #[test]
115 fn test_reasoning_metadata_auto_detected() {
116 let metadata = ReasoningMetadata::new(ReasoningMode::Auto)
117 .with_auto_detected(true)
118 .with_iterations(3);
119
120 assert!(metadata.auto_detected);
121 assert_eq!(metadata.iterations, 3);
122 }
123
124 #[test]
125 fn test_reasoning_metadata_default() {
126 let metadata = ReasoningMetadata::default();
127 assert_eq!(metadata.mode_used, ReasoningMode::None);
128 assert!(!metadata.has_thinking());
129 assert_eq!(metadata.iterations, 1);
130 }
131
132 #[test]
133 fn test_reflection_metadata_creation() {
134 let evaluation = EvaluationResult::new(true, 0.95);
135 let metadata = ReflectionMetadata::new(evaluation);
136
137 assert!(metadata.passed());
138 assert_eq!(metadata.attempts, 1);
139 assert!(metadata.history.is_empty());
140 }
141
142 #[test]
143 fn test_reflection_metadata_with_history() {
144 let eval1 = EvaluationResult::new(false, 0.5);
145 let attempt1 = ReflectionAttempt::new("First response", eval1);
146
147 let eval2 = EvaluationResult::new(true, 0.9);
148 let attempt2 = ReflectionAttempt::new("Second response", eval2.clone());
149
150 let metadata = ReflectionMetadata::new(eval2)
151 .with_attempts(2)
152 .with_history(vec![attempt1, attempt2]);
153
154 assert!(metadata.passed());
155 assert!(metadata.required_retries());
156 assert_eq!(metadata.history.len(), 2);
157 }
158
159 #[test]
160 fn test_reflection_metadata_add_attempt() {
161 let eval = EvaluationResult::new(false, 0.4);
162 let mut metadata = ReflectionMetadata::default();
163
164 metadata.add_attempt(ReflectionAttempt::new("Response 1", eval.clone()));
165 assert_eq!(metadata.attempts, 1);
166
167 metadata.add_attempt(ReflectionAttempt::new("Response 2", eval));
168 assert_eq!(metadata.attempts, 2);
169 }
170
171 #[test]
172 fn test_reflection_metadata_default() {
173 let metadata = ReflectionMetadata::default();
174 assert_eq!(metadata.attempts, 0);
175 assert!(!metadata.passed());
176 assert!(metadata.history.is_empty());
177 }
178
179 #[test]
180 fn test_reasoning_metadata_serde() {
181 let metadata = ReasoningMetadata::new(ReasoningMode::React)
182 .with_thinking("Thought process")
183 .with_iterations(5)
184 .with_auto_detected(true);
185
186 let json = serde_json::to_string(&metadata).unwrap();
187 let parsed: ReasoningMetadata = serde_json::from_str(&json).unwrap();
188
189 assert_eq!(parsed.mode_used, ReasoningMode::React);
190 assert_eq!(parsed.thinking, Some("Thought process".to_string()));
191 assert_eq!(parsed.iterations, 5);
192 assert!(parsed.auto_detected);
193 }
194
195 #[test]
196 fn test_reflection_metadata_serde() {
197 let criteria = vec![CriterionResult::pass("Clear response")];
198 let evaluation = EvaluationResult::new(true, 0.85).with_criteria(criteria);
199 let metadata = ReflectionMetadata::new(evaluation).with_attempts(2);
200
201 let json = serde_json::to_string(&metadata).unwrap();
202 let parsed: ReflectionMetadata = serde_json::from_str(&json).unwrap();
203
204 assert!(parsed.passed());
205 assert_eq!(parsed.attempts, 2);
206 assert_eq!(parsed.final_evaluation.criteria_results.len(), 1);
207 }
208}