Skip to main content
Sonzai Docs
教程·约 20 分钟

记忆感知对话

构建一个能记住一切的对话智能体——用户偏好、过往事件、承诺和情感上下文——跨会话持续存在。 完成本教程后,您将了解如何以编程方式注入上下文、搜索记忆以及检查智能体对用户的了解。

您将构建什么

  • → 一个流式聊天循环,智能体自动提取和存储事实
  • → 一个预注入流程,在首次对话前注入现有用户数据
  • → 一个记忆搜索 API 调用,查找智能体对特定主题的了解
  • → 一个事实时间线查询,审计智能体的记忆增长

记忆如何工作

记忆在对话中完全自动化。每次消息交换后,平台会:

  1. 运行提取管道,从对话中识别事实、偏好、承诺和事件
  2. 使用取代链对现有记忆进行去重(旧事实被淘汰而非删除)
  3. 为全文搜索和时间查询索引所有内容
  4. 在下一次对话中,在 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";

// First conversation — agent has no memory yet
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 ?? "");
}
// Platform extracts: name="Mia", allergy="peanuts", interest="hiking"

// Second conversation — agent recalls all of the above
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 ?? "");
}
// Agent knows Mia loves hiking and is allergic to peanuts — no re-intro needed.

记忆按用户隔离

从用户 A 的对话中提取的事实永远不会呈现给用户 B。 在每次聊天调用中始终传递 userId(或 user_id / UserID), 以便平台正确限定记忆范围。

2. 从现有数据预注入记忆

如果用户在您的系统中已有历史记录——CRM 档案、入职答案、过往订单—— 请在首次对话前注入这些数据,让智能体感觉已经认识他们。

// Call once during onboarding or after CRM import
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_factuser_preference shared_experienceuser_goal commitmenttime_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 等)。您可以逐节点浏览。

// Get top-level nodes
const tree = await client.agents.memory.list(AGENT_ID, {
  userId: USER_ID,
  includeContents: false,  // just node metadata, no fact text
});

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

// Drill into a node
const identityNode = await client.agents.memory.list(AGENT_ID, {
  userId: USER_ID,
  parentId: "node_identity_traits_id",
  includeContents: true,  // include fact text
});

您可以在仪表板中交互式浏览记忆树: 智能体 → 您的智能体 → 用户 → 选择用户 → 记忆 → 树浏览器

5. 查看事实时间线

时间线按时间顺序显示每个事实——何时创建、更新或被取代。 用于审计记忆增长或构建"对话历史"视图。

const timeline = await client.agents.memory.timeline(AGENT_ID, {
  userId: USER_ID,
  // Optional: narrow to a date range
  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 或合规导出,直接列出用户的所有原始事实, 无需通过树层级结构。支持按类别筛选。

// All facts for this user (paginated)
const facts = await client.agents.memory.listFacts(AGENT_ID, {
  userId: USER_ID,
  limit: 50,
  offset: 0,
  category: "user_preference",  // optional filter
});

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",  // what did the agent know at this moment?
});

console.log("Known facts at 2025-03-01:");
for (const fact of snapshot.facts) {
  console.log(`  ${fact.content}`);
}

取代机制原理:当事实被更新时, 旧记录被淘汰(而非删除),并创建一条新记录,带有 SupersedesID 指针。 时间机器通过回放此链来重建任何时间戳的状态。

下一步

  • → 阅读 记忆与上下文 参考了解完整的 7 层层级结构
  • → 设置 对话 处理多轮聊天会话的自动会话管理
  • → 探索 情绪与心情 了解智能体的情绪状态如何随记忆演变
  • → 添加 自定义状态 在记忆旁存储结构化应用数据