记忆
用于 AI Agent 的长期语义记忆,使用 adk-memory。
概述
记忆系统为 Agent 对话提供持久且可搜索的存储。与会话状态(其是短暂的)不同,记忆在会话之间持续存在,并使 Agent 能够回忆起过去交互中的相关上下文。
安装
[dependencies]
adk-memory = "0.2.0"
核心概念
MemoryEntry
包含内容、作者和时间戳的单个记忆记录:
use adk_memory::MemoryEntry;
use adk_core::Content;
use chrono::Utc;
let entry = MemoryEntry {
content: Content::new("user").with_text("I prefer dark mode"),
author: "user".to_string(),
timestamp: Utc::now(),
};
MemoryService Trait
记忆后端的核心 Trait:
#[async_trait]
pub trait MemoryService: Send + Sync {
/// 存储用户的会话记忆
async fn add_session(
&self,
app_name: &str,
user_id: &str,
session_id: &str,
entries: Vec<MemoryEntry>,
) -> Result<()>;
/// 通过查询搜索记忆
async fn search(&self, req: SearchRequest) -> Result<SearchResponse>;
}
SearchRequest
记忆搜索的查询参数:
use adk_memory::SearchRequest;
let request = SearchRequest {
query: "user preferences".to_string(),
user_id: "user-123".to_string(),
app_name: "my_app".to_string(),
};
InMemoryMemoryService
用于开发和测试的简单内存实现:
use adk_memory::{InMemoryMemoryService, MemoryService, MemoryEntry, SearchRequest};
use adk_core::Content;
use chrono::Utc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let memory = InMemoryMemoryService::new();
// 从会话中存储记忆
let entries = vec![
MemoryEntry {
content: Content::new("user").with_text("I like Rust programming"),
author: "user".to_string(),
timestamp: Utc::now(),
},
MemoryEntry {
content: Content::new("assistant").with_text("Rust is great for systems programming"),
author: "assistant".to_string(),
timestamp: Utc::now(),
},
];
memory.add_session("my_app", "user-123", "session-1", entries).await?;
// 搜索记忆
let request = SearchRequest {
query: "Rust".to_string(),
user_id: "user-123".to_string(),
app_name: "my_app".to_string(),
};
let response = memory.search(request).await?;
println!("找到 {} 条记忆", response.memories.len());
Ok(())
}
记忆隔离
记忆通过以下方式隔离:
- app_name:不同的应用程序拥有独立的记忆空间
- user_id:每个用户的记忆都是私有的
// 用户 A 的记忆
memory.add_session("app", "user-a", "sess-1", entries_a).await?;
// 用户 B 的记忆(独立)
memory.add_session("app", "user-b", "sess-1", entries_b).await?;
// 搜索仅返回用户 A 的记忆
let request = SearchRequest {
query: "topic".to_string(),
user_id: "user-a".to_string(),
app_name: "app".to_string(),
};
搜索行为
InMemoryMemoryService 使用基于词语的匹配:
- 查询被分词为词语(小写)
- 每个记忆的
content被分词 - 返回包含任何匹配词语的记忆
// 查询:"rust programming"
// 匹配包含 "rust" 或 "programming" 的记忆
自定义 Memory 后端
实现 MemoryService 以用于自定义存储(例如,向量数据库):
use adk_memory::{MemoryService, MemoryEntry, SearchRequest, SearchResponse};
use adk_core::Result;
use async_trait::async_trait;
pub struct VectorMemoryService {
// 您的向量数据库客户端
}
#[async_trait]
impl MemoryService for VectorMemoryService {
async fn add_session(
&self,
app_name: &str,
user_id: &str,
session_id: &str,
entries: Vec<MemoryEntry>,
) -> Result<()> {
// 1. 为每个条目生成嵌入
// 2. 将其与元数据一起存储在向量数据库中
Ok(())
}
async fn search(&self, req: SearchRequest) -> Result<SearchResponse> {
// 1. 为查询生成嵌入
// 2. 执行相似性搜索
// 3. 返回 Top-K 结果
Ok(SearchResponse { memories: vec![] })
}
}
与 Agent 集成
Memory 与 LlmAgentBuilder 集成:
use adk_agent::LlmAgentBuilder;
use adk_memory::InMemoryMemoryService;
use std::sync::Arc;
let memory = Arc::new(InMemoryMemoryService::new());
let agent = LlmAgentBuilder::new("assistant")
.model(model)
.instruction("You are a helpful assistant with memory.")
.memory(memory)
.build()?;
当 memory 配置后:
- 每次交互前,会搜索相关的 memories
- 匹配的 memories 会被注入到上下文中
- 每次 session 结束后,对话会作为 memories 存储
架构
┌─────────────────────────────────────────────────────────────┐
│ Agent Request │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Memory Search │
│ │
│ SearchRequest { query, user_id, app_name } │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MemoryService │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │
│ │ │ InMemory │ │ Vector DB │ │ Custom │ │ │
│ │ │ (dev/test) │ │ (Qdrant) │ │ Backend │ │ │
│ │ └─────────────┘ └─────────────┘ └────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ SearchResponse { memories: Vec<MemoryEntry> } │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Context Injection │
│ │
│ Relevant memories added to agent context │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Agent Execution │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Memory Storage │
│ │
│ Session conversation stored for future recall │
└─────────────────────────────────────────────────────────────┘
最佳实践
| 实践 | 描述 |
|---|---|
| 在生产环境中使用向量数据库 | InMemory 仅用于开发/测试 |
| 按用户范围划分 | 始终包含 user_id 以保护隐私 |
| 限制结果数量 | 限制返回的记忆数量以避免上下文溢出 |
| 清理旧记忆 | 为过期数据实现 TTL 或归档 |
| 策略性地嵌入 | 存储摘要,而非原始对话 |
与 Session 的比较
| 特性 | Session 状态 | Memory |
|---|---|---|
| 持久性 | Session 生命周期 | 永久 |
| 范围 | 单 Session | 跨 Session |
| 搜索 | 键值查找 | 语义搜索 |
| 用例 | 当前上下文 | 长期回忆 |
上一页: ← Guardrails | 下一页: Studio →