云计算百科
云计算领域专业知识百科平台

Day 026|短期记忆和长期记忆:LangGraph 的记忆怎么落地

系列:100 天系统学习 AI Agent 开发
当前阶段:LangChain 与 LangGraph 工程化
今日目标:短期记忆服务当前线程,长期记忆服务跨会话偏好、事实和经验。

Day 008 讲的是“该记什么”,今天要回答“放在哪里”

短期记忆和长期记忆的概念已经出现过一次。进入 LangGraph 后,区别变得更工程化:当前 thread 的对话和任务进度,适合随 checkpoint 保存;跨 thread 仍需复用的用户目标、偏好或已确认事实,则进入独立 store,并按用户与命名空间隔离。

我不想把“自动记忆”当卖点。记忆写错一次,可能影响之后很多次运行。系统必须能解释来源、更新、过期和删除。

Thread 与 Store 的边界

内容短期 / thread长期 / store原因
本轮用户问题 只服务当前语境
当前节点和重试次数 属于任务状态
用户确认的 100 天学习目标 可引用 跨会话稳定
“最近有点忙” 先短期 经确认且设 TTL 才考虑 可能只是临时状态
已完成 Day 18 当前状态可缓存 是,由进度事件更新 跨会话事实
工具超时 trace/checkpoint 不是用户画像
推测用户不擅长 RAG 可作为本轮假设 谨慎,需评测证据 推断可能错
API 密钥 不应进入模型记忆

学习助手的 memory store

{
"namespace": ["users", "example-user", "learning"],
"key": "progress",
"value": {
"goal": "完成 AI Agent 100 天路线",
"completed_days": [1, 2, 3],
"weak_topics": [
{
"topic": "RAG 评测",
"kind": "inference",
"evidence_ids": ["eval-case-07"],
"confidence": "low"
}
],
"preferred_stack": ["Python"]
},
"source": "user_confirmed_and_progress_events",
"updated_at": "真实写入时生成",
"expires_at": null,
"schema_version": 1
}

示例里的 completed_days 只是结构占位,不代表真实用户进度。真正数据要由完成事件更新,不能让模型把“我准备学 Day 20”误写为“已经完成 Day 20”。

写入比读取更需要规则

#mermaid-svg-y7JgMdOCbkc2JIL4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y7JgMdOCbkc2JIL4 .error-icon{fill:#552222;}#mermaid-svg-y7JgMdOCbkc2JIL4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y7JgMdOCbkc2JIL4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .marker.cross{stroke:#333333;}#mermaid-svg-y7JgMdOCbkc2JIL4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y7JgMdOCbkc2JIL4 p{margin:0;}#mermaid-svg-y7JgMdOCbkc2JIL4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster-label text{fill:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster-label span{color:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster-label span p{background-color:transparent;}#mermaid-svg-y7JgMdOCbkc2JIL4 .label text,#mermaid-svg-y7JgMdOCbkc2JIL4 span{fill:#333;color:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .node rect,#mermaid-svg-y7JgMdOCbkc2JIL4 .node circle,#mermaid-svg-y7JgMdOCbkc2JIL4 .node ellipse,#mermaid-svg-y7JgMdOCbkc2JIL4 .node polygon,#mermaid-svg-y7JgMdOCbkc2JIL4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .rough-node .label text,#mermaid-svg-y7JgMdOCbkc2JIL4 .node .label text,#mermaid-svg-y7JgMdOCbkc2JIL4 .image-shape .label,#mermaid-svg-y7JgMdOCbkc2JIL4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-y7JgMdOCbkc2JIL4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .rough-node .label,#mermaid-svg-y7JgMdOCbkc2JIL4 .node .label,#mermaid-svg-y7JgMdOCbkc2JIL4 .image-shape .label,#mermaid-svg-y7JgMdOCbkc2JIL4 .icon-shape .label{text-align:center;}#mermaid-svg-y7JgMdOCbkc2JIL4 .node.clickable{cursor:pointer;}#mermaid-svg-y7JgMdOCbkc2JIL4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .arrowheadPath{fill:#333333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y7JgMdOCbkc2JIL4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y7JgMdOCbkc2JIL4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y7JgMdOCbkc2JIL4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster text{fill:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 .cluster span{color:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-y7JgMdOCbkc2JIL4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y7JgMdOCbkc2JIL4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-y7JgMdOCbkc2JIL4 .icon-shape,#mermaid-svg-y7JgMdOCbkc2JIL4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y7JgMdOCbkc2JIL4 .icon-shape p,#mermaid-svg-y7JgMdOCbkc2JIL4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y7JgMdOCbkc2JIL4 .icon-shape .label rect,#mermaid-svg-y7JgMdOCbkc2JIL4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y7JgMdOCbkc2JIL4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y7JgMdOCbkc2JIL4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y7JgMdOCbkc2JIL4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

对话/评测/业务事件

生成候选记忆

允许保存且对未来有用?

留在 thread 或丢弃

标注事实/偏好/推断

来源校验、去重、冲突检查

需要用户确认?

等待确认

按规则写入

更新、过期、删除

我会给不同记忆类型不同策略:

  • 进度事实:只接受受信事件,允许回滚;
  • 明确偏好:用户主动表达后写入,支持随时修改;
  • 系统推断:保存证据、低权重、短 TTL;
  • 敏感信息:写入前拦截;
  • 冲突事实:保留旧记录为 superseded,不静默覆盖审计历史。

读取也要最小化

Agent 开始运行时不应把一个用户的全部长期记忆塞进 Prompt。先根据任务选 namespace,再按 key、时间和相关性取最少记录。比如回答 Day 18 的主题,只需读取学习进度和技术栈;不需要加载写作风格、历史错误全文和所有对话。

还要防止跨用户与跨租户读取。namespace 必须由已认证 user_id 构造,不允许模型在工具参数中自由指定另一个用户。

长期记忆的失败模式

  • 旧偏好覆盖新明确要求;
  • 一次随口表达被永久保存;
  • 模型推断被当作用户事实;
  • 删除 UI 只隐藏记录,底层仍会召回;
  • thread_id 当成 user_id,导致新会话找不到或串错记忆;
  • 记忆进入日志后无法按用户请求清理。
  • 记忆系统的成熟度,不在“能记住多少”,而在“知道什么不该记、什么时候应该忘”。下一篇进入 Human-in-the-loop,这些记忆会影响审批展示,但不能代替用户对本次高风险动作的明确确认。

    面试官会追问:Memory 越多,Agent 就越聪明吗?

    Memory 的代价是错误被长期放大。长期记忆写入前要回答四个问题:它是否稳定、是否得到用户授权、多久过期、用户能否查看和删除。临时任务状态不应进入长期记忆,敏感事实也不能因为模型“觉得有用”就保存。

    在 Context Engineering 里,我会把上下文分成 system 规则、当前任务 state、最近消息、按需检索的长期记忆、工具结果摘要五层,并为每层设置来源和 Token 预算。长任务优先压缩旧 observation,关键目标与未完成约束始终保留。

    作品集可以加入一条“错误记忆纠正”用例:用户修改偏好后,旧值被标记 superseded,后续检索只返回新值,审计记录仍能解释何时发生了变化。

    今日检查清单

    • thread 状态与跨 thread store 明确分开
    • 事实、偏好、推断有不同写入策略
    • 每条长期记忆可追溯、过期、修正和删除
    • namespace 由认证身份生成
    • 每次运行只检索完成任务所需的最少记忆
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Day 026|短期记忆和长期记忆:LangGraph 的记忆怎么落地
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!