独立 Memory Agent 模式
独立 Memory Agent 模式
学习目标
本章聚焦 LibreChat 的 Memory Agent 实现。你将了解:
- Memory Agent 与主对话 Agent 的完全解耦设计
set_memory/delete_memory专用工具的content_and_artifact返回格式- Token 预算管理与双错误类型设计
- 不同模型提供商的 Memory Agent 适配
前置知识
下文假设你已理解上述概念,直接聚焦 LibreChat 的具体实现。
项目实践
Memory Agent 与主 Agent 的解耦
LibreChat 的 Memory Agent 拥有完整的独立 Agent 栈:
createMemoryProcessor() → [memory, process(memory, messages)] ↓processMemory() ↓Run.create({ runId: messageId, graphConfig: { type: 'standard', llmConfig: { provider: OpenAI, model: 'gpt-4.1-mini', streaming: false }, tools: [memoryTool, deleteMemoryTool], instructions: memoryInstructions, additional_instructions: memoryStatus, toolEnd: true, }, customHandlers: { TOOL_END: BasicToolEndHandler }, returnContent: true,})关键隔离点:
| 维度 | 主 Agent | Memory Agent |
|---|---|---|
| Run 实例 | 主 Run | 独立 Run.create |
| 模型 | 用户选择 | 固定 gpt-4.1-mini(可配置) |
| 流式 | 是 | 否(disableStreaming: true) |
| 温度 | 用户配置 | 固定 0.4 |
| 递归限制 | 默认 | recursionLimit: 3 |
content_and_artifact 返回格式
Memory Agent 的工具使用 LangChain 的 content_and_artifact response format:
工具返回: [content: "Memory set for key 'name' (12 tokens)", artifact: { memory: { key: 'name', value: '用户叫张三', tokenCount: 12, type: 'update', }}]Artifact 的结构化设计支持三种类型:
| type | 含义 | 前端展示 |
|---|---|---|
update | 成功写入 | 绿色确认卡片 |
delete | 成功删除 | 灰色删除标记 |
error | 预算溢出 | 红色警告卡片 |
Token 预算双错误类型
already_exceeded: 预算已完全耗尽,不再接受任何新记忆would_exceed: 本次写入会导致超限,拒绝本次操作双错误类型的设计让前端能够区分”完全不能再写”和”这次太大了”——前者需要用户清理记忆,后者可以尝试写更短的内容。
模型适配
Bedrock:Bedrock Converse API 要求对话以用户消息开始。Memory Agent 将系统提示和记忆状态合并到第一个 HumanMessage 中:
if isBedrock: combinedInstructions = [instructions, memoryStatus].join('\n\n') processedMessages[0] = new HumanMessage(combinedInstructions + '\n\n' + originalContent) graphInstructions = undefinedGPT-5+:移除 temperature 参数,将 maxTokens 迁移到 modelKwargs。
Anthropic Thinking:当启用 thinking 模式时删除 temperature。
记忆 Artifacts 的流式通道适配
Memory Agent 可能在主回复已经开始流式输出后才完成:
if res.headersSent: GenerationJobManager.emitChunk(streamId, { event: 'attachment', data: attachment })else: res.write(`event: attachment\ndata: ${JSON.stringify(attachment)}\n\n`)这确保记忆操作结果能通过可恢复流式通道传递给前端,即使在 headersSent 之后。
问题与规避
问题 1:Memory Agent 失败阻塞主回复
规避:processMemory 被 try-catch 包裹,失败仅记录日志,不影响主回复流。调用方(AgentClient)在发送主回复后异步触发 createMemoryProcessor 返回的处理函数。
问题 2:Token 计数与实际使用不一致
规避:统一使用 o200k_base tokenizer。Memory 写入时记录 tokenCount,后续预算检查基于累计值而非重新计算。
问题 3:Bedrock 系统提示格式导致 API 错误
规避:Bedrock 分支将系统提示合并到用户消息中,设置 graphInstructions = undefined。
设计取舍
固定小模型 vs 复用主模型
Memory Agent 默认使用 gpt-4.1-mini(小型、低成本),而非复用用户选择的主模型。
| 方案 | 优势 | 代价 |
|---|---|---|
| 固定小模型 | 成本低、延迟小、输出稳定 | 需要额外配置管理 |
| 复用主模型 | 配置简单 | 成本可能很高(如用 Claude Opus 做记忆提取) |
记忆提取是相对简单的 NLU 任务,不需要主模型的推理能力。小模型更经济。
参考来源
- Generative Agents 论文 — 记忆架构的理论基础
- LangChain Tools with artifact