5baa170508
- README 添加 feature 组合表 + 模块级 features 清单 + 升级指南 - 18 个 example 顶部添加 Required features 注释 - roadmap.md 和 roadmap-v0.3.2.md 同步 Phase 26-27 完成状态 - cargo fmt 全量格式化(修复预存格式问题,CI format job 可通过)
137 lines
4.6 KiB
Rust
137 lines
4.6 KiB
Rust
//! conversation_memory_demo —— 对话记忆滑动窗口与隔离。
|
||
//! Required features: cargo run --example conversation_memory_demo --features "memory"
|
||
//!
|
||
//! 演示:
|
||
//! 1. `ConversationMemoryConfig` 构造(SlidingWindow / Full 策略)
|
||
//! 2. `add_message` 写入多角色消息(Message IR)
|
||
//! 3. 滑动窗口自动淘汰旧消息
|
||
//! 4. Full 策略保留全部
|
||
//! 5. `get_history` / `len` / `clear`
|
||
//! 6. 跨 session 数据隔离(共用 MemoryStore)
|
||
//!
|
||
//! 运行:`cargo run --example conversation_memory_demo`
|
||
|
||
use std::sync::Arc;
|
||
|
||
use agcore::llm::types::message::Message;
|
||
use agcore::memory::{ConversationMemory, ConversationMemoryConfig, InMemoryStore, MemoryStrategy};
|
||
|
||
fn message_text(msg: &Message) -> &str {
|
||
match msg {
|
||
Message::User { content }
|
||
| Message::System { content }
|
||
| Message::Assistant { content }
|
||
| Message::ToolResult { content, .. } => content
|
||
.iter()
|
||
.filter_map(|b| match b {
|
||
agcore::llm::types::message::ContentBlock::Text { text } => Some(text.as_str()),
|
||
_ => None,
|
||
})
|
||
.next()
|
||
.unwrap_or(""),
|
||
Message::UserImage { .. } => "[image]",
|
||
_ => "",
|
||
}
|
||
}
|
||
|
||
#[tokio::main]
|
||
async fn main() {
|
||
// 1. 滑动窗口策略:写入 5 条但只保留最近 3 条
|
||
println!("=== SlidingWindow 策略(max_turns=3)===");
|
||
let store = Arc::new(InMemoryStore::new());
|
||
let config = ConversationMemoryConfig {
|
||
strategy: MemoryStrategy::SlidingWindow,
|
||
max_turns: 3,
|
||
compact_config: None,
|
||
};
|
||
let mut memory = ConversationMemory::new(store, "session-1", config);
|
||
|
||
for i in 0..5 {
|
||
memory
|
||
.add_message(Message::user_text(format!("消息 {i}")))
|
||
.await
|
||
.expect("写入失败");
|
||
}
|
||
println!("写入 5 条 → len = {} (期望 3)", memory.len());
|
||
let history = memory.get_history();
|
||
for (i, msg) in history.iter().enumerate() {
|
||
println!(" [{}] {}", i, message_text(msg));
|
||
}
|
||
assert_eq!(memory.len(), 3);
|
||
assert_eq!(message_text(&history[0]), "消息 2", "最旧应是消息 2");
|
||
assert_eq!(message_text(&history[2]), "消息 4", "最新应是消息 4");
|
||
|
||
// 2. Full 策略:保留全部
|
||
println!("\n=== Full 策略(max_turns=3)===");
|
||
let store2 = Arc::new(InMemoryStore::new());
|
||
let config2 = ConversationMemoryConfig {
|
||
strategy: MemoryStrategy::Full,
|
||
max_turns: 3,
|
||
compact_config: None,
|
||
};
|
||
let mut memory2 = ConversationMemory::new(store2, "session-2", config2);
|
||
for i in 0..5 {
|
||
memory2
|
||
.add_message(Message::user_text(format!("Full {i}")))
|
||
.await
|
||
.unwrap();
|
||
}
|
||
println!("写入 5 条 → len = {} (期望 5)", memory2.len());
|
||
assert_eq!(memory2.len(), 5);
|
||
|
||
// 3. 多角色混合 + clear
|
||
println!("\n=== 多角色写入 + clear ===");
|
||
let store3 = Arc::new(InMemoryStore::new());
|
||
let mut memory3 =
|
||
ConversationMemory::new(store3, "session-3", ConversationMemoryConfig::default());
|
||
memory3
|
||
.add_message(Message::user_text("你好"))
|
||
.await
|
||
.unwrap();
|
||
memory3
|
||
.add_message(Message::assistant("你好!有什么可以帮你的吗?"))
|
||
.await
|
||
.unwrap();
|
||
memory3
|
||
.add_message(Message::user_text("今天天气怎么样?"))
|
||
.await
|
||
.unwrap();
|
||
memory3
|
||
.add_message(Message::assistant(
|
||
"我无法查询实时天气,但你可以查看天气应用。",
|
||
))
|
||
.await
|
||
.unwrap();
|
||
println!(
|
||
"写入 4 条多角色消息 → len = {}, 最后一条: {:?}",
|
||
memory3.len(),
|
||
message_text(memory3.get_history().last().unwrap())
|
||
);
|
||
assert_eq!(memory3.len(), 4);
|
||
|
||
memory3.clear().await.unwrap();
|
||
println!(
|
||
"clear 后 → len = {}, is_empty = {}",
|
||
memory3.len(),
|
||
memory3.is_empty()
|
||
);
|
||
assert!(memory3.is_empty());
|
||
|
||
// 4. Session 隔离
|
||
println!("\n=== Session 隔离(共用 InMemoryStore)===");
|
||
let store4 = Arc::new(InMemoryStore::new());
|
||
let mut a = ConversationMemory::new(store4.clone(), "s-a", ConversationMemoryConfig::default());
|
||
let mut b = ConversationMemory::new(store4.clone(), "s-b", ConversationMemoryConfig::default());
|
||
a.add_message(Message::user_text("A 的消息")).await.unwrap();
|
||
b.add_message(Message::user_text("B 的消息")).await.unwrap();
|
||
println!(
|
||
"A.len = {}, B.len = {} (期望 1/1,互不污染)",
|
||
a.len(),
|
||
b.len()
|
||
);
|
||
assert_eq!(a.len(), 1);
|
||
assert_eq!(b.len(), 1);
|
||
|
||
println!("\n✓ conversation_memory_demo 完成");
|
||
}
|