LangChain 学习笔记 05:聊天记录很多,不等于模型真的有记忆

📅 2026/7/31 8:55:27 👁️ 阅读次数 📝 编程学习
LangChain 学习笔记 05:聊天记录很多,不等于模型真的有记忆

用户说“还是按上次那个地址寄”,系统怎样知道“上次那个地址”指什么?这是聊天应用开始变得像助手的时刻,也是状态管理真正变麻烦的时刻。

第 6 章集中讨论 Memory。读这一章前,我容易把记忆理解成“把历史对话都塞回 Prompt”;读完以后,最大的变化是开始区分原始记录、当前上下文和长期事实。

版本说明:LangChain 的记忆与 Agent 状态接口已经历多次演进。这里讨论的是记忆设计问题,不建议直接照搬书中的旧类名。

模型本身不会记住上一轮

一次模型调用通常只看到本次请求提供的内容。所谓“记得”,其实是应用在调用前读取状态、把相关信息放进上下文,并在调用后保存新状态。

可以把它拆成三类:

类型 示例 保存方式
会话历史 用户和助手的原始消息 按会话持久化
工作记忆 本轮回答需要的最近消息或摘要 动态选择后放入上下文
长期记忆 用户偏好、地址、任务进度 结构化存储并按需读取

三者混成一个无限增长的消息列表,会同时带来成本、噪声、隐私和一致性问题。

常见策略各自牺牲了什么

完整缓冲保留全部消息,最容易实现,也最忠实。但对话越长,token 成本越高,早期关键信息还可能被大量闲聊淹没。

窗口记忆只保留最近若干轮,成本可控,却可能把前面已经确认的重要约束丢掉。

摘要记忆把旧对话压缩成摘要。它节省上下文,但摘要也是模型生成的,可能遗漏数字、否定条件和用户态度。摘要最好保留版本,并允许回查原始消息。

实体或结构化记忆抽取姓名、偏好、地址和任务状态,查询效率高,但需要处理更新、冲突和删除。例如用户说“以后不要寄到公司”,系统不能只新增一条偏好,而要正确替换旧状态。

一个预约助手该怎样记

假设用户先说“周五下午帮我约牙医”,几轮后又说“改到下周一上午”。

如果只保存聊天文本,模型每次都要从长记录里重新推断最终时间。更稳妥的做法是同时维护结构化状态:

{"service": "牙医","date": "下周一","period": "上午","confirmed": false
}

模型负责从自然语言中提取候选修改,程序负责日期解析、字段校验和最终写入。真正提交预约前,还要把明确日期和时间展示给用户确认。

这个例子也说明:Memory 不只是“聊天体验功能”,它已经接近业务状态管理。

记忆最难的是冲突,不是存储

用户可能先说喜欢简洁回答,后来又要求某个话题详细解释;资料库可能保存旧公司名称,当前会话里用户又给出新名称。

因此长期记忆至少需要来源、更新时间、作用范围和可信级别。遇到冲突时,可以按明确规则选择,或者向用户询问,而不是让模型默默猜一个。

敏感信息还要考虑授权、加密、保留期限和删除能力。能保存不代表应该保存,能从历史推断出来也不代表可以长期固化。

这章给我的启发

记忆模块真正要解决的,不是“怎样装下更多聊天记录”,而是“此刻哪些信息值得进入上下文”。

原始消息负责追溯,摘要帮助压缩,结构化状态支撑业务,长期记忆提供跨会话连续性。把这些职责分开,系统才不会一边声称记得用户,一边又把过期信息当成事实。