From a21a891c1c676f6e81b8e9d8d1c75bba63fb5763 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Wed, 21 Jan 2026 18:17:04 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 85 +++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/memory/working_memory/sliding_window.rs diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs new file mode 100644 index 0000000..6b79d99 --- /dev/null +++ b/src/memory/working_memory/sliding_window.rs @@ -0,0 +1,85 @@ +use std::collections::VecDeque + +//滑动窗口(容器、容量、标记窗口)通过标记窗口中对应索引是否为true来判断是否被标记 +pub struct SlidingWindow { + window: VecDeque, + capacity: usize, + tag_window: VecDeque, + tag_count: usize +} + +impl SlidingWindow { + //新建 + pub fn new(capacity: usize) -> Self { + Self { + window: VecDeque::with_capacity(capacity), + capacity, + tag_window: VecDeque::with_capacity(capacity), + tag_count: 0 + } + } + //信息滑入,对应标记窗口滑入false,返回被弹出的信息,若未满或弹出未标记的信息则返回None,若弹出被标记信息则返回Some(该信息) + pub fn push(&mut self, value: T) -> Option { + let target = None; + if self.window.len() == self.capacity { + target = self.pop(); + } + self.capacity += 1; + self.window.push_back(value); + self.auto_tag(); + target + } + //信息滑出,返回被弹出的信息,若未满或弹出未标记的信息则返回None,若弹出被标记信息则返回Some(该信息) + pub fn pop(&mut self) -> Option { + if self.tag_window.get(0).copied() == Some(true) { + let target = Some(self.dwindow.pop_front()); + self.capacity -= 1; + self.tag_window.pop_front(); + target + } else { + self.window.pop_front(); + self.capacity -= 1; + self.tag_window.pop_front(); + None + } + } + //获取窗口大小 + pub fn len(&self) -> usize { + self.window.len() + } + //获取窗口容量 + pub fn get_capacity(&self) -> usize { + self.capacity + } + //获取窗口容量(可变) + pub fn get_mut_capacity(&mut self) -> &mut usize { + &mut self.capacity + } + //判断窗口是否为空 + pub fn is_empty(&self) -> bool { + self.window.is_empty() + } + //标记用 + pub fn tag_information(&mut self, index: usize) { + if index < self.capacity { + self.tag_window[index] = true; + } + } + //取消标记用 + pub fn untag_information(&mut self, index: usize) { + if index < self.capacity { + self.tag_window[index] = false; + } + } + //每滑出capacity次信息时进行一次标记 + fn auto_tag(&mut self) { + self.tag_count += 1; + if self.tag_count == self.capacity { + self.tag_window.push_back(true); + self.tag_count = 0; + } + else{ + self.tag_window.push_back(false); + } + } +} From a6b15e190ebd82160e8af1adbca2bae9677b9824 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Wed, 21 Jan 2026 22:00:14 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 102 +++++++++++++------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index 6b79d99..eb4d723 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,47 +1,44 @@ use std::collections::VecDeque -//滑动窗口(容器、容量、标记窗口)通过标记窗口中对应索引是否为true来判断是否被标记 -pub struct SlidingWindow { - window: VecDeque, +//滑动窗口(容器、容量、标记计数、摘要用临时储存) +pub struct SlidingWindow { + window: VecDeque, capacity: usize, - tag_window: VecDeque, - tag_count: usize + tag_count: usize, + summary: Vec } -impl SlidingWindow { +impl SlidingWindow { //新建 pub fn new(capacity: usize) -> Self { Self { window: VecDeque::with_capacity(capacity), - capacity, - tag_window: VecDeque::with_capacity(capacity), - tag_count: 0 + capacity: 0, + tag_count: 0, + summary: Vec::with_capacity(capacity) } } - //信息滑入,对应标记窗口滑入false,返回被弹出的信息,若未满或弹出未标记的信息则返回None,若弹出被标记信息则返回Some(该信息) - pub fn push(&mut self, value: T) -> Option { - let target = None; + //信息滑入,若滑出时信息有标记则发送摘要用片段 + pub fn push(&mut self, value: information) -> Option> { + value = self.auto_tag(value); + let is_tagged: bool = false; + let target: Option = None; if self.window.len() == self.capacity { - target = self.pop(); + is_tagged = self.pop(); + } + if is_tagged { + target = self.summarize(); } self.capacity += 1; self.window.push_back(value); - self.auto_tag(); target } - //信息滑出,返回被弹出的信息,若未满或弹出未标记的信息则返回None,若弹出被标记信息则返回Some(该信息) - pub fn pop(&mut self) -> Option { - if self.tag_window.get(0).copied() == Some(true) { - let target = Some(self.dwindow.pop_front()); - self.capacity -= 1; - self.tag_window.pop_front(); - target - } else { - self.window.pop_front(); - self.capacity -= 1; - self.tag_window.pop_front(); - None - } + //信息滑出,返回弹出信息是否被标记 + pub fn pop(&mut self) -> bool { + let target = self.window.pop_front(); + self.capacity -= 1; + self.summary.push(target.clone()); + self.get_tagged(target) } //获取窗口大小 pub fn len(&self) -> usize { @@ -59,27 +56,64 @@ impl SlidingWindow { pub fn is_empty(&self) -> bool { self.window.is_empty() } + //清空窗口 + pub fn clear(&mut self) { + self.window.clear(); + self.capacity = 0; + self.tag_count = 0; + self.summary.clear(); + } //标记用 pub fn tag_information(&mut self, index: usize) { if index < self.capacity { - self.tag_window[index] = true; + self.window[index].tag_information(); } } //取消标记用 pub fn untag_information(&mut self, index: usize) { if index < self.capacity { - self.tag_window[index] = false; + self.window[index].untag_information(); } } //每滑出capacity次信息时进行一次标记 - fn auto_tag(&mut self) { + fn auto_tag(&mut self, value: information) -> information { self.tag_count += 1; if self.tag_count == self.capacity { - self.tag_window.push_back(true); + value.tag_information(); self.tag_count = 0; } - else{ - self.tag_window.push_back(false); - } + value + } + //给出摘要 + pub fn summarize(&mut self) -> Vec { + self.summary.drain(..).collect() + } + //检测是否存在标记信息 + pub fn is_tagged(&mut self, value: information) -> bool { + value.is_tagged() + } + +} + +pub struct information { + pub text: String, + pub tag: bool, +} + +impl information { + pub fn new(text: String) -> Self { + Self { text, false } + } + pub fn tag_information(&mut self) { + self.tag = true; + } + pub fn untag_information(&mut self) { + self.tag = false; + } + pub fn is_tagged(&self) -> bool { + self.tag + } + pub fn get_mut_capacity(&mut self) -> &mut usize { + &mut self.capacity } } From 6252d7d599ae965e6a2d2d1548b9918cece7b32c Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Wed, 21 Jan 2026 22:06:35 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index eb4d723..b19e3f3 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -75,7 +75,7 @@ impl SlidingWindow { self.window[index].untag_information(); } } - //每滑出capacity次信息时进行一次标记 + //每滑入capacity次信息时进行一次标记 fn auto_tag(&mut self, value: information) -> information { self.tag_count += 1; if self.tag_count == self.capacity { From 0089a4760a3ba91bf131423d8b5c837ce7be9ec2 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Fri, 23 Jan 2026 23:08:53 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index b19e3f3..daf9321 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,14 +1,14 @@ use std::collections::VecDeque //滑动窗口(容器、容量、标记计数、摘要用临时储存) -pub struct SlidingWindow { - window: VecDeque, +pub struct SlidingWindow { + window: VecDeque, capacity: usize, tag_count: usize, - summary: Vec + summary: Vec } -impl SlidingWindow { +impl SlidingWindow { //新建 pub fn new(capacity: usize) -> Self { Self { @@ -19,10 +19,10 @@ impl SlidingWindow { } } //信息滑入,若滑出时信息有标记则发送摘要用片段 - pub fn push(&mut self, value: information) -> Option> { + pub fn push(&mut self, value: Information) -> Option> { value = self.auto_tag(value); let is_tagged: bool = false; - let target: Option = None; + let target: Option = None; if self.window.len() == self.capacity { is_tagged = self.pop(); } @@ -76,7 +76,7 @@ impl SlidingWindow { } } //每滑入capacity次信息时进行一次标记 - fn auto_tag(&mut self, value: information) -> information { + fn auto_tag(&mut self, value: Information) -> Information { self.tag_count += 1; if self.tag_count == self.capacity { value.tag_information(); @@ -85,22 +85,22 @@ impl SlidingWindow { value } //给出摘要 - pub fn summarize(&mut self) -> Vec { + pub fn summarize(&mut self) -> Vec { self.summary.drain(..).collect() } //检测是否存在标记信息 - pub fn is_tagged(&mut self, value: information) -> bool { + pub fn is_tagged(&mut self, value: Information) -> bool { value.is_tagged() } } -pub struct information { +pub struct Information { pub text: String, pub tag: bool, } -impl information { +impl Information { pub fn new(text: String) -> Self { Self { text, false } } From 40ae2a4cab16229f557b7444ad24b7c25d7403f2 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Sun, 1 Feb 2026 12:30:35 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index daf9321..bebf07a 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -19,7 +19,7 @@ impl SlidingWindow { } } //信息滑入,若滑出时信息有标记则发送摘要用片段 - pub fn push(&mut self, value: Information) -> Option> { + pub fn push(&mut self, value: Information) -> Vec { value = self.auto_tag(value); let is_tagged: bool = false; let target: Option = None; From 9a93d4250b0dee9a8fbd164f781beeac4bd4192a Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 00:48:24 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 15 ++++ Cargo.toml | 1 + src/memory/working_memory/sliding_window.rs | 97 +++++++++++++++------ 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 010a3a3..7ee346d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -308,6 +308,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "async-openai" +version = "0.32.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4d91c2005832450ad9ac92411b9d4cec39e30be21adc76553efc47f812d59c7" +dependencies = [ + "getrandom 0.3.3", + "reqwest", + "serde", + "serde_json", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -2085,6 +2097,7 @@ dependencies = [ "hyper", "hyper-util", "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", "tokio-rustls", @@ -4159,6 +4172,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -4902,6 +4916,7 @@ version = "0.1.0" dependencies = [ "anyhow", "approx 0.5.1", + "async-openai", "async-trait", "chrono", "dotenvy", diff --git a/Cargo.toml b/Cargo.toml index bc21d69..3f3c88a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ dotenvy = "0.15.7" tokio-util = "0.7.16" toml = "0.9.5" thiserror = "2.0.17" +async-openai = "0.32.4" [profile.release] lto = true diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index bebf07a..f4d1a7e 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,11 +1,16 @@ -use std::collections::VecDeque +use std::collections::VecDeque; +use tokio::sync::mpsc; +use async_openai::{ + types::{CreateChatCompletionRequest, ChatCompletionRequestMessage}, + Client, +}; //滑动窗口(容器、容量、标记计数、摘要用临时储存) pub struct SlidingWindow { window: VecDeque, capacity: usize, tag_count: usize, - summary: Vec + summary: String, } impl SlidingWindow { @@ -13,32 +18,31 @@ impl SlidingWindow { pub fn new(capacity: usize) -> Self { Self { window: VecDeque::with_capacity(capacity), - capacity: 0, + capacity, tag_count: 0, - summary: Vec::with_capacity(capacity) + summary: String::new(), } } - //信息滑入,若滑出时信息有标记则发送摘要用片段 - pub fn push(&mut self, value: Information) -> Vec { + //信息滑入 + pub fn push(&mut self, value: Information) { value = self.auto_tag(value); - let is_tagged: bool = false; - let target: Option = None; if self.window.len() == self.capacity { - is_tagged = self.pop(); + self.pop(); } - if is_tagged { - target = self.summarize(); - } - self.capacity += 1; self.window.push_back(value); - target } - //信息滑出,返回弹出信息是否被标记 - pub fn pop(&mut self) -> bool { + //信息滑出,若信息被标记则进行摘要 + pub fn pop(&mut self) { let target = self.window.pop_front(); - self.capacity -= 1; - self.summary.push(target.clone()); - self.get_tagged(target) + if target.is_tagged() { + let summary = self.summarize(); + tokio::spawn(async move { + match call_llm(summary).await { + Ok(response) => { + self.set_summary(response); + } + Err(e) => eprintln!("LLM error for id {}: {}", id, e), + } } //获取窗口大小 pub fn len(&self) -> usize { @@ -56,10 +60,9 @@ impl SlidingWindow { pub fn is_empty(&self) -> bool { self.window.is_empty() } - //清空窗口 + //清空窗口内容 pub fn clear(&mut self) { self.window.clear(); - self.capacity = 0; self.tag_count = 0; self.summary.clear(); } @@ -78,19 +81,29 @@ impl SlidingWindow { //每滑入capacity次信息时进行一次标记 fn auto_tag(&mut self, value: Information) -> Information { self.tag_count += 1; - if self.tag_count == self.capacity { + if self.tag_count >= self.capacity { value.tag_information(); self.tag_count = 0; } value } - //给出摘要 - pub fn summarize(&mut self) -> Vec { - self.summary.drain(..).collect() + + //将摘要记忆和当前滑动窗口信息合并 + pub fn summarize(&mut self) -> String { + let mut summary = self.summary; + for (index, i) in self.window.iter().enumerate() { + summary.push_str(index.to_string()); + summary.push_str(&i.text); + } + summary } - //检测是否存在标记信息 - pub fn is_tagged(&mut self, value: Information) -> bool { - value.is_tagged() + //将返回摘要记忆存入 + pub fn set_summary(&mut self, summary: String) { + self.summary = summary; + } + //将摘要记忆清空 + pub fn clear_summary(&mut self) { + self.summary.clear(); } } @@ -117,3 +130,31 @@ impl Information { &mut self.capacity } } + +async fn call_llm(summary: String) -> Result> { + let client = Client::new(); + + let request = CreateChatCompletionRequest { + model: "unknown".to_string(), + messages: vec![ChatCompletionRequestMessage { + role: "user".to_string(), + content: summary, + ..Default::default() + }], + ..Default::default() + }; + let response = client.chat().create(request).await?; + let output = response + .choices + .first() + .and_then(|c| c.message.content.clone()) + .unwrap_or_default(); + + Ok(output) +} + + +#[cfg(test)] +fn test_call(summary: String) -> Result{ + Ok("success".to_string()) +} From c7beed6ee09d0780edbcd1b2e8f901a1eb2fa2c4 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 13:06:04 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory.rs | 1 + src/memory/working_memory.rs | 1 + src/memory/working_memory/sliding_window.rs | 156 ++++++++++++++------ 3 files changed, 109 insertions(+), 49 deletions(-) create mode 100644 src/memory/working_memory.rs diff --git a/src/memory.rs b/src/memory.rs index 6df01bd..e6a35dd 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -2,3 +2,4 @@ pub mod embedding; pub mod memory_cluster; pub mod memory_links; pub mod memory_note; +pub mod working_memory; diff --git a/src/memory/working_memory.rs b/src/memory/working_memory.rs new file mode 100644 index 0000000..8472d2f --- /dev/null +++ b/src/memory/working_memory.rs @@ -0,0 +1 @@ +pub mod sliding_window; diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index f4d1a7e..3285799 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,47 +1,53 @@ use std::collections::VecDeque; use tokio::sync::mpsc; -use async_openai::{ - types::{CreateChatCompletionRequest, ChatCompletionRequestMessage}, - Client, -}; +// use async_openai::{ +// types::{CreateChatCompletionRequest, ChatCompletionRequestMessage}, +// Client, +// }; + //滑动窗口(容器、容量、标记计数、摘要用临时储存) -pub struct SlidingWindow { +pub struct SlidingWindow { window: VecDeque, capacity: usize, tag_count: usize, summary: String, } -impl SlidingWindow { +impl SlidingWindow { //新建 pub fn new(capacity: usize) -> Self { Self { - window: VecDeque::with_capacity(capacity), + window: VecDeque::with_capacity(capacity+1), capacity, - tag_count: 0, + tag_count: capacity, summary: String::new(), } } //信息滑入 - pub fn push(&mut self, value: Information) { + pub fn push(&mut self, mut value: Information) { value = self.auto_tag(value); - if self.window.len() == self.capacity { + self.window.push_back(value); + if self.window.len() == (self.capacity+1) { self.pop(); } - self.window.push_back(value); } //信息滑出,若信息被标记则进行摘要 pub fn pop(&mut self) { let target = self.window.pop_front(); - if target.is_tagged() { - let summary = self.summarize(); - tokio::spawn(async move { - match call_llm(summary).await { - Ok(response) => { - self.set_summary(response); - } - Err(e) => eprintln!("LLM error for id {}: {}", id, e), + if let Some(value) = target { + if value.is_tagged() { + let summary = self.summarize(); + self.set_summary(test_summary(summary)); + // tokio::spawn(async move { + // match call_llm(summary).await { + // Ok(response) => { + // self.set_summary(response); + // } + // Err(e) => eprintln!("LLM Error"), + // } + // }); + } } } //获取窗口大小 @@ -56,6 +62,14 @@ impl SlidingWindow { pub fn get_mut_capacity(&mut self) -> &mut usize { &mut self.capacity } + //获取窗口中指定索引的信息 + pub fn get(&self, index: usize) -> Option<&Information> { + self.window.get(index) + } + //获取摘要记忆 + pub fn get_summary(&self) -> &String { + &self.summary + } //判断窗口是否为空 pub fn is_empty(&self) -> bool { self.window.is_empty() @@ -79,7 +93,7 @@ impl SlidingWindow { } } //每滑入capacity次信息时进行一次标记 - fn auto_tag(&mut self, value: Information) -> Information { + fn auto_tag(&mut self, mut value: Information) -> Information { self.tag_count += 1; if self.tag_count >= self.capacity { value.tag_information(); @@ -90,10 +104,10 @@ impl SlidingWindow { //将摘要记忆和当前滑动窗口信息合并 pub fn summarize(&mut self) -> String { - let mut summary = self.summary; + let mut summary = self.summary.clone(); for (index, i) in self.window.iter().enumerate() { - summary.push_str(index.to_string()); - summary.push_str(&i.text); + summary.push_str(&index.to_string()); + summary.push_str(&i.to_string()); } summary } @@ -115,46 +129,90 @@ pub struct Information { impl Information { pub fn new(text: String) -> Self { - Self { text, false } + Self { text, tag: false } } pub fn tag_information(&mut self) { - self.tag = true; + self.tag = true } pub fn untag_information(&mut self) { - self.tag = false; + self.tag = false } pub fn is_tagged(&self) -> bool { self.tag } - pub fn get_mut_capacity(&mut self) -> &mut usize { - &mut self.capacity + pub fn to_string(&self) -> String { + self.text.clone() } } -async fn call_llm(summary: String) -> Result> { - let client = Client::new(); +fn test_summary(summary: String) -> String { + println!("{}", summary.clone()); + summary +} - let request = CreateChatCompletionRequest { - model: "unknown".to_string(), - messages: vec![ChatCompletionRequestMessage { - role: "user".to_string(), - content: summary, - ..Default::default() - }], - ..Default::default() - }; - let response = client.chat().create(request).await?; - let output = response - .choices - .first() - .and_then(|c| c.message.content.clone()) - .unwrap_or_default(); +// async fn call_llm(summary: String) -> Result> { +// let client = Client::new(); - Ok(output) -} +// let request = CreateChatCompletionRequest { +// model: "unknown".to_string(), +// messages: vec![ChatCompletionRequestMessage { +// role: "user".to_string(), +// content: summary, +// ..Default::default() +// }], +// ..Default::default() +// }; +// let response = client.chat().create(request).await?; +// let output = response +// .choices +// .first() +// .and_then(|c| c.message.content.clone()) +// .unwrap_or_default(); + +// Ok(output) +// } #[cfg(test)] -fn test_call(summary: String) -> Result{ - Ok("success".to_string()) +mod slidingwindow_test{ + use super::*; + + async fn SlidingWindowtest_call(summary: String) -> Result> { + Ok("success".to_string()) + } + #[test] + fn SlidingWindowtest_push(){ + let mut window = SlidingWindow::new(10); + let info = Information::new("test1".to_string()); + window.push(info); + let info2 = Information::new("test2".to_string()); + window.push(info2); + assert_eq!(window.get(0).unwrap().text, "test1"); + assert_eq!(window.get(1).unwrap().text, "test2"); + } + #[test] + fn SlidingWindowtest_pop(){ + let mut window = SlidingWindow::new(10); + let info = Information::new("test1".to_string()); + window.push(info); + let info2 = Information::new("test2".to_string()); + window.push(info2); + let _ = window.pop(); + assert_eq!(window.get(0).unwrap().text, "test2"); + } + #[test] + fn SlidingWindowtest_summary_and_tag(){ + let mut window = SlidingWindow::new(2); + let info = Information::new("test1".to_string()); + window.push(info); + let info2 = Information::new("test2".to_string()); + window.push(info2); + let info3 = Information::new("test3".to_string()); + window.push(info3); + assert_eq!(window.get_summary(), "0test21test3"); + let test = window.get(1); + if let Some(value) = test { + assert!(value.is_tagged()); + } + } } From 80759c7bfcf021ae32d3a68aa837abd8c3164c71 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 13:24:24 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index 3285799..e1c7134 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -177,11 +177,11 @@ fn test_summary(summary: String) -> String { mod slidingwindow_test{ use super::*; - async fn SlidingWindowtest_call(summary: String) -> Result> { - Ok("success".to_string()) + // async fn SlidingWindowtest_call(summary: String) -> Result> { + // Ok("success".to_string()) } #[test] - fn SlidingWindowtest_push(){ + fn sliding_window_test_push(){ let mut window = SlidingWindow::new(10); let info = Information::new("test1".to_string()); window.push(info); @@ -191,7 +191,7 @@ mod slidingwindow_test{ assert_eq!(window.get(1).unwrap().text, "test2"); } #[test] - fn SlidingWindowtest_pop(){ + fn sliding_window_test_pop(){ let mut window = SlidingWindow::new(10); let info = Information::new("test1".to_string()); window.push(info); @@ -201,7 +201,7 @@ mod slidingwindow_test{ assert_eq!(window.get(0).unwrap().text, "test2"); } #[test] - fn SlidingWindowtest_summary_and_tag(){ + fn sliding_window_test_summary_and_tag(){ let mut window = SlidingWindow::new(2); let info = Information::new("test1".to_string()); window.push(info); From 2c36428f2d0e49c4d70dbd6e0ee886e1b533503b Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 15:12:01 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 116 +++++++++++--------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index e1c7134..7dbfbb1 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,5 +1,9 @@ use std::collections::VecDeque; use tokio::sync::mpsc; +use std::sync::{Arc, Mutex}; +use tokio::time::{sleep, Duration}; +use tokio::runtime::Runtime; + // use async_openai::{ // types::{CreateChatCompletionRequest, ChatCompletionRequestMessage}, // Client, @@ -11,7 +15,7 @@ pub struct SlidingWindow { window: VecDeque, capacity: usize, tag_count: usize, - summary: String, + summary: Arc>, } impl SlidingWindow { @@ -21,7 +25,7 @@ impl SlidingWindow { window: VecDeque::with_capacity(capacity+1), capacity, tag_count: capacity, - summary: String::new(), + summary: Arc::new(Mutex::new(String::new())), } } //信息滑入 @@ -37,16 +41,7 @@ impl SlidingWindow { let target = self.window.pop_front(); if let Some(value) = target { if value.is_tagged() { - let summary = self.summarize(); - self.set_summary(test_summary(summary)); - // tokio::spawn(async move { - // match call_llm(summary).await { - // Ok(response) => { - // self.set_summary(response); - // } - // Err(e) => eprintln!("LLM Error"), - // } - // }); + self.summarize(); } } } @@ -67,8 +62,8 @@ impl SlidingWindow { self.window.get(index) } //获取摘要记忆 - pub fn get_summary(&self) -> &String { - &self.summary + pub fn get_summary(&self) -> Arc> { + self.summary.clone() } //判断窗口是否为空 pub fn is_empty(&self) -> bool { @@ -78,7 +73,7 @@ impl SlidingWindow { pub fn clear(&mut self) { self.window.clear(); self.tag_count = 0; - self.summary.clear(); + self.clear_summary(); } //标记用 pub fn tag_information(&mut self, index: usize) { @@ -102,22 +97,31 @@ impl SlidingWindow { value } - //将摘要记忆和当前滑动窗口信息合并 - pub fn summarize(&mut self) -> String { - let mut summary = self.summary.clone(); + //将摘要记忆和当前滑动窗口信息合并提供LLM + fn summarize(&self) { + let mut summary_text = self.summary.lock().unwrap().clone(); + for (index, i) in self.window.iter().enumerate() { - summary.push_str(&index.to_string()); - summary.push_str(&i.to_string()); + summary_text.push_str(&index.to_string()); + summary_text.push_str(&i.to_string()); } - summary - } - //将返回摘要记忆存入 - pub fn set_summary(&mut self, summary: String) { - self.summary = summary; + + let summary_arc = self.summary.clone(); + + tokio::spawn(async move { + match call_llm(&summary_text).await { + Ok(response) => { + *summary_arc.lock().unwrap() = response; + println!("Summary updated in background."); + } + Err(e) => eprintln!("LLM Error: {}", e), + } + }); } + //将摘要记忆清空 - pub fn clear_summary(&mut self) { - self.summary.clear(); + fn clear_summary(&mut self) { + self.summary.lock().unwrap().clear(); } } @@ -150,27 +154,29 @@ fn test_summary(summary: String) -> String { summary } -// async fn call_llm(summary: String) -> Result> { -// let client = Client::new(); - -// let request = CreateChatCompletionRequest { -// model: "unknown".to_string(), -// messages: vec![ChatCompletionRequestMessage { -// role: "user".to_string(), -// content: summary, -// ..Default::default() -// }], -// ..Default::default() -// }; -// let response = client.chat().create(request).await?; -// let output = response -// .choices -// .first() -// .and_then(|c| c.message.content.clone()) -// .unwrap_or_default(); - -// Ok(output) -// } + +async fn call_llm(summary: &String) -> Result> { + // let client = Client::new(); + + // let request = CreateChatCompletionRequest { + // model: "unknown".to_string(), + // messages: vec![ChatCompletionRequestMessage { + // role: "user".to_string(), + // content: summary, + // ..Default::default() + // }], + // ..Default::default() + // }; + // let response = client.chat().create(request).await?; + // let output = response + // .choices + // .first() + // .and_then(|c| c.message.content.clone()) + // .unwrap_or_default(); + sleep(Duration::from_millis(500)).await; + let output = summary.clone(); + Ok(output) +} #[cfg(test)] @@ -179,7 +185,7 @@ mod slidingwindow_test{ // async fn SlidingWindowtest_call(summary: String) -> Result> { // Ok("success".to_string()) - } + // } #[test] fn sliding_window_test_push(){ let mut window = SlidingWindow::new(10); @@ -190,18 +196,19 @@ mod slidingwindow_test{ assert_eq!(window.get(0).unwrap().text, "test1"); assert_eq!(window.get(1).unwrap().text, "test2"); } - #[test] - fn sliding_window_test_pop(){ + #[tokio::test] + async fn sliding_window_test_pop(){ let mut window = SlidingWindow::new(10); let info = Information::new("test1".to_string()); window.push(info); let info2 = Information::new("test2".to_string()); window.push(info2); + sleep(Duration::from_millis(500)).await; let _ = window.pop(); assert_eq!(window.get(0).unwrap().text, "test2"); } - #[test] - fn sliding_window_test_summary_and_tag(){ + #[tokio::test] + async fn sliding_window_test_summary_and_tag(){ let mut window = SlidingWindow::new(2); let info = Information::new("test1".to_string()); window.push(info); @@ -209,7 +216,8 @@ mod slidingwindow_test{ window.push(info2); let info3 = Information::new("test3".to_string()); window.push(info3); - assert_eq!(window.get_summary(), "0test21test3"); + sleep(Duration::from_millis(1000)).await; + assert_eq!(window.get_summary().lock().unwrap().as_str(), "0test21test3"); let test = window.get(1); if let Some(value) = test { assert!(value.is_tagged()); From ed37fbfcbdf6d6de4e056fa2e3fe279c11f3d885 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 18:04:01 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 65 +++++++++++---------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index 7dbfbb1..d7f4f4d 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -1,6 +1,7 @@ use std::collections::VecDeque; use tokio::sync::mpsc; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; +use std::error::Error; use tokio::time::{sleep, Duration}; use tokio::runtime::Runtime; @@ -15,7 +16,7 @@ pub struct SlidingWindow { window: VecDeque, capacity: usize, tag_count: usize, - summary: Arc>, + summary: Arc>, } impl SlidingWindow { @@ -25,25 +26,27 @@ impl SlidingWindow { window: VecDeque::with_capacity(capacity+1), capacity, tag_count: capacity, - summary: Arc::new(Mutex::new(String::new())), + summary: Arc::new(RwLock::new(String::new())), } } //信息滑入 - pub fn push(&mut self, mut value: Information) { + pub async fn push(&mut self, mut value: Information) -> Result<(), Box> { value = self.auto_tag(value); self.window.push_back(value); if self.window.len() == (self.capacity+1) { - self.pop(); + self.pop().await?; } + Ok(()) } //信息滑出,若信息被标记则进行摘要 - pub fn pop(&mut self) { + pub async fn pop(&mut self) -> Result<(), Box> { let target = self.window.pop_front(); if let Some(value) = target { if value.is_tagged() { - self.summarize(); + self.summarize().await?; } } + Ok(()) } //获取窗口大小 pub fn len(&self) -> usize { @@ -62,7 +65,7 @@ impl SlidingWindow { self.window.get(index) } //获取摘要记忆 - pub fn get_summary(&self) -> Arc> { + pub fn get_summary(&self) -> Arc> { self.summary.clone() } //判断窗口是否为空 @@ -98,8 +101,8 @@ impl SlidingWindow { } //将摘要记忆和当前滑动窗口信息合并提供LLM - fn summarize(&self) { - let mut summary_text = self.summary.lock().unwrap().clone(); + async fn summarize(&self) -> Result>, Box> { + let mut summary_text = self.summary.write().unwrap().clone(); for (index, i) in self.window.iter().enumerate() { summary_text.push_str(&index.to_string()); @@ -108,20 +111,20 @@ impl SlidingWindow { let summary_arc = self.summary.clone(); - tokio::spawn(async move { - match call_llm(&summary_text).await { - Ok(response) => { - *summary_arc.lock().unwrap() = response; - println!("Summary updated in background."); - } - Err(e) => eprintln!("LLM Error: {}", e), + match call_llm(&summary_text).await { + Ok(response) => { + *summary_arc.write().unwrap() = response; + println!("Summary updated in background."); } - }); + Err(e) => eprintln!("LLM Error: {}", e), + } + + Ok(summary_arc) } //将摘要记忆清空 fn clear_summary(&mut self) { - self.summary.lock().unwrap().clear(); + self.summary.write().unwrap().clear(); } } @@ -186,13 +189,13 @@ mod slidingwindow_test{ // async fn SlidingWindowtest_call(summary: String) -> Result> { // Ok("success".to_string()) // } - #[test] - fn sliding_window_test_push(){ + #[tokio::test] + async fn sliding_window_test_push(){ let mut window = SlidingWindow::new(10); let info = Information::new("test1".to_string()); - window.push(info); + window.push(info).await; let info2 = Information::new("test2".to_string()); - window.push(info2); + window.push(info2).await; assert_eq!(window.get(0).unwrap().text, "test1"); assert_eq!(window.get(1).unwrap().text, "test2"); } @@ -200,24 +203,22 @@ mod slidingwindow_test{ async fn sliding_window_test_pop(){ let mut window = SlidingWindow::new(10); let info = Information::new("test1".to_string()); - window.push(info); + window.push(info).await; let info2 = Information::new("test2".to_string()); - window.push(info2); - sleep(Duration::from_millis(500)).await; - let _ = window.pop(); + window.push(info2).await; + window.pop().await; assert_eq!(window.get(0).unwrap().text, "test2"); } #[tokio::test] async fn sliding_window_test_summary_and_tag(){ let mut window = SlidingWindow::new(2); let info = Information::new("test1".to_string()); - window.push(info); + window.push(info).await; let info2 = Information::new("test2".to_string()); - window.push(info2); + window.push(info2).await; let info3 = Information::new("test3".to_string()); - window.push(info3); - sleep(Duration::from_millis(1000)).await; - assert_eq!(window.get_summary().lock().unwrap().as_str(), "0test21test3"); + window.push(info3).await; + assert_eq!(window.get_summary().write().unwrap().as_str(), "0test21test3"); let test = window.get(1); if let Some(value) = test { assert!(value.is_tagged()); From c7d534cc7e2dcaed908ad799c8eaa6bc5eba50a5 Mon Sep 17 00:00:00 2001 From: seeleseelesee <2448828513@qq.com> Date: Mon, 2 Feb 2026 23:58:18 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=94=B94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/memory/working_memory/sliding_window.rs | 39 ++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/memory/working_memory/sliding_window.rs b/src/memory/working_memory/sliding_window.rs index d7f4f4d..35e966b 100644 --- a/src/memory/working_memory/sliding_window.rs +++ b/src/memory/working_memory/sliding_window.rs @@ -64,10 +64,7 @@ impl SlidingWindow { pub fn get(&self, index: usize) -> Option<&Information> { self.window.get(index) } - //获取摘要记忆 - pub fn get_summary(&self) -> Arc> { - self.summary.clone() - } + //判断窗口是否为空 pub fn is_empty(&self) -> bool { self.window.is_empty() @@ -76,7 +73,6 @@ impl SlidingWindow { pub fn clear(&mut self) { self.window.clear(); self.tag_count = 0; - self.clear_summary(); } //标记用 pub fn tag_information(&mut self, index: usize) { @@ -102,7 +98,13 @@ impl SlidingWindow { //将摘要记忆和当前滑动窗口信息合并提供LLM async fn summarize(&self) -> Result>, Box> { - let mut summary_text = self.summary.write().unwrap().clone(); + let mut summary_text = match self.summary.write() { + Ok(mut value) => value.clone(), + Err(e) => { + eprintln!("Summary Error: {}", e); + String::new() + } + }; for (index, i) in self.window.iter().enumerate() { summary_text.push_str(&index.to_string()); @@ -113,8 +115,13 @@ impl SlidingWindow { match call_llm(&summary_text).await { Ok(response) => { - *summary_arc.write().unwrap() = response; - println!("Summary updated in background."); + match summary_arc.write() { + Ok(mut value) => { + println!("Summary updated in background."); + *value = response + }, + Err(e) => eprintln!("LLM Error: {}", e), + } } Err(e) => eprintln!("LLM Error: {}", e), } @@ -122,11 +129,6 @@ impl SlidingWindow { Ok(summary_arc) } - //将摘要记忆清空 - fn clear_summary(&mut self) { - self.summary.write().unwrap().clear(); - } - } pub struct Information { @@ -186,9 +188,6 @@ async fn call_llm(summary: &String) -> Result Result> { - // Ok("success".to_string()) - // } #[tokio::test] async fn sliding_window_test_push(){ let mut window = SlidingWindow::new(10); @@ -196,8 +195,8 @@ mod slidingwindow_test{ window.push(info).await; let info2 = Information::new("test2".to_string()); window.push(info2).await; - assert_eq!(window.get(0).unwrap().text, "test1"); - assert_eq!(window.get(1).unwrap().text, "test2"); + assert_eq!(window.get(0).expect("not found this information").text, "test1"); + assert_eq!(window.get(1).expect("not found this information").text, "test2"); } #[tokio::test] async fn sliding_window_test_pop(){ @@ -207,7 +206,7 @@ mod slidingwindow_test{ let info2 = Information::new("test2".to_string()); window.push(info2).await; window.pop().await; - assert_eq!(window.get(0).unwrap().text, "test2"); + assert_eq!(window.get(0).expect("not found this information").text, "test2"); } #[tokio::test] async fn sliding_window_test_summary_and_tag(){ @@ -218,7 +217,7 @@ mod slidingwindow_test{ window.push(info2).await; let info3 = Information::new("test3".to_string()); window.push(info3).await; - assert_eq!(window.get_summary().write().unwrap().as_str(), "0test21test3"); + assert_eq!(window.summary.read().unwrap().as_str(), "0test21test3"); let test = window.get(1); if let Some(value) = test { assert!(value.is_tagged());