1use async_trait::async_trait;
5use lc_schema::Message;
6use std::collections::HashMap;
7
8#[derive(Debug, thiserror::Error)]
10pub enum MemoryError {
11 #[error("Failed to load memory: {0}")]
13 LoadError(String),
14
15 #[error("Failed to save memory: {0}")]
17 SaveError(String),
18
19 #[error("Failed to clear memory: {0}")]
21 ClearError(String),
22
23 #[error("Memory error: {0}")]
25 Other(String),
26}
27
28#[async_trait]
32pub trait BaseMemory: Send + Sync {
33 fn memory_variables(&self) -> Vec<&str>;
37
38 async fn load_memory_variables(
46 &self,
47 inputs: &HashMap<String, String>,
48 ) -> Result<HashMap<String, serde_json::Value>, MemoryError>;
49
50 async fn save_context(
56 &mut self,
57 inputs: &HashMap<String, String>,
58 outputs: &HashMap<String, String>,
59 ) -> Result<(), MemoryError>;
60
61 async fn clear(&mut self) -> Result<(), MemoryError>;
63}
64
65pub trait BaseChatMemory: BaseMemory {
69 fn messages(&self) -> &Vec<Message>;
71
72 fn add_message(&mut self, message: Message);
74
75 fn add_user_message(&mut self, content: &str) {
77 self.add_message(Message::human(content));
78 }
79
80 fn add_ai_message(&mut self, content: &str) {
82 self.add_message(Message::ai(content));
83 }
84}
85
86#[derive(Debug, Clone)]
90pub struct ChatMessageHistory {
91 messages: Vec<Message>,
93}
94
95impl ChatMessageHistory {
96 pub fn new() -> Self {
98 Self {
99 messages: Vec::new(),
100 }
101 }
102
103 pub fn from_messages(messages: Vec<Message>) -> Self {
105 Self { messages }
106 }
107
108 pub fn add_message(&mut self, message: Message) {
110 self.messages.push(message);
111 }
112
113 pub fn add_user_message(&mut self, content: &str) {
115 self.add_message(Message::human(content));
116 }
117
118 pub fn add_ai_message(&mut self, content: &str) {
120 self.add_message(Message::ai(content));
121 }
122
123 pub fn add_system_message(&mut self, content: &str) {
125 self.add_message(Message::system(content));
126 }
127
128 pub fn messages(&self) -> &[Message] {
130 &self.messages
131 }
132
133 pub fn clear(&mut self) {
135 self.messages.clear();
136 }
137
138 pub fn len(&self) -> usize {
140 self.messages.len()
141 }
142
143 pub fn is_empty(&self) -> bool {
145 self.messages.is_empty()
146 }
147}
148
149impl std::fmt::Display for ChatMessageHistory {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 let formatted: String = self
152 .messages
153 .iter()
154 .map(|msg| {
155 let role = match msg.message_type {
156 lc_schema::MessageType::Human => "Human",
157 lc_schema::MessageType::AI => "AI",
158 lc_schema::MessageType::System => "System",
159 lc_schema::MessageType::Tool { .. } => "Tool",
160 };
161 format!("{}: {}", role, msg.content)
162 })
163 .collect::<Vec<_>>()
164 .join("\n");
165 write!(f, "{}", formatted)
166 }
167}
168
169impl Default for ChatMessageHistory {
170 fn default() -> Self {
171 Self::new()
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn test_chat_message_history() {
181 let mut history = ChatMessageHistory::new();
182
183 history.add_user_message("hello");
184 history.add_ai_message("Hello! How can I help you?");
185 history.add_user_message("introduce yourself");
186
187 assert_eq!(history.len(), 3);
188 assert!(!history.is_empty());
189 }
190
191 #[test]
192 fn test_chat_message_history_to_string() {
193 let mut history = ChatMessageHistory::new();
194
195 history.add_user_message("hello");
196 history.add_ai_message("Hello!");
197
198 let str = history.to_string();
199 assert!(str.contains("Human: hello"));
200 assert!(str.contains("AI: Hello!"));
201 }
202
203 #[test]
204 fn test_chat_message_history_clear() {
205 let mut history = ChatMessageHistory::new();
206
207 history.add_user_message("test");
208 assert_eq!(history.len(), 1);
209
210 history.clear();
211 assert_eq!(history.len(), 0);
212 assert!(history.is_empty());
213 }
214}