LangChain 记忆系统:从对话缓存到持久化存储

0 阅读5分钟

记忆是让 AI 应用实现多轮对话和上下文感知的核心能力。没有记忆的 AI 每次对话都是全新的开始;而有记忆的 AI 能够记住用户偏好、历史交互和关键事实,真正实现连贯、个性化的智能体验。

本文将深入 LangChain 1.0 的记忆模块,从基础实现到高级模式,再到生产级的持久化方案,帮助你全面掌握记忆系统的设计与集成。

为什么需要记忆?

无记忆的 AI:每次对话都是独立的

// 第一轮
用户:我叫小明  
AI:你好小明!

// 第二轮
用户:我叫什么名字?  
AI:我不知道你的名字

有记忆的 AI:能记住上下文

// 第一轮  
用户:我叫小明  
AI:你好小明!

// 第二轮
用户:我叫什么名字?  
AI:你叫小明!

1. 记忆的核心概念

LangChain 中的记忆本质上是一个状态管理模块,负责存储、加载和更新对话过程中的上下文信息。

1.1 三种主要记忆类型

类型描述存储内容适用场景
对话记忆存储对话历史用户和 AI 的消息列表聊天机器人、客服
实体记忆存储关键事实用户提及的实体信息个性化助手
总结记忆存储对话摘要压缩后的长对话总结长对话、节省 token

2. 基础记忆实现:BufferMemory

BufferMemory 是最简单、最常用的记忆类型,它将对话历史以原始消息列表的形式存储在内存中。

import { BufferMemory } from "langchain/memory";
import { ConversationChain } from "langchain/chains";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({
  apiKey: process.env.DEEPSEEK_API_KEY,
  baseURL: "https://api.deepseek.com/v1",
  model: "deepseek-chat"
});

const memory = new BufferMemory({
  memoryKey: "chat_history",
  returnMessages: true
});

const prompt = ChatPromptTemplate.fromMessages([
  ["system", "你是一个友好的助手。对话历史:{chat_history}"],
  ["human", "{input}"]
]);

const chain = new ConversationChain({
  llm: model,
  memory,
  prompt
});

// 多轮对话
await chain.invoke({ input: "你好,我是小明" });
await chain.invoke({ input: "你还记得我叫什么吗?" }); // ✅ 记得

关键参数

  • memoryKey:记忆在提示词模板中的变量名

  • returnMessages:是否返回完整的消息对象(推荐 true

  • inputKey / outputKey:指定输入输出的键名

3. 高级记忆类型

3.1 ConversationSummaryMemory:总结式记忆

当对话过长时,原始消息列表会消耗大量 token。ConversationSummaryMemory 会定期总结对话,只保留摘要。

import { ConversationSummaryMemory } from "langchain/memory";

const summaryMemory = new ConversationSummaryMemory({
  llm: new ChatOpenAI({ temperature: 0.3 }),
  memoryKey: "summary",
  inputKey: "input",
  outputKey: "response"
});

// 每次调用后,记忆会自动更新摘要

3.2 EntityMemory:实体记忆

自动从对话中提取并存储实体信息(人名、地点、偏好等)。

import { EntityMemory } from "langchain/memory";

const entityMemory = new EntityMemory({
  llm: model,
  chatHistoryKey: "chat_history",
  entitiesKey: "entities"
});

// 记忆内容示例
{
  entities: {
    "李华": "28岁,软件工程师,有猫叫小花",
    "小花": "猫,李华的宠物"
  }
}

4. 记忆与链的深度集成

4.1 在自定义 LCEL 链中使用记忆

import { RunnableSequence } from "@langchain/core/runnables";

class MemoryAwareChain {
  private memory = new BufferMemory({ memoryKey: "history", returnMessages: true });

  buildChain() {
    return RunnableSequence.from([
      // 1. 加载记忆
      async (input) => ({
        ...input,
        chat_history: (await this.memory.loadMemoryVariables({})).history || []
      }),
      // 2. 调用模型
      async (state) => {
        const response = await this.callModel(state);
        return { ...state, response };
      },
      // 3. 保存记忆
      async (state) => {
        await this.memory.chatHistory.addUserMessage(state.user_input);
        await this.memory.chatHistory.addAIMessage(state.response);
        return state.response;
      }
    ]);
  }
}

4.2 带记忆的条件路由

结合 RunnableBranch 实现记忆感知的意图路由:

const router = RunnableBranch.from([
  [
    async (input) => {
      const history = await memory.loadMemoryVariables({});
      return detectIntent(input.question, history); // 基于历史判断
    },
    technicalChain
  ],
  // ...
]);

5. 记忆的持久化

5.1 文件系统持久化

class PersistentMemory {
  private memory: BufferMemory;
  private storagePath = "./memory_store/session.json";

  async saveToDisk() {
    const state = await this.memory.loadMemoryVariables({});
    fs.writeFileSync(this.storagePath, JSON.stringify(state));
  }

  async loadFromDisk() {
    if (fs.existsSync(this.storagePath)) {
      const data = JSON.parse(fs.readFileSync(this.storagePath, "utf8"));
      await this.restoreMemory(data);
    }
  }
}

5.2 Redis 持久化(生产推荐)

使用 RedisChatMessageHistory 为每个用户/会话创建隔离的记忆存储。

import { RedisChatMessageHistory } from "langchain/stores/message/redis";

const messageHistory = new RedisChatMessageHistory({
  sessionId: "user_123", // 唯一标识
  config: { url: "redis://localhost:6379" }
});

const memory = new BufferMemory({
  chatHistory: messageHistory,
  returnMessages: true
});

优势

  • 会话隔离,支持海量用户

  • 持久化存储,重启不丢失

  • 支持分布式部署

6. 实战:带记忆的智能客服

完整示例:意图识别 + 上下文感知 + 对话摘要 + Redis 持久化。

class CustomerServiceWithMemory {
  private memory: BufferMemory;
  private model: ChatOpenAI;

  constructor(sessionId: string) {
    const history = new RedisChatMessageHistory({ sessionId });
    this.memory = new BufferMemory({
      chatHistory: history,
      memoryKey: "customer_history",
      returnMessages: true
    });
    this.model = new ChatOpenAI({ /* 配置 */ });
  }

  buildChain() {
    return RunnableSequence.from([
      async (input) => {
        const history = await this.memory.loadMemoryVariables({});
        const context = await this.analyzeContext(history.customer_history);
        return { ...input, context };
      },
      async (state) => {
        const response = await this.generateResponse(state);
        return { ...state, response };
      },
      async (state) => {
        await this.memory.chatHistory.addUserMessage(state.query);
        await this.memory.chatHistory.addAIMessage(state.response);
        return state.response;
      }
    ]);
  }

  private async analyzeContext(history: BaseMessage[]) {
    // 使用模型提取客户称呼、问题类型、情绪等
  }
}

// 不同客户独立记忆
const serviceA = new CustomerServiceWithMemory("user_001");
const serviceB = new CustomerServiceWithMemory("user_002");

关键知识点与最佳实践

✅ 核心要点

  1. 记忆类型选择

    1. 短对话 → BufferMemory

    2. 长对话 → ConversationSummaryMemory

    3. 需要记住事实 → EntityMemory

    4. 生产环境 → Redis 等持久化方案

  2. 记忆集成方式

    1. ConversationChain:快速上手

    2. LCEL 自定义链:灵活可控

  3. 记忆长度控制

      // 限制 token 数
      new BufferMemory({ maxTokenLimit: 2000 });
      // 或限制最近 N 条消息
      new BufferMemory({ k: 10 });
    

🛡️ 隐私与安全

  • 禁止存储密码、身份证等敏感信息

  • 提供显式的 clear() 方法

  • 遵循 GDPR 等数据保护法规

⚡ 性能优化

  • 使用 batch() 批量处理

  • 长对话启用总结记忆

  • Redis 连接池管理

总结

记忆系统将 AI 应用从无状态的单次交互升级为有状态的连续对话。LangChain 提供了从内存缓存到数据库持久化的完整解决方案,开发者可以根据场景灵活选择:

  • 快速原型 → BufferMemory

  • 生产级多用户 → RedisChatMessageHistory

  • 超长对话 → ConversationSummaryMemory

掌握记忆,你的 AI 才能真正“记住”用户,提供个性化的智能服务。