前端开发AI Agent之Memory理论篇

我是使用mastra开发,Mastra 是一个开源的 TypeScript AI 代理框架,旨在帮助开发者快速构建 AI 应用。其中的 Memory(内存) 部分是 Mastra 的核心功能之一,用于管理代理的上下文和会话历史,从而实现更自然、连贯的交互体验。以下是 Mastra 中 Memory 部分的系统性介绍


1. Memory 概述

在 Mastra 中,Memory 是代理管理上下文的核心机制,负责存储和检索会话历史、用户相关信息以及语义相关的上下文。Memory 的设计目标是让代理能够像人类一样"记住"之前的交互内容,从而提供更智能的响应。

Memory 的上下文管理基于上下文窗口(Context Window) ,即语言模型在任意时刻可见的总信息。Mastra 将上下文分为以下三个主要部分:

  • 系统指令和用户信息(Working Memory) :存储代理的系统提示和用户的关键信息(例如用户名、偏好等)。
  • 近期消息(Message History) :保存最近的会话消息,提供即时的对话上下文。
  • 语义召回(Semantic Recall) :检索与当前查询语义相关的较旧消息,增强上下文的深度。

此外,Mastra 提供 Memory Processors 来优化上下文管理,例如修剪过长的上下文或移除无关信息。

Memory 的核心优势在于其灵活性和可扩展性,支持多种存储后端(如 LibSQL、PostgreSQL、Upstash)和嵌入模型(如 FastEmbed),适用于从原型开发到生产环境的各种场景。


2. Memory 的核心组件

2.1 Memory 类

Memory 类是 Mastra 中管理会话历史和上下文的核心组件。它支持以下功能:

  • 会话历史存储 :将消息存储在线程中,按 resourceId(用户或实体 ID)和 threadId(会话线程 ID)组织。
  • 语义搜索:通过向量数据库和嵌入模型支持语义召回,检索与查询相关的历史消息。
  • 工作内存(Working Memory) :存储用户关键信息(如姓名、偏好),并支持跨会话持久化。
  • 线程管理:支持创建、更新和检索会话线程,方便管理多个对话。

默认配置下,Memory 使用 LibSQL 作为存储后端,FastEmbed 提供嵌入支持,开发者无需额外配置即可快速上手。

2.2 存储后端

Mastra 的 Memory 系统支持灵活的存储后端,开发者可以根据需求选择合适的数据库:

  • LibSQL:默认存储选项,适合本地开发和轻量级应用。
  • PostgreSQL(pgvector) :适合需要高性能和扩展性的生产环境。
  • Upstash:基于 Redis 的云存储,适合低延迟的分布式应用。
  • 其他支持的向量数据库包括 Pinecone、Qdrant、Chroma 等,用于语义搜索和 RAG(检索增强生成)。

存储后端通过统一的接口操作,开发者可以在开发和生产环境中无缝切换,而无需更改代码逻辑。

2.3 上下文管理

Mastra 的 Memory 系统通过以下方式管理上下文:

  • 消息历史:默认存储最近 40 条消息(可配置),确保代理能够快速访问近期对话。
  • 语义召回:通过嵌入模型和向量搜索,检索与当前查询语义相似的历史消息,增强上下文相关性。
  • 工作内存 :以 Markdown 或 XML 格式存储用户关键信息,支持通过文本流标签或工具调用更新。

2.4 Memory API

Mastra 提供了一套 Memory API,用于管理和查询会话线程及消息历史。例如:

  • 获取线程client.getMemoryThreads({ resourceId, agentId }) 获取指定资源的所有线程。
  • 创建线程client.createMemoryThread({ title, metadata, resourceId, agentId }) 创建新会话线程。
  • 更新线程thread.update({ title, metadata, resourceId }) 修改线程元数据。

这些 API 简化了开发者对会话历史的直接操作,适合需要自定义内存管理的场景。


3. Memory 的配置

Memory 的配置通过 Memory 类的 options 对象实现,允许开发者自定义内存行为。以下是主要配置项及其作用:

3.1 lastMessages

  • 作用:控制代理在上下文窗口中包含的近期消息数量。
  • 默认值:40 条。
  • 示例
arduino 复制代码
const memory = new Memory({
  options: { lastMessages: 20 } // 仅包含最近 20 条消息
});
  • 注意 :设置为 false 可禁用近期消息限制,包含所有消息(可能增加计算成本)。

3.2 semanticRecall

  • 作用:配置语义召回,检索与当前查询语义相关的历史消息。
  • 子选项
    • topK:返回的最相关消息数量(默认:3)。
    • messageRange:围绕每个相关消息的上下文范围(例如,前 2 条和后 1 条消息)。
  • 示例
yaml 复制代码
const memory = new Memory({
  options: {
    semanticRecall: {
      topK: 3,
      messageRange: { before: 2, after: 1 }
    }
  }
});
  • 注意 :可设置为 false 禁用语义召回,或设置为 true 使用默认配置。

3.3 workingMemory

  • 作用:启用工作内存,存储用户关键信息,支持跨会话持久化。
  • 子选项
    • enabled:是否启用工作内存(默认:false)。
    • use:更新模式,text-stream(通过 XML 标签)或 tool-call(通过工具调用)。
    • template:定义工作内存的结构(Markdown 格式)。
  • 示例
yaml 复制代码
const memory = new Memory({
  options: {
    workingMemory: {
      enabled: true,
      use: 'text-stream', // 或者tool-call
      template: `# User\n- First Name: \n- Last Name: `
    }
  }
});
  • 注意tool-call 模式适合与 toDataStream() 配合使用,避免文本流冲突。这种模式提供了对内存更新的更明确控制,当与那些更擅长使用工具而不是管理文本标签的代理一起工作时,可能会更受欢迎

3.4 threads

  • 作用:配置线程创建行为,例如是否自动生成线程标题。
  • 子选项
    • generateTitle:基于用户首条消息的 LLM 摘要生成线程标题。
  • 示例
yaml 复制代码
const memory = new Memory({
  options: {
    threads: { generateTitle: true }
  }
});

3.5 存储和向量配置

  • 存储后端 :通过 storage 参数指定,例如 LibSQLStoreUpstashStore
  • 向量数据库 :通过 vector 参数指定,例如 LibSQLVectorPineconeVector
  • 示例
css 复制代码
const memory = new Memory({
  storage: new LibSQLStore({ url: "file:memory.db" }),
  vector: new LibSQLVector({ url: "file:vector.db" })
});

开发者可以通过这些配置灵活调整 Memory 的行为,适应不同的应用场景。


4. Memory 的使用方式

4.1 基本设置

要为代理启用 Memory,只需在创建 Agent 时传入 Memory 实例:

javascript 复制代码
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";
import { openai } from "@ai-sdk/openai";

const memory = new Memory();
const agent = new Agent({
  name: "MyMemoryAgent",
  instructions: "You are a helpful assistant with memory.",
  model: openai("gpt-4o"),
  memory
});

4.2 会话交互

在调用代理的 stream()generate() 方法时,必须提供 resourceIdthreadId 以启用 Memory:

php 复制代码
await agent.stream("Remember my favorite color is blue.", {
  resourceId: "user_alice",
  threadId: "preferences_thread"
});

const response = await agent.stream("What's my favorite color?", {
  resourceId: "user_alice",
  threadId: "preferences_thread"
}); // 代理将回忆并返回 "blue"

4.3 工作内存更新

工作内存可以通过文本流标签或工具调用自动更新。例如,在文本流模式下:

javascript 复制代码
import { maskStreamTags } from "@mastra/core/utils";

const response = await agent.stream("My name is Jane", {
  threadId: randomUUID(),
  resourceId: "SOME_USER_ID"
});

for await (const chunk of maskStreamTags(response.textStream, "working_memory")) {
  process.stdout.write(chunk); // 隐藏工作内存标签,仅输出用户可见内容
}

4.4 动态内存配置

开发者可以在每次请求中覆盖全局内存配置:

php 复制代码
await agent.stream("What's the weather today?", {
  resourceId: "user_bob",
  threadId: "weather_thread",
  memoryOptions: {
    lastMessages: 10,
    semanticRecall: { topK: 2, messageRange: 5 }
  }
});

4.5 开发环境支持

Mastra 提供内置的 开发游乐场(Playground) ,允许开发者在本地测试代理的 Memory 功能。运行 mastra dev 后,可以通过 UI 查看代理的状态、内存内容和会话历史,简化调试过程。


5. 实际应用场景

Mastra 的 Memory 系统适用于多种 AI 应用场景,以下是一些典型用例:

5.1 客户支持机器人

  • 需求:机器人需要记住用户的偏好、问题历史和上下文,提供连贯的对话。
  • 实现 :使用 resourceId 标识用户,threadId 区分不同支持会话,启用工作内存存储用户关键信息(如姓名、问题类型)。
  • 示例 :用户报告问题后,代理可召回之前的对话,快速提供解决方案。

5.2 个性化推荐

  • 需求:代理根据用户的历史偏好推荐内容或产品。
  • 实现:通过工作内存存储用户的兴趣标签,结合语义召回查找相关历史交互。
  • 示例 :用户提到喜欢蓝色,代理在后续推荐中优先展示蓝色产品。

5.3 知识库助手

  • 需求:代理需要结合内部文档和用户查询历史回答复杂问题。
  • 实现:结合 RAG 和 Memory,代理通过语义召回检索相关历史消息,并从知识库中提取上下文。
  • 示例 :学术研究助手根据用户之前的提问,结合论文内容提供精准答案。

5.4 烹饪助手

  • 需求:代理根据用户提供的食材和历史偏好推荐菜谱。
  • 实现:使用 Memory 存储用户提供的食材列表和工作内存记录饮食偏好。
  • 示例 :用户提到现有食材(面条、番茄),代理推荐意面菜谱,并记住用户偏好低盐口味。

6. 高级功能与扩展

6.1 语义召回与 RAG 集成

Memory 的语义召回功能与 Mastra 的 RAG 系统无缝集成。开发者可以通过向量数据库存储文档嵌入,并在查询时结合会话历史和外部知识库生成响应。例如:

arduino 复制代码
const memory = new Memory({
  vector: new PgVector(process.env.POSTGRES_CONNECTION_STRING),
  options: { semanticRecall: { topK: 5 } }
});

6.2 多代理协作

在多代理工作流中,Memory 支持共享会话历史,确保不同代理能够访问相同的上下文。例如,一个支持代理可以将用户问题记录在共享线程中,另一个分析代理随后处理。

6.3 可观测性

Mastra 的 Memory 系统与 OpenTelemetry 集成,支持跟踪消息存储和检索的操作。开发者可以通过 observability 工具(如 SigNoz、Langfuse)监控内存性能和上下文使用情况。

6.4 生产化支持

Memory 支持生产环境的高可用性配置,例如使用 PostgreSQL 或 Upstash 作为存储后端,并通过分布式向量数据库实现低延迟的语义搜索。


7. 注意事项与最佳实践

  • 必须提供 ID :代理调用时必须指定 resourceIdthreadId,否则 Memory 功能不会生效。
  • 避免重复历史 :不要在代理调用中手动发送完整会话历史,Mastra 会自动管理历史注入,避免重复。
  • 优化上下文 :通过调整 lastMessagessemanticRecall 参数,平衡上下文丰富度和性能开销。
  • 数据迁移 :在切换存储后端(例如从 LibSQL 到 PostgreSQL)时,需要手动迁移数据。
  • 调试支持 :利用 Mastra 的 Playground 调试 Memory 配置,检查消息存储和召回效果。

8.Memory Processors

在 Mastra 的 Memory 系统中, 是用于优化和管理上下文的核心组件,负责处理会话历史、语义召回和工作内存,以确保代理能够高效、准确地利用上下文,同时避免上下文窗口过载或无关信息干扰。以下是对 Memory Processors 的系统性介绍,涵盖其定义、功能、实现机制、使用方式、配置选项以及实际应用场景。


1. Memory Processors 概述

Memory Processors 是 Mastra Memory 系统中的一组处理逻辑,设计目标是动态优化代理的上下文管理。它们通过修剪、过滤、增强或重新组织上下文数据,确保语言模型接收到最相关、最精简的输入,从而提升性能和响应质量。

Memory Processors 的主要作用包括:

  • 上下文修剪:移除过长或无关的历史消息,保持上下文在模型的窗口限制内。
  • 语义增强:通过语义召回,添加与当前查询高度相关的历史消息。
  • 工作内存管理:动态更新和格式化用户关键信息,确保跨会话的持久性和一致性。
  • 性能优化:减少不必要的计算开销,提升响应速度和内存效率。

Memory Processors 与 Mastra 的 Memory 类紧密协作,通常在代理处理用户请求时自动触发。开发者可以通过配置选项或自定义处理器扩展其功能,适应不同的应用场景。


2. Memory Processors 的工作流程

Memory Processors 在代理处理用户请求时按照以下步骤执行:

  1. 输入解析
    • 处理器接收用户查询、当前线程的 threadIdresourceId
    • 提取请求中的内存配置(如 memoryOptions)。
  1. 消息检索
    • 从数据库中加载指定线程的近期消息(受 lastMessages 限制)。
    • 若启用语义召回,执行向量搜索,检索相关历史消息。
  1. 上下文优化
    • 修剪过长的消息,确保总标记数在上下文窗口内。
    • 合并工作内存和历史消息,应用优先级排序。
  1. 工作内存更新
    • 解析代理响应中的标签或工具调用,更新工作内存。
    • 将更新后的工作内存存储到数据库。
  1. 输出生成
    • 处理器将优化后的上下文注入语言模型的提示中。
    • 若使用流式响应,处理器确保工作内存标签对用户不可见。

整个流程通过异步操作实现,确保低延迟和高吞吐量。


9. 总结

Mastra 的 Memory 系统通过灵活的存储、语义召回和工作内存功能,为 AI 代理提供了强大的上下文管理能力。无论是简单的会话历史记录,还是复杂的语义搜索和 RAG 集成,Memory 都能满足从原型到生产的需求。开发者可以通过简单的配置快速上手,并利用高级功能实现复杂的应用场景。

10. 参考

  1. Memory API
  2. Memory文档
相关推荐
GISer_Jing2 小时前
前端性能指标及优化策略——从加载、渲染和交互阶段分别解读详解并以Webpack+Vue项目为例进行解读
前端·javascript·vue
不知几秋2 小时前
数字取证-内存取证(volatility)
java·linux·前端
水银嘻嘻3 小时前
08 web 自动化之 PO 设计模式详解
前端·自动化
Zero1017135 小时前
【详解pnpm、npm、yarn区别】
前端·react.js·前端框架
&白帝&5 小时前
vue右键显示菜单
前端·javascript·vue.js
Wannaer5 小时前
从 Vue3 回望 Vue2:事件总线的前世今生
前端·javascript·vue.js
羽球知道6 小时前
在Spark搭建YARN
前端·javascript·ajax
光影少年6 小时前
vue中,created和mounted两个钩子之间调用时差值受什么影响
前端·javascript·vue.js
青苔猿猿6 小时前
node版本.node版本、npm版本和pnpm版本对应
前端·npm·node.js·pnpm
一只码代码的章鱼7 小时前
Spring的 @Validate注解详细分析
前端·spring boot·算法