Files
agcore/examples/conversation_memory_demo.rs
T
徐涛 6e1182e64c feat(core): 14 个公开枚举标记 #[non_exhaustive]
为 v0.2.0-rc.1 API 稳定性收尾。覆盖:
- P0 核心 IR: Message / ContentBlock / ContentBlockType / StreamEvent / HookEvent
- P0 Error: AgentError / LlmError / ToolError / MemoryError / PromptError
- P1 其他: MemoryStrategy / StepStatus / ToolChoice / ResponseFormat

明确不加的: 内部 wire-format (OpenaiChatMessage 等) /
语义已收敛 (Role/ServiceTier 等) / 使用面窄 (Permission 等)。

示例侧的 3 处 Message exhaustive match (prompt_composer /
conversation_memory_demo) 补全 `_` 通配分支,零行为变化。

验收: cargo build + clippy -D warnings + test --all-targets 全绿 (200 passed)
2026-07-05 19:47:03 +08:00

136 lines
4.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! conversation_memory_demo —— 对话记忆滑动窗口与隔离。
//!
//! 演示:
//! 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 完成");
}