记忆是让 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");
关键知识点与最佳实践
✅ 核心要点
-
记忆类型选择
-
短对话 →
BufferMemory -
长对话 →
ConversationSummaryMemory -
需要记住事实 →
EntityMemory -
生产环境 → Redis 等持久化方案
-
-
记忆集成方式
-
ConversationChain:快速上手 -
LCEL 自定义链:灵活可控
-
-
记忆长度控制
// 限制 token 数 new BufferMemory({ maxTokenLimit: 2000 }); // 或限制最近 N 条消息 new BufferMemory({ k: 10 });
🛡️ 隐私与安全
-
禁止存储密码、身份证等敏感信息
-
提供显式的
clear()方法 -
遵循 GDPR 等数据保护法规
⚡ 性能优化
-
使用
batch()批量处理 -
长对话启用总结记忆
-
Redis 连接池管理
总结
记忆系统将 AI 应用从无状态的单次交互升级为有状态的连续对话。LangChain 提供了从内存缓存到数据库持久化的完整解决方案,开发者可以根据场景灵活选择:
-
快速原型 →
BufferMemory -
生产级多用户 →
RedisChatMessageHistory -
超长对话 →
ConversationSummaryMemory
掌握记忆,你的 AI 才能真正“记住”用户,提供个性化的智能服务。