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> {
195 let mut messages = Vec::new();
196 for value in vars.values() {
197 match value {
198 serde_json::Value::Array(items) => {
199 for item in items {
200 if let Ok(msg) = serde_json::from_value::<Message>(item.clone()) {
201 messages.push(msg);
202 } else if let Some(s) = item.as_str() {
203 messages.push(Message::system(s));
204 }
205 }
206 }
207 serde_json::Value::String(s) => messages.push(Message::system(s)),
208 _ => {}
209 }
210 }
211 messages
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn test_chat_message_history() {
220 let mut history = ChatMessageHistory::new();
221
222 history.add_user_message("hello");
223 history.add_ai_message("Hello! How can I help you?");
224 history.add_user_message("introduce yourself");
225
226 assert_eq!(history.len(), 3);
227 assert!(!history.is_empty());
228 }
229
230 #[test]
231 fn test_chat_message_history_to_string() {
232 let mut history = ChatMessageHistory::new();
233
234 history.add_user_message("hello");
235 history.add_ai_message("Hello!");
236
237 let str = history.to_string();
238 assert!(str.contains("Human: hello"));
239 assert!(str.contains("AI: Hello!"));
240 }
241
242 #[test]
243 fn test_chat_message_history_clear() {
244 let mut history = ChatMessageHistory::new();
245
246 history.add_user_message("test");
247 assert_eq!(history.len(), 1);
248
249 history.clear();
250 assert_eq!(history.len(), 0);
251 assert!(history.is_empty());
252 }
253
254 #[test]
256 fn test_memory_variables_to_messages() {
257 let msg = Message::ai("你好");
259 let mut vars = HashMap::new();
260 vars.insert(
261 "history".to_string(),
262 serde_json::json!([serde_json::to_value(&msg).unwrap()]),
263 );
264 let messages = memory_variables_to_messages(&vars);
265 assert_eq!(messages.len(), 1);
266 assert_eq!(messages[0].content, "你好");
267
268 let mut vars = HashMap::new();
270 vars.insert(
271 "history".to_string(),
272 serde_json::Value::String("Human: 在吗\nAI: 在".to_string()),
273 );
274 let messages = memory_variables_to_messages(&vars);
275 assert_eq!(messages.len(), 1);
276 assert_eq!(messages[0].message_type, lc_schema::MessageType::System);
277 }
278}