1use async_trait::async_trait;
5use lc_schema::Message;
6use std::collections::HashMap;
7
8#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum MemoryError {
12 #[error("Failed to load memory: {0}")]
14 LoadError(String),
15
16 #[error("Failed to save memory: {0}")]
18 SaveError(String),
19
20 #[error("Failed to clear memory: {0}")]
22 ClearError(String),
23
24 #[error("Memory error: {0}")]
26 Other(String),
27}
28
29#[async_trait]
33pub trait BaseMemory: Send + Sync {
34 fn memory_variables(&self) -> Vec<&str>;
38
39 async fn load_memory_variables(
47 &self,
48 inputs: &HashMap<String, String>,
49 ) -> Result<HashMap<String, serde_json::Value>, MemoryError>;
50
51 async fn save_context(
62 &mut self,
63 inputs: &HashMap<String, String>,
64 outputs: &HashMap<String, String>,
65 ) -> Result<(), MemoryError>;
66
67 async fn clear(&mut self) -> Result<(), MemoryError>;
69}
70
71pub trait BaseChatMemory: BaseMemory {
79 fn messages(&self) -> &[Message];
81
82 fn add_message(&mut self, message: Message);
84
85 fn add_user_message(&mut self, content: &str) {
87 self.add_message(Message::human(content));
88 }
89
90 fn add_ai_message(&mut self, content: &str) {
92 self.add_message(Message::ai(content));
93 }
94}
95
96#[derive(Debug, Clone)]
100pub struct ChatMessageHistory {
101 messages: Vec<Message>,
103}
104
105impl ChatMessageHistory {
106 pub fn new() -> Self {
108 Self {
109 messages: Vec::new(),
110 }
111 }
112
113 pub fn from_messages(messages: Vec<Message>) -> Self {
115 Self { messages }
116 }
117
118 pub fn add_message(&mut self, message: Message) {
120 self.messages.push(message);
121 }
122
123 pub fn add_user_message(&mut self, content: &str) {
125 self.add_message(Message::human(content));
126 }
127
128 pub fn add_ai_message(&mut self, content: &str) {
130 self.add_message(Message::ai(content));
131 }
132
133 pub fn add_system_message(&mut self, content: &str) {
135 self.add_message(Message::system(content));
136 }
137
138 pub fn messages(&self) -> &[Message] {
140 &self.messages
141 }
142
143 pub fn clear(&mut self) {
145 self.messages.clear();
146 }
147
148 pub fn len(&self) -> usize {
150 self.messages.len()
151 }
152
153 pub fn is_empty(&self) -> bool {
155 self.messages.is_empty()
156 }
157}
158
159impl std::fmt::Display for ChatMessageHistory {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 let formatted: String = self
162 .messages
163 .iter()
164 .map(|msg| {
165 let role = match msg.message_type {
166 lc_schema::MessageType::Human => "Human",
167 lc_schema::MessageType::AI => "AI",
168 lc_schema::MessageType::System => "System",
169 lc_schema::MessageType::Tool { .. } => "Tool",
170 };
171 format!("{}: {}", role, msg.content)
172 })
173 .collect::<Vec<_>>()
174 .join("\n");
175 write!(f, "{}", formatted)
176 }
177}
178
179impl Default for ChatMessageHistory {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185pub fn memory_variables_to_messages(vars: &HashMap<String, serde_json::Value>) -> Vec<Message> {
196 let mut messages = Vec::new();
197 for value in vars.values() {
198 match value {
199 serde_json::Value::Array(items) => {
200 for item in items {
201 if let Ok(msg) = serde_json::from_value::<Message>(item.clone()) {
202 messages.push(msg);
203 } else if let Some(s) = item.as_str() {
204 messages.push(Message::system(s));
205 }
206 }
207 }
208 serde_json::Value::String(s) => messages.push(Message::system(s)),
209 _ => {}
210 }
211 }
212 messages
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn test_chat_message_history() {
221 let mut history = ChatMessageHistory::new();
222
223 history.add_user_message("hello");
224 history.add_ai_message("Hello! How can I help you?");
225 history.add_user_message("introduce yourself");
226
227 assert_eq!(history.len(), 3);
228 assert!(!history.is_empty());
229 }
230
231 #[test]
232 fn test_chat_message_history_to_string() {
233 let mut history = ChatMessageHistory::new();
234
235 history.add_user_message("hello");
236 history.add_ai_message("Hello!");
237
238 let str = history.to_string();
239 assert!(str.contains("Human: hello"));
240 assert!(str.contains("AI: Hello!"));
241 }
242
243 #[test]
244 fn test_chat_message_history_clear() {
245 let mut history = ChatMessageHistory::new();
246
247 history.add_user_message("test");
248 assert_eq!(history.len(), 1);
249
250 history.clear();
251 assert_eq!(history.len(), 0);
252 assert!(history.is_empty());
253 }
254
255 #[test]
257 fn test_memory_variables_to_messages() {
258 let msg = Message::ai("你好");
260 let mut vars = HashMap::new();
261 vars.insert(
262 "history".to_string(),
263 serde_json::json!([serde_json::to_value(&msg).unwrap()]),
264 );
265 let messages = memory_variables_to_messages(&vars);
266 assert_eq!(messages.len(), 1);
267 assert_eq!(messages[0].content, "你好");
268
269 let mut vars = HashMap::new();
271 vars.insert(
272 "history".to_string(),
273 serde_json::Value::String("Human: 在吗\nAI: 在".to_string()),
274 );
275 let messages = memory_variables_to_messages(&vars);
276 assert_eq!(messages.len(), 1);
277 assert_eq!(messages[0].message_type, lc_schema::MessageType::System);
278 }
279}