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)]
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}