记忆感知对话
构建一个能记住一切的对话智能体——用户偏好、过往事件、承诺和情感上下文——跨会话持续存在。完成本教程后,您将了解如何以编程方式注入上下文、搜索记忆以及检查智能体对用户的了解。
你将构建什么
- 一个智能体自动提取和存储事实的流式聊天循环
- 一个在首次对话前注入现有用户数据的预填流程
- 一个查找智能体对特定话题了解情况的记忆搜索 API 调用
- 一个审计智能体记忆增长情况的事实时间线查询
记忆的工作原理
聊天时记忆完全自动化。每次消息交换后,平台会:
- 运行提取流水线,识别对话中的事实、偏好、承诺和事件
- 使用替代链与现有记忆去重(旧事实被退役,而不是删除)
- 为全文搜索和时序查询建立索引
- 在下一次对话时,自动在 token 预算内获取最相关的记忆
你永远不需要管理向量存储、编写提取提示词或实现检索逻辑。平台处理所有这些。
1. 聊天并让记忆积累
开始聊天。记忆提取在响应流式完成后自动发生。你这边无需任何特殊处理。
import { Sonzai } from "@sonzai-labs/agents";
const client = new Sonzai({ apiKey: process.env.SONZAI_API_KEY! });
const AGENT_ID = "agent_abc";
const USER_ID = "user_123";
// 第一次对话——智能体尚无记忆
for await (const event of client.agents.chatStream(AGENT_ID, {
userId: USER_ID,
messages: [
{ role: "user", content: "My name is Mia. I'm allergic to peanuts and I love hiking." },
],
})) {
process.stdout.write(event.choices?.[0]?.delta?.content ?? "");
}
// 平台提取:name="Mia",allergy="peanuts",interest="hiking"
// 第二次对话——智能体回忆起上述所有内容
for await (const event of client.agents.chatStream(AGENT_ID, {
userId: USER_ID,
messages: [
{ role: "user", content: "What snacks should I bring on my next hike?" },
],
})) {
process.stdout.write(event.choices?.[0]?.delta?.content ?? "");
}
// 智能体知道 Mia 热爱徒步且对花生过敏——无需重新介绍。记忆是每用户独立的
从用户 A 对话中提取的事实永远不会暴露给用户 B。每次聊天调用都要传入 userId(或 user_id / UserID),让平台正确地限定记忆范围。
2. 从现有数据预填记忆
如果用户在你的系统中有历史记录——CRM 档案、入职答案、历史订单——在第一次对话前注入它,让智能体感觉已经认识他们。
// 在入职期间或 CRM 导入后调用一次
await client.agents.memory.seed(AGENT_ID, {
userId: USER_ID,
memories: [
{
content: "Mia is a 32-year-old UX designer based in Berlin.",
type: "user_fact",
},
{
content: "Mia subscribed to the Pro plan on 2024-11-03.",
type: "shared_experience",
occurred_at: "2024-11-03T00:00:00Z",
},
{
content: "Mia prefers email over SMS for notifications.",
type: "user_preference",
},
{
content: "Mia mentioned she wants to get into trail running.",
type: "user_goal",
},
],
});支持的记忆类型:user_fact、user_preference、shared_experience、user_goal、commitment、time_sensitive。
3. 搜索智能体知道的内容
直接查询记忆存储,查找智能体对某个话题提取到的内容。适用于构建面向用户的"我的智能体记得什么?"功能,或用于调试。
const results = await client.agents.memory.search(AGENT_ID, {
query: "diet restrictions food allergies",
userId: USER_ID,
limit: 10,
});
for (const fact of results.facts) {
console.log(`[${fact.type}] ${fact.content} (confidence: ${fact.confidence})`);
}
// [user_fact] Mia is allergic to peanuts (confidence: 0.97)
// [user_preference] Mia prefers nut-free snacks on hikes (confidence: 0.85)4. 浏览记忆树
记忆树是一个 7 级层级结构,按类别组织事实(/identity/traits、/preferences/interests、/episodes/sessions 等)。你可以逐节点遍历它。
// 获取顶层节点
const tree = await client.agents.memory.list(AGENT_ID, {
userId: USER_ID,
includeContents: false, // 只获取节点元数据,不获取事实文本
});
for (const node of tree.nodes) {
console.log(`${node.path} — ${node.fact_count} facts`);
}
// /identity/traits — 3 facts
// /preferences/interests — 5 facts
// /episodes/sessions — 12 facts
// /temporal — 2 facts
// 深入某个节点
const identityNode = await client.agents.memory.list(AGENT_ID, {
userId: USER_ID,
parentId: "node_identity_traits_id",
includeContents: true, // 包含事实文本
});你可以在仪表盘的智能体 → 你的智能体 → 用户 → 选择用户 → 记忆 → 树状探索器中交互式地探索记忆树。
5. 检查事实时间线
时间线按时间顺序展示每个事实——创建、更新或被替代的时间。用它来审计记忆增长,或构建"对话历史"视图。
const timeline = await client.agents.memory.timeline(AGENT_ID, {
userId: USER_ID,
// 可选:缩小日期范围
start: "2025-01-01T00:00:00Z",
end: "2025-12-31T23:59:59Z",
});
for (const entry of timeline.entries) {
console.log(
`${new Date(entry.created_at).toLocaleDateString()} — ${entry.type}: ${entry.content}`
);
}6. 直接列出提取的事实
对于管理 UI 或合规导出,直接列出用户的所有原始事实,无需经过树状层级。支持按 factType(TS)/ fact_type(Python/Go)过滤。
// 该用户的所有事实(分页)
const facts = await client.agents.memory.listFacts(AGENT_ID, {
userId: USER_ID,
limit: 50,
offset: 0,
factType: "user_preference", // 可选过滤器
});
console.log(`Total facts: ${facts.total}`);
for (const f of facts.facts) {
console.log(` ${f.content}`);
}GDPR / 被遗忘权
要删除某用户的所有记忆,调用 client.agents.memory.reset(agentId, { userId })。这会创建墓碑记录以防止已删除的事实被重新浮现;数据会立即从检索中移除。
7. 回溯历史(时光机)
时光机让你查看智能体在过去任意时间点对用户的了解——适用于调试智能体为何说了某些话,或审计其理解如何演化。
const snapshot = await client.agents.getTimeMachine(AGENT_ID, {
userId: USER_ID,
at: "2025-03-01T00:00:00Z", // 智能体在这个时刻知道什么?
});
console.log("Known facts at 2025-03-01:");
for (const fact of snapshot.facts) {
console.log(` ${fact.content}`);
}替代机制的工作原理
当事实更新时,旧记录被退役(而不是删除),并创建一个带有 SupersedesID 指针的新记录。时光机重放这条链以重建任意时间戳时的状态。