langchain_rust/memory/
window_buffer.rs1use std::collections::VecDeque;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use tokio::sync::Mutex;
6
7use crate::schemas::{
8 memory::{BaseMemory, MemoryError},
9 messages::Message,
10};
11
12pub struct WindowBufferMemory {
17 window_size: usize,
18 messages: VecDeque<Message>,
19}
20
21impl Default for WindowBufferMemory {
22 fn default() -> Self {
23 Self::new(10)
24 }
25}
26
27impl WindowBufferMemory {
28 pub fn new(window_size: usize) -> Self {
29 Self {
30 messages: VecDeque::new(),
31 window_size,
32 }
33 }
34}
35
36impl Into<Arc<dyn BaseMemory>> for WindowBufferMemory {
37 fn into(self) -> Arc<dyn BaseMemory> {
38 Arc::new(self)
39 }
40}
41
42impl Into<Arc<Mutex<dyn BaseMemory>>> for WindowBufferMemory {
43 fn into(self) -> Arc<Mutex<dyn BaseMemory>> {
44 Arc::new(Mutex::new(self))
45 }
46}
47
48#[async_trait]
49impl BaseMemory for WindowBufferMemory {
50 async fn messages(&self) -> Result<Vec<Message>, MemoryError> {
51 Ok(self.messages.iter().cloned().collect())
52 }
53
54 async fn add_message(&mut self, message: Message) -> Result<(), MemoryError> {
55 if self.window_size == 0 {
56 return Ok(());
57 }
58 if self.messages.len() >= self.window_size {
59 self.messages.pop_front();
60 }
61 self.messages.push_back(message);
62 Ok(())
63 }
64
65 async fn clear(&mut self) -> Result<(), MemoryError> {
66 self.messages.clear();
67 Ok(())
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use crate::schemas::MessageType;
75
76 #[tokio::test]
77 async fn keeps_only_last_window_size_messages() {
78 let mut memory = WindowBufferMemory::new(2);
79 memory.add_user_message(&"one").await.unwrap();
80 memory.add_ai_message(&"two").await.unwrap();
81 memory.add_user_message(&"three").await.unwrap();
82
83 let messages = memory.messages().await.unwrap();
84 assert_eq!(messages.len(), 2);
85 assert_eq!(messages[0].content, "two");
86 assert_eq!(messages[0].message_type, MessageType::AIMessage);
87 assert_eq!(messages[1].content, "three");
88 assert_eq!(messages[1].message_type, MessageType::HumanMessage);
89 }
90
91 #[tokio::test]
92 async fn default_window_is_ten() {
93 let mut memory = WindowBufferMemory::default();
94 for i in 0..15 {
95 memory.add_user_message(&i).await.unwrap();
96 }
97 let messages = memory.messages().await.unwrap();
98 assert_eq!(messages.len(), 10);
99 assert_eq!(messages.first().unwrap().content, "5");
100 assert_eq!(messages.last().unwrap().content, "14");
101 }
102
103 #[tokio::test]
104 async fn zero_window_stores_nothing_and_does_not_panic() {
105 let mut memory = WindowBufferMemory::new(0);
106 memory.add_user_message(&"hello").await.unwrap();
107 assert!(memory.messages().await.unwrap().is_empty());
108 }
109
110 #[tokio::test]
111 async fn clear_and_to_string() {
112 let mut memory = WindowBufferMemory::new(5);
113 memory.add_user_message(&"hi").await.unwrap();
114 memory.add_ai_message(&"hello").await.unwrap();
115 assert_eq!(memory.to_string().await.unwrap(), "human: hi\nai: hello");
116 memory.clear().await.unwrap();
117 assert!(memory.messages().await.unwrap().is_empty());
118 assert_eq!(memory.to_string().await.unwrap(), "");
119 }
120}