第4章我们给Agent加上了工具调用能力。它现在能查数据库、查天气、计算数字了。
但你用着用着会发现一个尴尬的问题:这Agent怎么聊着聊着就忘了事呢?
举个例子。你跟Agent聊:
你:我叫小明,在济南工作,是个程序员。
Agent:好的小明,济南的程序员你好!
你:今天心情不太好。
Agent:怎么了?
你:你还记得我是干什么工作的吗?
Agent:抱歉,我不记得了。
看到没?才聊了3句,Agent就把你的信息忘了。
这章我们就来解决这个"Agent失忆"的老大难。
5.1 为什么Agent会"失忆"?
你可能以为这是模型的问题。其实不是。 这是设计上的限制。
上下文窗口:Agent的"工作台"就这么大
每个大语言模型都有一个上下文窗口(Context Window),你可以把它理解成Agent的"工作台"。
#mermaid-svg-H1NQT00ZtNaWXVeP{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-H1NQT00ZtNaWXVeP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-H1NQT00ZtNaWXVeP .error-icon{fill:#552222;}#mermaid-svg-H1NQT00ZtNaWXVeP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H1NQT00ZtNaWXVeP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H1NQT00ZtNaWXVeP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H1NQT00ZtNaWXVeP .marker.cross{stroke:#333333;}#mermaid-svg-H1NQT00ZtNaWXVeP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H1NQT00ZtNaWXVeP p{margin:0;}#mermaid-svg-H1NQT00ZtNaWXVeP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster-label text{fill:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster-label span{color:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster-label span p{background-color:transparent;}#mermaid-svg-H1NQT00ZtNaWXVeP .label text,#mermaid-svg-H1NQT00ZtNaWXVeP span{fill:#333;color:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP .node rect,#mermaid-svg-H1NQT00ZtNaWXVeP .node circle,#mermaid-svg-H1NQT00ZtNaWXVeP .node ellipse,#mermaid-svg-H1NQT00ZtNaWXVeP .node polygon,#mermaid-svg-H1NQT00ZtNaWXVeP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-H1NQT00ZtNaWXVeP .rough-node .label text,#mermaid-svg-H1NQT00ZtNaWXVeP .node .label text,#mermaid-svg-H1NQT00ZtNaWXVeP .image-shape .label,#mermaid-svg-H1NQT00ZtNaWXVeP .icon-shape .label{text-anchor:middle;}#mermaid-svg-H1NQT00ZtNaWXVeP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-H1NQT00ZtNaWXVeP .rough-node .label,#mermaid-svg-H1NQT00ZtNaWXVeP .node .label,#mermaid-svg-H1NQT00ZtNaWXVeP .image-shape .label,#mermaid-svg-H1NQT00ZtNaWXVeP .icon-shape .label{text-align:center;}#mermaid-svg-H1NQT00ZtNaWXVeP .node.clickable{cursor:pointer;}#mermaid-svg-H1NQT00ZtNaWXVeP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-H1NQT00ZtNaWXVeP .arrowheadPath{fill:#333333;}#mermaid-svg-H1NQT00ZtNaWXVeP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-H1NQT00ZtNaWXVeP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-H1NQT00ZtNaWXVeP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H1NQT00ZtNaWXVeP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-H1NQT00ZtNaWXVeP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H1NQT00ZtNaWXVeP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster text{fill:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP .cluster span{color:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP 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-H1NQT00ZtNaWXVeP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-H1NQT00ZtNaWXVeP rect.text{fill:none;stroke-width:0;}#mermaid-svg-H1NQT00ZtNaWXVeP .icon-shape,#mermaid-svg-H1NQT00ZtNaWXVeP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H1NQT00ZtNaWXVeP .icon-shape p,#mermaid-svg-H1NQT00ZtNaWXVeP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-H1NQT00ZtNaWXVeP .icon-shape .label rect,#mermaid-svg-H1NQT00ZtNaWXVeP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H1NQT00ZtNaWXVeP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-H1NQT00ZtNaWXVeP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-H1NQT00ZtNaWXVeP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent的工作台
(上下文窗口)
📝 系统提示词
3k tokens
💬 对话历史
每轮约500 tokens
🛠️ 工具定义
每个工具约300 tokens
📚 RAG检索内容
每次约2000 tokens
🤔 模型生成的回复
约500 tokens
❌ 没空间了
超出的内容会被截断
我给你算一笔账。GPT-4.1的上下文窗口是128k tokens(约等于10万字)。听起来挺多?来看看Agent一次"完整调用"会消耗多少:
| 占用项 | 典型大小 | 备注 |
|---|---|---|
| 系统提示词 | 2000 tokens | Agent的"人设"和工具说明 |
| 工具定义 | 3000 tokens | 10个工具约3k |
| 对话历史 | 每轮500 tokens | 聊20轮就是1万 |
| RAG检索内容 | 2000 tokens/次 | 每次问答都要塞进相关文档 |
| 模型回复 | 1000 tokens | 一次约500-1000字 |
算一下:20轮对话 + 5次工具调用 = 2k+3k+1万+1万+5k = 3万token。
看起来离128k远着呢。但问题是------Token会按次收费的! 一次Agent调用花的钱是简单聊天的几十倍。
更关键的是,对话越长,单次调用的成本越高,速度越慢。你每问一句话,模型都要把整段历史重新"读一遍"。
模型会"忘记中间":Lost in the Middle
还有个更反直觉的问题:模型对超长上下文的"中间部分"会视而不见。
研究者做过实验:把一段很长的文本喂给模型,把关键信息藏在不同位置,问模型"刚才第X段说了什么"?
结果:
#mermaid-svg-NpeRfLvOSD2vyMkb{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-NpeRfLvOSD2vyMkb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NpeRfLvOSD2vyMkb .error-icon{fill:#552222;}#mermaid-svg-NpeRfLvOSD2vyMkb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NpeRfLvOSD2vyMkb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NpeRfLvOSD2vyMkb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NpeRfLvOSD2vyMkb .marker.cross{stroke:#333333;}#mermaid-svg-NpeRfLvOSD2vyMkb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NpeRfLvOSD2vyMkb p{margin:0;}#mermaid-svg-NpeRfLvOSD2vyMkb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster-label text{fill:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster-label span{color:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster-label span p{background-color:transparent;}#mermaid-svg-NpeRfLvOSD2vyMkb .label text,#mermaid-svg-NpeRfLvOSD2vyMkb span{fill:#333;color:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb .node rect,#mermaid-svg-NpeRfLvOSD2vyMkb .node circle,#mermaid-svg-NpeRfLvOSD2vyMkb .node ellipse,#mermaid-svg-NpeRfLvOSD2vyMkb .node polygon,#mermaid-svg-NpeRfLvOSD2vyMkb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NpeRfLvOSD2vyMkb .rough-node .label text,#mermaid-svg-NpeRfLvOSD2vyMkb .node .label text,#mermaid-svg-NpeRfLvOSD2vyMkb .image-shape .label,#mermaid-svg-NpeRfLvOSD2vyMkb .icon-shape .label{text-anchor:middle;}#mermaid-svg-NpeRfLvOSD2vyMkb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NpeRfLvOSD2vyMkb .rough-node .label,#mermaid-svg-NpeRfLvOSD2vyMkb .node .label,#mermaid-svg-NpeRfLvOSD2vyMkb .image-shape .label,#mermaid-svg-NpeRfLvOSD2vyMkb .icon-shape .label{text-align:center;}#mermaid-svg-NpeRfLvOSD2vyMkb .node.clickable{cursor:pointer;}#mermaid-svg-NpeRfLvOSD2vyMkb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NpeRfLvOSD2vyMkb .arrowheadPath{fill:#333333;}#mermaid-svg-NpeRfLvOSD2vyMkb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NpeRfLvOSD2vyMkb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NpeRfLvOSD2vyMkb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NpeRfLvOSD2vyMkb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NpeRfLvOSD2vyMkb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NpeRfLvOSD2vyMkb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster text{fill:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb .cluster span{color:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb 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-NpeRfLvOSD2vyMkb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NpeRfLvOSD2vyMkb rect.text{fill:none;stroke-width:0;}#mermaid-svg-NpeRfLvOSD2vyMkb .icon-shape,#mermaid-svg-NpeRfLvOSD2vyMkb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NpeRfLvOSD2vyMkb .icon-shape p,#mermaid-svg-NpeRfLvOSD2vyMkb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NpeRfLvOSD2vyMkb .icon-shape .label rect,#mermaid-svg-NpeRfLvOSD2vyMkb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NpeRfLvOSD2vyMkb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NpeRfLvOSD2vyMkb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NpeRfLvOSD2vyMkb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 关键信息
关键信息
关键信息
开头
找到率: 95%
中间
找到率: 40%
结尾
找到率: 90%
U形的注意力曲线------模型对开头和结尾的内容记得最清楚,中间的部分经常"看漏"。
这意味着什么?你把对话历史全塞进prompt里,模型也不一定真的"读"了。 它可能只看了头尾。
一个比喻:Agent的短期记忆像便利贴
我再给你打个比方,保管你忘不了。
Agent的上下文窗口就像办公桌上贴满便利贴。每来一条新消息,Agent就贴一张新便利贴。
#mermaid-svg-npralA1nyyEoGC2a{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-npralA1nyyEoGC2a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-npralA1nyyEoGC2a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-npralA1nyyEoGC2a .error-icon{fill:#552222;}#mermaid-svg-npralA1nyyEoGC2a .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-npralA1nyyEoGC2a .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-npralA1nyyEoGC2a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-npralA1nyyEoGC2a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-npralA1nyyEoGC2a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-npralA1nyyEoGC2a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-npralA1nyyEoGC2a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-npralA1nyyEoGC2a .marker{fill:#333333;stroke:#333333;}#mermaid-svg-npralA1nyyEoGC2a .marker.cross{stroke:#333333;}#mermaid-svg-npralA1nyyEoGC2a svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-npralA1nyyEoGC2a p{margin:0;}#mermaid-svg-npralA1nyyEoGC2a .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-npralA1nyyEoGC2a .cluster-label text{fill:#333;}#mermaid-svg-npralA1nyyEoGC2a .cluster-label span{color:#333;}#mermaid-svg-npralA1nyyEoGC2a .cluster-label span p{background-color:transparent;}#mermaid-svg-npralA1nyyEoGC2a .label text,#mermaid-svg-npralA1nyyEoGC2a span{fill:#333;color:#333;}#mermaid-svg-npralA1nyyEoGC2a .node rect,#mermaid-svg-npralA1nyyEoGC2a .node circle,#mermaid-svg-npralA1nyyEoGC2a .node ellipse,#mermaid-svg-npralA1nyyEoGC2a .node polygon,#mermaid-svg-npralA1nyyEoGC2a .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-npralA1nyyEoGC2a .rough-node .label text,#mermaid-svg-npralA1nyyEoGC2a .node .label text,#mermaid-svg-npralA1nyyEoGC2a .image-shape .label,#mermaid-svg-npralA1nyyEoGC2a .icon-shape .label{text-anchor:middle;}#mermaid-svg-npralA1nyyEoGC2a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-npralA1nyyEoGC2a .rough-node .label,#mermaid-svg-npralA1nyyEoGC2a .node .label,#mermaid-svg-npralA1nyyEoGC2a .image-shape .label,#mermaid-svg-npralA1nyyEoGC2a .icon-shape .label{text-align:center;}#mermaid-svg-npralA1nyyEoGC2a .node.clickable{cursor:pointer;}#mermaid-svg-npralA1nyyEoGC2a .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-npralA1nyyEoGC2a .arrowheadPath{fill:#333333;}#mermaid-svg-npralA1nyyEoGC2a .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-npralA1nyyEoGC2a .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-npralA1nyyEoGC2a .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-npralA1nyyEoGC2a .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-npralA1nyyEoGC2a .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-npralA1nyyEoGC2a .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-npralA1nyyEoGC2a .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-npralA1nyyEoGC2a .cluster text{fill:#333;}#mermaid-svg-npralA1nyyEoGC2a .cluster span{color:#333;}#mermaid-svg-npralA1nyyEoGC2a 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-npralA1nyyEoGC2a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-npralA1nyyEoGC2a rect.text{fill:none;stroke-width:0;}#mermaid-svg-npralA1nyyEoGC2a .icon-shape,#mermaid-svg-npralA1nyyEoGC2a .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-npralA1nyyEoGC2a .icon-shape p,#mermaid-svg-npralA1nyyEoGC2a .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-npralA1nyyEoGC2a .icon-shape .label rect,#mermaid-svg-npralA1nyyEoGC2a .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-npralA1nyyEoGC2a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-npralA1nyyEoGC2a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-npralA1nyyEoGC2a :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 扔掉旧的
换大桌子
建档案室
桌子的面积(上下文窗口)
= 128k tokens
约10万字
便利贴越贴越多
桌面贴满了
怎么办?
桌子能继续用
但旧事记不住了
换200k tokens的模型
更贵,更慢
✅ 旧事存起来
需要时再调出来
短期记忆(贴在桌上的便利贴)= 上下文窗口
长期记忆(档案室)= 外部存储
这就是为什么Agent需要记忆管理。
5.2 两种记忆系统:短期和长期
跟人脑一样,Agent的记忆也得分成两套。
#mermaid-svg-y0DjCkf86zR1snK4{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-y0DjCkf86zR1snK4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y0DjCkf86zR1snK4 .error-icon{fill:#552222;}#mermaid-svg-y0DjCkf86zR1snK4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y0DjCkf86zR1snK4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y0DjCkf86zR1snK4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y0DjCkf86zR1snK4 .marker.cross{stroke:#333333;}#mermaid-svg-y0DjCkf86zR1snK4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y0DjCkf86zR1snK4 p{margin:0;}#mermaid-svg-y0DjCkf86zR1snK4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-y0DjCkf86zR1snK4 .cluster-label text{fill:#333;}#mermaid-svg-y0DjCkf86zR1snK4 .cluster-label span{color:#333;}#mermaid-svg-y0DjCkf86zR1snK4 .cluster-label span p{background-color:transparent;}#mermaid-svg-y0DjCkf86zR1snK4 .label text,#mermaid-svg-y0DjCkf86zR1snK4 span{fill:#333;color:#333;}#mermaid-svg-y0DjCkf86zR1snK4 .node rect,#mermaid-svg-y0DjCkf86zR1snK4 .node circle,#mermaid-svg-y0DjCkf86zR1snK4 .node ellipse,#mermaid-svg-y0DjCkf86zR1snK4 .node polygon,#mermaid-svg-y0DjCkf86zR1snK4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y0DjCkf86zR1snK4 .rough-node .label text,#mermaid-svg-y0DjCkf86zR1snK4 .node .label text,#mermaid-svg-y0DjCkf86zR1snK4 .image-shape .label,#mermaid-svg-y0DjCkf86zR1snK4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-y0DjCkf86zR1snK4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y0DjCkf86zR1snK4 .rough-node .label,#mermaid-svg-y0DjCkf86zR1snK4 .node .label,#mermaid-svg-y0DjCkf86zR1snK4 .image-shape .label,#mermaid-svg-y0DjCkf86zR1snK4 .icon-shape .label{text-align:center;}#mermaid-svg-y0DjCkf86zR1snK4 .node.clickable{cursor:pointer;}#mermaid-svg-y0DjCkf86zR1snK4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y0DjCkf86zR1snK4 .arrowheadPath{fill:#333333;}#mermaid-svg-y0DjCkf86zR1snK4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y0DjCkf86zR1snK4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y0DjCkf86zR1snK4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y0DjCkf86zR1snK4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y0DjCkf86zR1snK4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y0DjCkf86zR1snK4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y0DjCkf86zR1snK4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y0DjCkf86zR1snK4 .cluster text{fill:#333;}#mermaid-svg-y0DjCkf86zR1snK4 .cluster span{color:#333;}#mermaid-svg-y0DjCkf86zR1snK4 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-y0DjCkf86zR1snK4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y0DjCkf86zR1snK4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-y0DjCkf86zR1snK4 .icon-shape,#mermaid-svg-y0DjCkf86zR1snK4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y0DjCkf86zR1snK4 .icon-shape p,#mermaid-svg-y0DjCkf86zR1snK4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y0DjCkf86zR1snK4 .icon-shape .label rect,#mermaid-svg-y0DjCkf86zR1snK4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y0DjCkf86zR1snK4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y0DjCkf86zR1snK4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y0DjCkf86zR1snK4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 长期记忆
短期记忆
是
是
是
当前对话历史
存在上下文窗口里
关键事实
用户姓名/偏好
历史对话摘要
很久以前聊的
文档知识
RAG检索
用户消息
需要查长期记忆?
模型回答
短期记忆:当前对话历史
最简单粗暴的短期记忆,就是把整段对话历史都塞进prompt里。
python
messages = [
{"role": "system", "content": "你是一个友好的助手"},
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!有什么能帮你的?"},
{"role": "user", "content": "我叫小明"},
{"role": "assistant", "content": "你好小明!"},
{"role": "user", "content": "今天天气怎么样?"} # 当前问题
]
优点:简单,模型能看到完整对话。
缺点:
- 对话长了Token消耗爆炸
- 模型对中间内容"视而不见"
- 跨对话不持久(关掉就没了)
什么时候用:对话轮次少(<20轮)的简单场景。
长期记忆:3种实现方案
长期记忆就是把Agent"以前"知道的东西存起来,需要时再调出来。3种常见方案:
方案1:用文件存(最简单)
python
import json
import os
MEMORY_FILE = "agent_memory.json"
def save_memory(key, value):
"""存一条记忆"""
if os.path.exists(MEMORY_FILE):
with open(MEMORY_FILE, "r", encoding="utf-8") as f:
memory = json.load(f)
else:
memory = {}
memory[key] = value
with open(MEMORY_FILE, "w", encoding="utf-8") as f:
json.dump(memory, f, ensure_ascii=False, indent=2)
def load_memory():
"""读所有记忆"""
if os.path.exists(MEMORY_FILE):
with open(MEMORY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {}
# 用法
save_memory("user_name", "小明")
save_memory("user_city", "济南")
save_memory("user_job", "程序员")
print(load_memory())
# {'user_name': '小明', 'user_city': '济南', 'user_job': '程序员'}
方案2:用数据库存(适合生产)
python
import sqlite3
class MemoryDB:
def __init__(self, db_path="memory.db"):
self.conn = sqlite3.connect(db_path)
self._create_table()
def _create_table(self):
self.conn.execute("""
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
key TEXT,
value TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
self.conn.commit()
def save(self, user_id, key, value):
self.conn.execute(
"INSERT INTO memories (user_id, key, value) VALUES (?, ?, ?)",
(user_id, key, value)
)
self.conn.commit()
def get(self, user_id, key):
cursor = self.conn.execute(
"SELECT value FROM memories WHERE user_id=? AND key=? ORDER BY created_at DESC LIMIT 1",
(user_id, key)
)
row = cursor.fetchone()
return row[0] if row else None
def get_all(self, user_id):
cursor = self.conn.execute(
"SELECT key, value FROM memories WHERE user_id=?",
(user_id,)
)
return dict(cursor.fetchall())
# 用法
db = MemoryDB()
db.save("user_001", "姓名", "小明")
db.save("user_001", "城市", "济南")
print(db.get("user_001", "姓名")) # 输出:小明
print(db.get_all("user_001")) # 输出:{'姓名': '小明', '城市': '济南'}
方案3:用向量数据库(语义搜索)
前两种都只能"按key精确查找"。但如果用户问"我以前告诉过你我喜欢什么?"------你得按意思找,不是按key。
这时候就要向量数据库了。
5.3 向量数据库:让Agent"按意思"搜索
这节我们搞懂一个看起来高大上其实没那么玄的概念------向量数据库。
先理解"向量"
你把一句话扔进一个叫"嵌入模型"(Embedding Model)的小模型,它会给你吐出来一组数字------这就是向量。
python
from openai import OpenAI
client = OpenAI(api_key="你的Key", base_url="https://api.deepseek.com")
# 把一段文本转成向量
response = client.embeddings.create(
model="text-embedding-v3", # Embedding专用模型
input="我喜欢吃川菜,尤其是火锅"
)
vector = response.data[0].embedding
print(f"向量维度: {len(vector)}") # 1536维
print(f"前5个数字: {vector[:5]}") # [0.012, -0.034, 0.056, ...]
一段文字变成了一串数字。关键是:意思相近的文本,数字也相近。
比如:
- "我喜欢吃川菜" →
[0.1, 0.2, 0.3, ...] - "我爱吃麻辣火锅" →
[0.11, 0.21, 0.31, ...](很接近!) - "我不喜欢吃西餐" →
[-0.1, -0.2, -0.3, ...](方向相反)
这就是向量数据库的魔法------按"意思"搜索,而不是按"关键词"。
#mermaid-svg-nZePLxU89qfdJe9r{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-nZePLxU89qfdJe9r .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nZePLxU89qfdJe9r .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nZePLxU89qfdJe9r .error-icon{fill:#552222;}#mermaid-svg-nZePLxU89qfdJe9r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nZePLxU89qfdJe9r .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nZePLxU89qfdJe9r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nZePLxU89qfdJe9r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nZePLxU89qfdJe9r .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nZePLxU89qfdJe9r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nZePLxU89qfdJe9r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nZePLxU89qfdJe9r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nZePLxU89qfdJe9r .marker.cross{stroke:#333333;}#mermaid-svg-nZePLxU89qfdJe9r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nZePLxU89qfdJe9r p{margin:0;}#mermaid-svg-nZePLxU89qfdJe9r .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nZePLxU89qfdJe9r .cluster-label text{fill:#333;}#mermaid-svg-nZePLxU89qfdJe9r .cluster-label span{color:#333;}#mermaid-svg-nZePLxU89qfdJe9r .cluster-label span p{background-color:transparent;}#mermaid-svg-nZePLxU89qfdJe9r .label text,#mermaid-svg-nZePLxU89qfdJe9r span{fill:#333;color:#333;}#mermaid-svg-nZePLxU89qfdJe9r .node rect,#mermaid-svg-nZePLxU89qfdJe9r .node circle,#mermaid-svg-nZePLxU89qfdJe9r .node ellipse,#mermaid-svg-nZePLxU89qfdJe9r .node polygon,#mermaid-svg-nZePLxU89qfdJe9r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nZePLxU89qfdJe9r .rough-node .label text,#mermaid-svg-nZePLxU89qfdJe9r .node .label text,#mermaid-svg-nZePLxU89qfdJe9r .image-shape .label,#mermaid-svg-nZePLxU89qfdJe9r .icon-shape .label{text-anchor:middle;}#mermaid-svg-nZePLxU89qfdJe9r .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nZePLxU89qfdJe9r .rough-node .label,#mermaid-svg-nZePLxU89qfdJe9r .node .label,#mermaid-svg-nZePLxU89qfdJe9r .image-shape .label,#mermaid-svg-nZePLxU89qfdJe9r .icon-shape .label{text-align:center;}#mermaid-svg-nZePLxU89qfdJe9r .node.clickable{cursor:pointer;}#mermaid-svg-nZePLxU89qfdJe9r .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nZePLxU89qfdJe9r .arrowheadPath{fill:#333333;}#mermaid-svg-nZePLxU89qfdJe9r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nZePLxU89qfdJe9r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nZePLxU89qfdJe9r .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nZePLxU89qfdJe9r .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nZePLxU89qfdJe9r .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nZePLxU89qfdJe9r .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nZePLxU89qfdJe9r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nZePLxU89qfdJe9r .cluster text{fill:#333;}#mermaid-svg-nZePLxU89qfdJe9r .cluster span{color:#333;}#mermaid-svg-nZePLxU89qfdJe9r 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-nZePLxU89qfdJe9r .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nZePLxU89qfdJe9r rect.text{fill:none;stroke-width:0;}#mermaid-svg-nZePLxU89qfdJe9r .icon-shape,#mermaid-svg-nZePLxU89qfdJe9r .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nZePLxU89qfdJe9r .icon-shape p,#mermaid-svg-nZePLxU89qfdJe9r .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nZePLxU89qfdJe9r .icon-shape .label rect,#mermaid-svg-nZePLxU89qfdJe9r .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nZePLxU89qfdJe9r .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nZePLxU89qfdJe9r .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nZePLxU89qfdJe9r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Embed
Embed
Embed
距离近 ✅
距离远 ❌
'我喜欢吃川菜'
向量 1
'我爱吃麻辣火锅'
向量 2
'今天天气真好'
向量 3
ChromaDB:新手最友好的向量数据库
向量数据库有很多(Chroma、Milvus、Pinecone、Qdrant)。对新手来说,Chroma最友好------5分钟上手。
bash
# 安装
pip install chromadb
python
import chromadb
# ===== 1. 初始化 =====
client = chromadb.PersistentClient(path="./chroma_db") # 数据存到本地
collection = client.get_or_create_collection(name="user_memories")
# ===== 2. 存记忆 =====
# Chroma会自动把文本转成向量(用默认的Embedding模型)
collection.add(
documents=[
"用户姓名是小明",
"用户住在济南",
"用户是程序员",
"用户喜欢吃川菜"
],
ids=["mem1", "mem2", "mem3", "mem4"] # 每条记忆的唯一ID
)
# ===== 3. 查记忆(按意思)=====
results = collection.query(
query_texts=["你还记得我家在哪吗?"], # 用自然语言查
n_results=2 # 返回最相关的2条
)
print("查到的记忆:")
for doc in results["documents"][0]:
print(f" - {doc}")
# 输出:
# - 用户住在济南
# - 用户姓名是小明
看到没? 你问"我家在哪",系统自动找到了"用户住在济南"------因为意思相近,不需要关键词匹配。
完整实战:给Agent加上"记仇"功能
我们把上面这些拼起来,做一个完整的Agent------它能记住用户的偏好和重要信息。
python
import chromadb
from openai import OpenAI
from datetime import datetime
class MemoryAgent:
def __init__(self):
# LLM客户端
self.llm = OpenAI(
api_key="你的Key",
base_url="https://api.deepseek.com"
)
# 向量数据库(长期记忆)
self.chroma = chromadb.PersistentClient(path="./agent_memory")
self.memory = self.chroma.get_or_create_collection(name="memories")
# 短期记忆(当前对话)
self.short_term = []
def memorize(self, content: str, importance: int = 5):
"""主动记忆:把信息存进长期记忆"""
memory_id = f"mem_{datetime.now().timestamp()}"
self.memory.add(
documents=[f"[重要性:{importance}] {content}"],
ids=[memory_id]
)
print(f"💾 已记住: {content}")
def recall(self, query: str, top_k: int = 3) -> str:
"""主动回忆:从长期记忆里找相关的信息"""
results = self.memory.query(
query_texts=[query],
n_results=top_k
)
if not results["documents"][0]:
return "(没有相关记忆)"
memories = "\n".join([f"- {doc}" for doc in results["documents"][0]])
return memories
def chat(self, user_input: str) -> str:
"""主对话流程"""
# 1. 从长期记忆里找相关信息
relevant_memories = self.recall(user_input)
# 2. 构建prompt(带记忆的)
system_prompt = f"""你是一个贴心的助手。你记得用户的以下信息:
{relevant_memories}
请基于这些信息回答用户。如果用户告诉了新的重要信息,请在回答末尾用[MEMORY:内容]标注。"""
# 3. 调用模型
self.short_term.append({"role": "user", "content": user_input})
messages = [{"role": "system", "content": system_prompt}] + self.short_term
response = self.llm.chat.completions.create(
model="deepseek-chat",
messages=messages
)
reply = response.choices[0].message.content
# 4. 把模型回复加入短期记忆
self.short_term.append({"role": "assistant", "content": reply})
# 5. 检查是否有需要长期记忆的内容
if "[MEMORY:" in reply:
# 提取[MEMORY:xxx]中的内容
import re
mem_content = re.search(r'\[MEMORY:(.*?)\]', reply).group(1)
self.memorize(mem_content)
# 把标记去掉再给用户看
reply = re.sub(r'\[MEMORY:.*?\]', '', reply).strip()
return reply
# ===== 使用示例 =====
if __name__ == "__main__":
agent = MemoryAgent()
# 第1轮对话
print("\n👤: 我叫小明,在济南工作")
print(f"🤖: {agent.chat('我叫小明,在济南工作')}")
# 第2轮
print("\n👤: 我喜欢吃川菜,尤其是火锅")
print(f"🤖: {agent.chat('我喜欢吃川菜,尤其是火锅')}")
# 第3轮
print("\n👤: 今天心情不太好")
print(f"🤖: {agent.chat('今天心情不太好')}")
# 第4轮------测一下它还记不记得
print("\n👤: 你还记得我是干什么工作的吗?")
print(f"🤖: {agent.chat('你还记得我是干什么工作的吗?')}")
# 第5轮
print("\n👤: 我家在哪?")
print(f"🤖: {agent.chat('我家在哪?')}")
跑一下你就会发现------Agent真的"记住"了! 哪怕对话过了很多轮,它也能从长期记忆里把关键信息调出来。
这就是向量数据库+短期记忆的协作威力。
5.4 MemGPT论文:把"虚拟内存"搬进LLM
如果上面的方案是"小修小补",那MemGPT这论文就是"大刀阔斧"------它重新设计了Agent的记忆架构。
一句话讲清MemGPT
把LLM当成操作系统,用"主存+外存"的方式管理记忆,让LLM自己决定什么时候换页。
这是UC Berkeley 2023年发的论文,作者是大名鼎鼎的Joseph Gonzalez和Ion Stoica(这俩人是Spark和Ray的核心人物)。
核心思想:LLM = 操作系统
你可能没意识到:你电脑的内存管理,和LLM的记忆管理,原理上是一样的。
#mermaid-svg-1G05ohF4zM5jWr0d{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-1G05ohF4zM5jWr0d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1G05ohF4zM5jWr0d .error-icon{fill:#552222;}#mermaid-svg-1G05ohF4zM5jWr0d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1G05ohF4zM5jWr0d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1G05ohF4zM5jWr0d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1G05ohF4zM5jWr0d .marker.cross{stroke:#333333;}#mermaid-svg-1G05ohF4zM5jWr0d svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1G05ohF4zM5jWr0d p{margin:0;}#mermaid-svg-1G05ohF4zM5jWr0d .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1G05ohF4zM5jWr0d .cluster-label text{fill:#333;}#mermaid-svg-1G05ohF4zM5jWr0d .cluster-label span{color:#333;}#mermaid-svg-1G05ohF4zM5jWr0d .cluster-label span p{background-color:transparent;}#mermaid-svg-1G05ohF4zM5jWr0d .label text,#mermaid-svg-1G05ohF4zM5jWr0d span{fill:#333;color:#333;}#mermaid-svg-1G05ohF4zM5jWr0d .node rect,#mermaid-svg-1G05ohF4zM5jWr0d .node circle,#mermaid-svg-1G05ohF4zM5jWr0d .node ellipse,#mermaid-svg-1G05ohF4zM5jWr0d .node polygon,#mermaid-svg-1G05ohF4zM5jWr0d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1G05ohF4zM5jWr0d .rough-node .label text,#mermaid-svg-1G05ohF4zM5jWr0d .node .label text,#mermaid-svg-1G05ohF4zM5jWr0d .image-shape .label,#mermaid-svg-1G05ohF4zM5jWr0d .icon-shape .label{text-anchor:middle;}#mermaid-svg-1G05ohF4zM5jWr0d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1G05ohF4zM5jWr0d .rough-node .label,#mermaid-svg-1G05ohF4zM5jWr0d .node .label,#mermaid-svg-1G05ohF4zM5jWr0d .image-shape .label,#mermaid-svg-1G05ohF4zM5jWr0d .icon-shape .label{text-align:center;}#mermaid-svg-1G05ohF4zM5jWr0d .node.clickable{cursor:pointer;}#mermaid-svg-1G05ohF4zM5jWr0d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1G05ohF4zM5jWr0d .arrowheadPath{fill:#333333;}#mermaid-svg-1G05ohF4zM5jWr0d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1G05ohF4zM5jWr0d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1G05ohF4zM5jWr0d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1G05ohF4zM5jWr0d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1G05ohF4zM5jWr0d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1G05ohF4zM5jWr0d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1G05ohF4zM5jWr0d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1G05ohF4zM5jWr0d .cluster text{fill:#333;}#mermaid-svg-1G05ohF4zM5jWr0d .cluster span{color:#333;}#mermaid-svg-1G05ohF4zM5jWr0d 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-1G05ohF4zM5jWr0d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1G05ohF4zM5jWr0d rect.text{fill:none;stroke-width:0;}#mermaid-svg-1G05ohF4zM5jWr0d .icon-shape,#mermaid-svg-1G05ohF4zM5jWr0d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1G05ohF4zM5jWr0d .icon-shape p,#mermaid-svg-1G05ohF4zM5jWr0d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1G05ohF4zM5jWr0d .icon-shape .label rect,#mermaid-svg-1G05ohF4zM5jWr0d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1G05ohF4zM5jWr0d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1G05ohF4zM5jWr0d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1G05ohF4zM5jWr0d :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} LLM的记忆
需要时调入
主上下文(快、小、贵)
外部存储(慢、大、便宜)
LLM自己决定
什么时候换页
电脑的内存
需要时调入
RAM(快、小、贵)
Disk(慢、大、便宜)
操作系统决定
什么时候换页
MemGPT的核心洞见就是:把这套机制照搬到LLM上。
- RAM → 主上下文(Main Context):能装下系统指令、工作上下文、当前对话
- Disk → 外部上下文(External Context):更大的存储,LLM需要时主动调用函数加载
MemGPT的三层记忆
MemGPT把记忆分成了三层,层层递进:
| 层级 | 比喻 | 大小 | 访问方式 |
|---|---|---|---|
| 主上下文 | 工作台 | 128k tokens | 模型直接"看到" |
| 召回存储 | 桌面抽屉 | 几百MB | 关键词搜索 |
| 归档存储 | 档案室 | 几十GB | 向量搜索 |
#mermaid-svg-LyL7KUyYVT2MIthH{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-LyL7KUyYVT2MIthH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LyL7KUyYVT2MIthH .error-icon{fill:#552222;}#mermaid-svg-LyL7KUyYVT2MIthH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LyL7KUyYVT2MIthH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LyL7KUyYVT2MIthH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LyL7KUyYVT2MIthH .marker.cross{stroke:#333333;}#mermaid-svg-LyL7KUyYVT2MIthH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LyL7KUyYVT2MIthH p{margin:0;}#mermaid-svg-LyL7KUyYVT2MIthH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LyL7KUyYVT2MIthH .cluster-label text{fill:#333;}#mermaid-svg-LyL7KUyYVT2MIthH .cluster-label span{color:#333;}#mermaid-svg-LyL7KUyYVT2MIthH .cluster-label span p{background-color:transparent;}#mermaid-svg-LyL7KUyYVT2MIthH .label text,#mermaid-svg-LyL7KUyYVT2MIthH span{fill:#333;color:#333;}#mermaid-svg-LyL7KUyYVT2MIthH .node rect,#mermaid-svg-LyL7KUyYVT2MIthH .node circle,#mermaid-svg-LyL7KUyYVT2MIthH .node ellipse,#mermaid-svg-LyL7KUyYVT2MIthH .node polygon,#mermaid-svg-LyL7KUyYVT2MIthH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LyL7KUyYVT2MIthH .rough-node .label text,#mermaid-svg-LyL7KUyYVT2MIthH .node .label text,#mermaid-svg-LyL7KUyYVT2MIthH .image-shape .label,#mermaid-svg-LyL7KUyYVT2MIthH .icon-shape .label{text-anchor:middle;}#mermaid-svg-LyL7KUyYVT2MIthH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LyL7KUyYVT2MIthH .rough-node .label,#mermaid-svg-LyL7KUyYVT2MIthH .node .label,#mermaid-svg-LyL7KUyYVT2MIthH .image-shape .label,#mermaid-svg-LyL7KUyYVT2MIthH .icon-shape .label{text-align:center;}#mermaid-svg-LyL7KUyYVT2MIthH .node.clickable{cursor:pointer;}#mermaid-svg-LyL7KUyYVT2MIthH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LyL7KUyYVT2MIthH .arrowheadPath{fill:#333333;}#mermaid-svg-LyL7KUyYVT2MIthH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LyL7KUyYVT2MIthH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LyL7KUyYVT2MIthH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LyL7KUyYVT2MIthH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LyL7KUyYVT2MIthH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LyL7KUyYVT2MIthH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LyL7KUyYVT2MIthH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LyL7KUyYVT2MIthH .cluster text{fill:#333;}#mermaid-svg-LyL7KUyYVT2MIthH .cluster span{color:#333;}#mermaid-svg-LyL7KUyYVT2MIthH 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-LyL7KUyYVT2MIthH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LyL7KUyYVT2MIthH rect.text{fill:none;stroke-width:0;}#mermaid-svg-LyL7KUyYVT2MIthH .icon-shape,#mermaid-svg-LyL7KUyYVT2MIthH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LyL7KUyYVT2MIthH .icon-shape p,#mermaid-svg-LyL7KUyYVT2MIthH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LyL7KUyYVT2MIthH .icon-shape .label rect,#mermaid-svg-LyL7KUyYVT2MIthH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LyL7KUyYVT2MIthH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LyL7KUyYVT2MIthH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LyL7KUyYVT2MIthH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} retrieve()
向量搜索
满了
🤖 LLM
(看得到主上下文)
📋 主上下文
128k tokens
系统指令 + 当前对话 + 关键事实
📁 召回存储
全部历史消息
关键词搜索
🗄️ 归档存储
向量数据库
语义搜索
⚠️ 触发摘要
递归压缩旧对话
三个核心函数:retrieve / insert / update
LLM通过调用三个函数来管理自己的记忆:
python
# 1. retrieve:从档案室找资料
memory.retrieve(query="用户上次说想吃什么?")
# 2. insert:把新信息存进档案室
memory.insert(content="用户喜欢川菜,尤其是火锅")
# 3. update:更新已有记录
memory.update(memory_id="mem_123", new_content="用户现在不爱吃川菜了")
关键来了:这三个函数不是开发者调的,是LLM自己调的。
MemGPT的设计哲学是:让LLM自己决定什么时候调什么函数。 不需要写死规则。
MemGPT的实战效果
论文里有个实验特别有意思:把"嵌套K-V查找"的任务------也就是多跳记忆检索。
比如:
- 文档1:"Alice在巴黎"
- 文档2:"巴黎的法语是Paris"
- 文档3:"Paris的市长是Jean"
问"Alice所在城市的市长的名字",需要先查文档1,再查文档2,再查文档3。
#mermaid-svg-AcqdC65eICXSPx8h{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-AcqdC65eICXSPx8h .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AcqdC65eICXSPx8h .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AcqdC65eICXSPx8h .error-icon{fill:#552222;}#mermaid-svg-AcqdC65eICXSPx8h .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AcqdC65eICXSPx8h .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AcqdC65eICXSPx8h .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AcqdC65eICXSPx8h .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AcqdC65eICXSPx8h .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AcqdC65eICXSPx8h .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AcqdC65eICXSPx8h .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AcqdC65eICXSPx8h .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AcqdC65eICXSPx8h .marker.cross{stroke:#333333;}#mermaid-svg-AcqdC65eICXSPx8h svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AcqdC65eICXSPx8h p{margin:0;}#mermaid-svg-AcqdC65eICXSPx8h .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AcqdC65eICXSPx8h .cluster-label text{fill:#333;}#mermaid-svg-AcqdC65eICXSPx8h .cluster-label span{color:#333;}#mermaid-svg-AcqdC65eICXSPx8h .cluster-label span p{background-color:transparent;}#mermaid-svg-AcqdC65eICXSPx8h .label text,#mermaid-svg-AcqdC65eICXSPx8h span{fill:#333;color:#333;}#mermaid-svg-AcqdC65eICXSPx8h .node rect,#mermaid-svg-AcqdC65eICXSPx8h .node circle,#mermaid-svg-AcqdC65eICXSPx8h .node ellipse,#mermaid-svg-AcqdC65eICXSPx8h .node polygon,#mermaid-svg-AcqdC65eICXSPx8h .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AcqdC65eICXSPx8h .rough-node .label text,#mermaid-svg-AcqdC65eICXSPx8h .node .label text,#mermaid-svg-AcqdC65eICXSPx8h .image-shape .label,#mermaid-svg-AcqdC65eICXSPx8h .icon-shape .label{text-anchor:middle;}#mermaid-svg-AcqdC65eICXSPx8h .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AcqdC65eICXSPx8h .rough-node .label,#mermaid-svg-AcqdC65eICXSPx8h .node .label,#mermaid-svg-AcqdC65eICXSPx8h .image-shape .label,#mermaid-svg-AcqdC65eICXSPx8h .icon-shape .label{text-align:center;}#mermaid-svg-AcqdC65eICXSPx8h .node.clickable{cursor:pointer;}#mermaid-svg-AcqdC65eICXSPx8h .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AcqdC65eICXSPx8h .arrowheadPath{fill:#333333;}#mermaid-svg-AcqdC65eICXSPx8h .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AcqdC65eICXSPx8h .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AcqdC65eICXSPx8h .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AcqdC65eICXSPx8h .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AcqdC65eICXSPx8h .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AcqdC65eICXSPx8h .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AcqdC65eICXSPx8h .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AcqdC65eICXSPx8h .cluster text{fill:#333;}#mermaid-svg-AcqdC65eICXSPx8h .cluster span{color:#333;}#mermaid-svg-AcqdC65eICXSPx8h 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-AcqdC65eICXSPx8h .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AcqdC65eICXSPx8h rect.text{fill:none;stroke-width:0;}#mermaid-svg-AcqdC65eICXSPx8h .icon-shape,#mermaid-svg-AcqdC65eICXSPx8h .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AcqdC65eICXSPx8h .icon-shape p,#mermaid-svg-AcqdC65eICXSPx8h .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AcqdC65eICXSPx8h .icon-shape .label rect,#mermaid-svg-AcqdC65eICXSPx8h .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AcqdC65eICXSPx8h .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AcqdC65eICXSPx8h .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AcqdC65eICXSPx8h :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 文档1
文档2
文档3
Alice在哪?
巴黎
Paris
Jean
传统LLM(不管理记忆)的准确率:
| 模型 | 1层查找 | 2层查找 | 3层查找 |
|---|---|---|---|
| GPT-3.5 | 70% | 35% | 5% |
| GPT-4 | 75% | 40% | 10% |
| GPT-4 Turbo | 80% | 50% | 15% |
加了MemGPT之后:
| 模型 | 1层查找 | 2层查找 | 3层查找 |
|---|---|---|---|
| GPT-3.5 + MemGPT | 85% | 70% | 50% |
| GPT-4 + MemGPT | 95% | 92% | 88% |
天差地别。 在多跳查找任务上,MemGPT把GPT-4从15%拉到了88%。
一句话总结MemGPT
不要让LLM的"脑子"装所有东西。让它学会"翻本子"。
MemGPT后来演变成了开源项目Letta(GitHub 30k+⭐),专门做"有状态的LLM Agent"。
对普通开发者的启示
虽然MemGPT的设计很精妙,但对普通Agent开发 来说,80%的场景用短期记忆+向量数据库就够了。MemGPT是处理超长对话、复杂文档分析时才需要。
#mermaid-svg-FKEzixE3Zx3rB2Pe{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-FKEzixE3Zx3rB2Pe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FKEzixE3Zx3rB2Pe .error-icon{fill:#552222;}#mermaid-svg-FKEzixE3Zx3rB2Pe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FKEzixE3Zx3rB2Pe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .marker.cross{stroke:#333333;}#mermaid-svg-FKEzixE3Zx3rB2Pe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FKEzixE3Zx3rB2Pe p{margin:0;}#mermaid-svg-FKEzixE3Zx3rB2Pe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster-label text{fill:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster-label span{color:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster-label span p{background-color:transparent;}#mermaid-svg-FKEzixE3Zx3rB2Pe .label text,#mermaid-svg-FKEzixE3Zx3rB2Pe span{fill:#333;color:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .node rect,#mermaid-svg-FKEzixE3Zx3rB2Pe .node circle,#mermaid-svg-FKEzixE3Zx3rB2Pe .node ellipse,#mermaid-svg-FKEzixE3Zx3rB2Pe .node polygon,#mermaid-svg-FKEzixE3Zx3rB2Pe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .rough-node .label text,#mermaid-svg-FKEzixE3Zx3rB2Pe .node .label text,#mermaid-svg-FKEzixE3Zx3rB2Pe .image-shape .label,#mermaid-svg-FKEzixE3Zx3rB2Pe .icon-shape .label{text-anchor:middle;}#mermaid-svg-FKEzixE3Zx3rB2Pe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .rough-node .label,#mermaid-svg-FKEzixE3Zx3rB2Pe .node .label,#mermaid-svg-FKEzixE3Zx3rB2Pe .image-shape .label,#mermaid-svg-FKEzixE3Zx3rB2Pe .icon-shape .label{text-align:center;}#mermaid-svg-FKEzixE3Zx3rB2Pe .node.clickable{cursor:pointer;}#mermaid-svg-FKEzixE3Zx3rB2Pe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .arrowheadPath{fill:#333333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FKEzixE3Zx3rB2Pe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FKEzixE3Zx3rB2Pe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FKEzixE3Zx3rB2Pe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster text{fill:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe .cluster span{color:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe 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-FKEzixE3Zx3rB2Pe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FKEzixE3Zx3rB2Pe rect.text{fill:none;stroke-width:0;}#mermaid-svg-FKEzixE3Zx3rB2Pe .icon-shape,#mermaid-svg-FKEzixE3Zx3rB2Pe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FKEzixE3Zx3rB2Pe .icon-shape p,#mermaid-svg-FKEzixE3Zx3rB2Pe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FKEzixE3Zx3rB2Pe .icon-shape .label rect,#mermaid-svg-FKEzixE3Zx3rB2Pe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FKEzixE3Zx3rB2Pe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FKEzixE3Zx3rB2Pe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FKEzixE3Zx3rB2Pe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 对话短(<20轮)
文档少
对话中等
需要查文档
对话超长
多跳记忆检索
企业级文档分析
你的场景?
✅ 短期记忆
塞进prompt就行
✅ 短期+向量库
ChromaDB够用
✅ MemGPT/Letta
用框架
✅ MemGPT+自定义
生产环境
5.5 Generative Agents:25个AI在虚拟小镇生活
如果说MemGPT是"系统级"的方案,那Generative Agents就是"应用级"的奇迹。
论文做了什么?
2023年,斯坦福和Google的研究者搞了个虚拟小镇Smallville,放了25个AI居民。每个AI都有自己的人设、记忆、社交关系。
#mermaid-svg-Yy5Rtf2Dwnmx2gNz{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-Yy5Rtf2Dwnmx2gNz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .error-icon{fill:#552222;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .marker.cross{stroke:#333333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz p{margin:0;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster-label text{fill:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster-label span{color:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster-label span p{background-color:transparent;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .label text,#mermaid-svg-Yy5Rtf2Dwnmx2gNz span{fill:#333;color:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node rect,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node circle,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node ellipse,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node polygon,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .rough-node .label text,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node .label text,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .image-shape .label,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .icon-shape .label{text-anchor:middle;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .rough-node .label,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node .label,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .image-shape .label,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .icon-shape .label{text-align:center;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node.clickable{cursor:pointer;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .arrowheadPath{fill:#333333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster text{fill:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .cluster span{color:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz 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-Yy5Rtf2Dwnmx2gNz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz rect.text{fill:none;stroke-width:0;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .icon-shape,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .icon-shape p,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .icon-shape .label rect,#mermaid-svg-Yy5Rtf2Dwnmx2gNz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Yy5Rtf2Dwnmx2gNz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有生意往来
是朋友
有共同爱好
🏘️ Smallville 虚拟小镇
👨 25个AI居民
👤 Isabella
咖啡店老板
👤 Tom
作家
👤 Mary
画家
...
👤 John
最后一个居民
最神奇的是:这些AI能自主组织活动。比如情人节那天,几个AI自发决定办一个情人节派对------这个行为不是人写的,是AI自己涌现出来的。
研究者只是给了25个AI基本人设,它们就自己发展出了社交网络、传播八卦、结成同盟。
三大核心机制
Generative Agents成功的关键,是它设计了三个互相配合的机制。
#mermaid-svg-WjxKApmh8Qs6zh9x{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-WjxKApmh8Qs6zh9x .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WjxKApmh8Qs6zh9x .error-icon{fill:#552222;}#mermaid-svg-WjxKApmh8Qs6zh9x .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WjxKApmh8Qs6zh9x .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WjxKApmh8Qs6zh9x .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WjxKApmh8Qs6zh9x .marker.cross{stroke:#333333;}#mermaid-svg-WjxKApmh8Qs6zh9x svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WjxKApmh8Qs6zh9x p{margin:0;}#mermaid-svg-WjxKApmh8Qs6zh9x .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster-label text{fill:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster-label span{color:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster-label span p{background-color:transparent;}#mermaid-svg-WjxKApmh8Qs6zh9x .label text,#mermaid-svg-WjxKApmh8Qs6zh9x span{fill:#333;color:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x .node rect,#mermaid-svg-WjxKApmh8Qs6zh9x .node circle,#mermaid-svg-WjxKApmh8Qs6zh9x .node ellipse,#mermaid-svg-WjxKApmh8Qs6zh9x .node polygon,#mermaid-svg-WjxKApmh8Qs6zh9x .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WjxKApmh8Qs6zh9x .rough-node .label text,#mermaid-svg-WjxKApmh8Qs6zh9x .node .label text,#mermaid-svg-WjxKApmh8Qs6zh9x .image-shape .label,#mermaid-svg-WjxKApmh8Qs6zh9x .icon-shape .label{text-anchor:middle;}#mermaid-svg-WjxKApmh8Qs6zh9x .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WjxKApmh8Qs6zh9x .rough-node .label,#mermaid-svg-WjxKApmh8Qs6zh9x .node .label,#mermaid-svg-WjxKApmh8Qs6zh9x .image-shape .label,#mermaid-svg-WjxKApmh8Qs6zh9x .icon-shape .label{text-align:center;}#mermaid-svg-WjxKApmh8Qs6zh9x .node.clickable{cursor:pointer;}#mermaid-svg-WjxKApmh8Qs6zh9x .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WjxKApmh8Qs6zh9x .arrowheadPath{fill:#333333;}#mermaid-svg-WjxKApmh8Qs6zh9x .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WjxKApmh8Qs6zh9x .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WjxKApmh8Qs6zh9x .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WjxKApmh8Qs6zh9x .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WjxKApmh8Qs6zh9x .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WjxKApmh8Qs6zh9x .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster text{fill:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x .cluster span{color:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x 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-WjxKApmh8Qs6zh9x .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WjxKApmh8Qs6zh9x rect.text{fill:none;stroke-width:0;}#mermaid-svg-WjxKApmh8Qs6zh9x .icon-shape,#mermaid-svg-WjxKApmh8Qs6zh9x .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WjxKApmh8Qs6zh9x .icon-shape p,#mermaid-svg-WjxKApmh8Qs6zh9x .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WjxKApmh8Qs6zh9x .icon-shape .label rect,#mermaid-svg-WjxKApmh8Qs6zh9x .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WjxKApmh8Qs6zh9x .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WjxKApmh8Qs6zh9x .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WjxKApmh8Qs6zh9x :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 👀 Memory Stream
记忆流
🤔 Reflection
反思
📋 Planning
规划
🎬 Action
行动
机制1:记忆流(Memory Stream)
每个AI都有个"小本本",按时间顺序记下看到、听到、做过的事。
python
class MemoryStream:
def __init__(self):
self.memories = [] # 所有记忆
def add_observation(self, content, importance_score):
"""加一条新记忆(带重要性打分)"""
self.memories.append({
"time": current_time(),
"content": content,
"importance": importance_score, # 0-10分
"type": "observation"
})
def retrieve(self, query, top_k=10):
"""检索时综合考虑:相关性 + 重要性 + 时间新鲜度"""
scored = []
for mem in self.memories:
relevance = compute_relevance(query, mem["content"])
recency = time_decay(mem["time"])
score = relevance + mem["importance"]/10 + recency
scored.append((score, mem))
scored.sort(reverse=True)
return [m for _, m in scored[:top_k]]
关键创新 :检索时不是只看相关性,而是相关性 × 重要性 × 新鲜度的综合分数。
这意味着:
- 跟当前问题相关的(语义近)
- 重要性高的(重要的事)
- 最近发生的(新鲜的)
这三个维度综合起来,决定哪些记忆被调出来。
机制2:反思(Reflection)
光记流水账不够,AI还得有自己的"想法"。
当记忆积累到一定数量(论文里是100+条),LLM会主动总结:
python
class Reflection:
def generate(self, recent_memories):
prompt = f"""
基于以下最近的{len(recent_memories)}条重要记忆,
总结出几条高级洞察(用问题和答案的形式):
{recent_memories}
输出3条反思:
- 问题1:...
答案1:...
- 问题2:...
答案2:...
"""
reflections = llm_generate(prompt)
# 反思本身就是一条记忆
for reflection in reflections:
memory_stream.add(reflection, importance=9)
举个例子:
- 流水账:"早上起床了","和Bob吵架了","吃了个三明治"
- 反思:"我最近和Bob的关系变差了,可能因为上次项目的事"
反思是带"洞察"的------它把一堆散乱的事提炼成了一句"我学到了什么"。
机制3:规划(Planning)
有了记忆和反思,AI就能规划自己的行动。
python
class Planning:
def make_plan(self, agent, current_time):
# 1. 收集上下文:相关记忆 + 当前反思
context = memory_stream.retrieve("今天要做什么")
context += [r["content"] for r in reflection.reflections]
# 2. 让LLM生成分层计划
prompt = f"""
你是{agent.name}。
你最近的记忆和反思:{context}
当前时间:{current_time}
生成今日计划:
- 总体目标
- 上午计划
- 下午计划
- 晚上计划
"""
plan = llm_generate(prompt)
关键创新:递归规划。不是"我要做X",而是"我要做X,因为X,所以X"------一棵规划树。
三大机制怎么配合?
记忆流是数据库,反思是自我意识,规划是执行力。
#mermaid-svg-LdxzGy9H1aKzDcnp{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-LdxzGy9H1aKzDcnp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LdxzGy9H1aKzDcnp .error-icon{fill:#552222;}#mermaid-svg-LdxzGy9H1aKzDcnp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LdxzGy9H1aKzDcnp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LdxzGy9H1aKzDcnp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LdxzGy9H1aKzDcnp .marker.cross{stroke:#333333;}#mermaid-svg-LdxzGy9H1aKzDcnp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LdxzGy9H1aKzDcnp p{margin:0;}#mermaid-svg-LdxzGy9H1aKzDcnp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster-label text{fill:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster-label span{color:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster-label span p{background-color:transparent;}#mermaid-svg-LdxzGy9H1aKzDcnp .label text,#mermaid-svg-LdxzGy9H1aKzDcnp span{fill:#333;color:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp .node rect,#mermaid-svg-LdxzGy9H1aKzDcnp .node circle,#mermaid-svg-LdxzGy9H1aKzDcnp .node ellipse,#mermaid-svg-LdxzGy9H1aKzDcnp .node polygon,#mermaid-svg-LdxzGy9H1aKzDcnp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LdxzGy9H1aKzDcnp .rough-node .label text,#mermaid-svg-LdxzGy9H1aKzDcnp .node .label text,#mermaid-svg-LdxzGy9H1aKzDcnp .image-shape .label,#mermaid-svg-LdxzGy9H1aKzDcnp .icon-shape .label{text-anchor:middle;}#mermaid-svg-LdxzGy9H1aKzDcnp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LdxzGy9H1aKzDcnp .rough-node .label,#mermaid-svg-LdxzGy9H1aKzDcnp .node .label,#mermaid-svg-LdxzGy9H1aKzDcnp .image-shape .label,#mermaid-svg-LdxzGy9H1aKzDcnp .icon-shape .label{text-align:center;}#mermaid-svg-LdxzGy9H1aKzDcnp .node.clickable{cursor:pointer;}#mermaid-svg-LdxzGy9H1aKzDcnp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LdxzGy9H1aKzDcnp .arrowheadPath{fill:#333333;}#mermaid-svg-LdxzGy9H1aKzDcnp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LdxzGy9H1aKzDcnp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LdxzGy9H1aKzDcnp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LdxzGy9H1aKzDcnp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LdxzGy9H1aKzDcnp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LdxzGy9H1aKzDcnp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster text{fill:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp .cluster span{color:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp 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-LdxzGy9H1aKzDcnp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LdxzGy9H1aKzDcnp rect.text{fill:none;stroke-width:0;}#mermaid-svg-LdxzGy9H1aKzDcnp .icon-shape,#mermaid-svg-LdxzGy9H1aKzDcnp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LdxzGy9H1aKzDcnp .icon-shape p,#mermaid-svg-LdxzGy9H1aKzDcnp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LdxzGy9H1aKzDcnp .icon-shape .label rect,#mermaid-svg-LdxzGy9H1aKzDcnp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LdxzGy9H1aKzDcnp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LdxzGy9H1aKzDcnp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LdxzGy9H1aKzDcnp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 提供素材
变成记忆
检索相关
影响决策
产生新观察
👀 Memory Stream
数据库
🤔 Reflection
自我意识
📋 Planning
执行力
三者形成自我增强的循环:
- 记忆 → 反思(从经验中学到什么)
- 反思 → 记忆(反思本身被记住)
- 记忆+反思 → 规划(决定做什么)
- 规划 → 行动 → 新记忆
25个AI自己办了个情人节派对
论文里最惊艳的实验:研究者没写任何"办派对"的代码。
他们只是在情人节那天,告诉其中一个AI Isabella"你想办个情人节派对"。然后啥也没管。
接下来两天里,AI们自己:
- Isabella发了邀请
- AI们互相传播消息
- 大家主动准备礼物
- 派对那天按时到达
这一切是"涌现"出来的。 没有人写规则。
一句话总结Generative Agents
记忆+反思+规划,让Agent像人一样活着。
对我们的启示
Generative Agents对普通Agent开发的启示是:
- 重要性打分很有用------不要把所有记忆都平等对待
- 反思机制能大幅提升决策质量------"我学到了什么"比"我做了啥"更有价值
- 分层规划比"走一步看一步"更稳定
但要小心:这套机制很贵、很慢 。每次规划都要LLM生成,每次反思都要LLM总结。生产环境慎用。
5.6 三种记忆方案对比 + 选型指南
| 维度 | 短期记忆 | 长期记忆(向量库) | MemGPT |
|---|---|---|---|
| 原理 | 对话历史塞进prompt | 文本→向量→按语义查 | 操作系统式分层管理 |
| 适合场景 | 短对话(<20轮) | 中等复杂Agent | 超长对话/复杂文档 |
| 优点 | 简单直接 | 跨对话持久 | 突破上下文限制 |
| 缺点 | Token爆涨 | 检索不准会误导 | 实现复杂、贵 |
| 实现成本 | ⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 代表项目 | 直接用 | LangChain Memory | Letta(原MemGPT) |
| GitHub Stars | - | Mem0 52k | Letta 30k |
选型决策图
#mermaid-svg-GKzfLJ3hjCfTklnf{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-GKzfLJ3hjCfTklnf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GKzfLJ3hjCfTklnf .error-icon{fill:#552222;}#mermaid-svg-GKzfLJ3hjCfTklnf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GKzfLJ3hjCfTklnf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GKzfLJ3hjCfTklnf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GKzfLJ3hjCfTklnf .marker.cross{stroke:#333333;}#mermaid-svg-GKzfLJ3hjCfTklnf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GKzfLJ3hjCfTklnf p{margin:0;}#mermaid-svg-GKzfLJ3hjCfTklnf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster-label text{fill:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster-label span{color:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster-label span p{background-color:transparent;}#mermaid-svg-GKzfLJ3hjCfTklnf .label text,#mermaid-svg-GKzfLJ3hjCfTklnf span{fill:#333;color:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf .node rect,#mermaid-svg-GKzfLJ3hjCfTklnf .node circle,#mermaid-svg-GKzfLJ3hjCfTklnf .node ellipse,#mermaid-svg-GKzfLJ3hjCfTklnf .node polygon,#mermaid-svg-GKzfLJ3hjCfTklnf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GKzfLJ3hjCfTklnf .rough-node .label text,#mermaid-svg-GKzfLJ3hjCfTklnf .node .label text,#mermaid-svg-GKzfLJ3hjCfTklnf .image-shape .label,#mermaid-svg-GKzfLJ3hjCfTklnf .icon-shape .label{text-anchor:middle;}#mermaid-svg-GKzfLJ3hjCfTklnf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GKzfLJ3hjCfTklnf .rough-node .label,#mermaid-svg-GKzfLJ3hjCfTklnf .node .label,#mermaid-svg-GKzfLJ3hjCfTklnf .image-shape .label,#mermaid-svg-GKzfLJ3hjCfTklnf .icon-shape .label{text-align:center;}#mermaid-svg-GKzfLJ3hjCfTklnf .node.clickable{cursor:pointer;}#mermaid-svg-GKzfLJ3hjCfTklnf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GKzfLJ3hjCfTklnf .arrowheadPath{fill:#333333;}#mermaid-svg-GKzfLJ3hjCfTklnf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GKzfLJ3hjCfTklnf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GKzfLJ3hjCfTklnf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GKzfLJ3hjCfTklnf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GKzfLJ3hjCfTklnf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GKzfLJ3hjCfTklnf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster text{fill:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf .cluster span{color:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf 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-GKzfLJ3hjCfTklnf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GKzfLJ3hjCfTklnf rect.text{fill:none;stroke-width:0;}#mermaid-svg-GKzfLJ3hjCfTklnf .icon-shape,#mermaid-svg-GKzfLJ3hjCfTklnf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GKzfLJ3hjCfTklnf .icon-shape p,#mermaid-svg-GKzfLJ3hjCfTklnf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GKzfLJ3hjCfTklnf .icon-shape .label rect,#mermaid-svg-GKzfLJ3hjCfTklnf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GKzfLJ3hjCfTklnf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GKzfLJ3hjCfTklnf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GKzfLJ3hjCfTklnf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 几句话就完事
需要跨对话记用户偏好
需要按意思搜索历史
上千轮对话
多跳推理
你的Agent
要记多少东西?
短期记忆
塞prompt
文件/数据库
key-value存
向量数据库
ChromaDB
MemGPT/Letta
企业级方案
我的实战建议
80%的Agent项目,用这套就够了:
python
# 1. 短期记忆:最近10轮对话
recent_messages = full_history[-10:]
# 2. 长期记忆:用向量库存关键事实
long_term = chromadb.get_relevant_facts(user_query, top_k=5)
# 3. 拼成prompt
prompt_messages = [
{"role": "system", "content": system_prompt_with_memories(long_term)},
*recent_messages,
{"role": "user", "content": user_query}
]
简单、有效、好维护。 别一上来就上MemGPT那种重量级方案。
5.7 Mem0:开箱即用的Agent记忆层
如果你不想自己写记忆管理代码,可以用Mem0(GitHub 52k⭐)------一个专门做Agent记忆的开源项目。
一行代码加记忆
bash
pip install mem0ai
python
from mem0 import Memory
m = Memory()
# 存记忆
m.add("用户叫小明,在济南工作,是程序员,喜欢吃川菜", user_id="user_001")
# 查记忆
relevant = m.search("用户住在哪里?", user_id="user_001")
print(relevant)
# [{'memory': '用户叫小明...', 'score': 0.92}, ...]
Mem0会自动做几件事:
- 从文本里提取关键事实(用了LLM)
- 去重(如果已有类似记忆就不重复存)
- 更新(如果新信息和旧信息矛盾,自动更新)
- 按用户/会话分类
#mermaid-svg-EwBHeXA8vDEOQf5K{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-EwBHeXA8vDEOQf5K .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EwBHeXA8vDEOQf5K .error-icon{fill:#552222;}#mermaid-svg-EwBHeXA8vDEOQf5K .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EwBHeXA8vDEOQf5K .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EwBHeXA8vDEOQf5K .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EwBHeXA8vDEOQf5K .marker.cross{stroke:#333333;}#mermaid-svg-EwBHeXA8vDEOQf5K svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EwBHeXA8vDEOQf5K p{margin:0;}#mermaid-svg-EwBHeXA8vDEOQf5K .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster-label text{fill:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster-label span{color:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster-label span p{background-color:transparent;}#mermaid-svg-EwBHeXA8vDEOQf5K .label text,#mermaid-svg-EwBHeXA8vDEOQf5K span{fill:#333;color:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K .node rect,#mermaid-svg-EwBHeXA8vDEOQf5K .node circle,#mermaid-svg-EwBHeXA8vDEOQf5K .node ellipse,#mermaid-svg-EwBHeXA8vDEOQf5K .node polygon,#mermaid-svg-EwBHeXA8vDEOQf5K .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EwBHeXA8vDEOQf5K .rough-node .label text,#mermaid-svg-EwBHeXA8vDEOQf5K .node .label text,#mermaid-svg-EwBHeXA8vDEOQf5K .image-shape .label,#mermaid-svg-EwBHeXA8vDEOQf5K .icon-shape .label{text-anchor:middle;}#mermaid-svg-EwBHeXA8vDEOQf5K .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EwBHeXA8vDEOQf5K .rough-node .label,#mermaid-svg-EwBHeXA8vDEOQf5K .node .label,#mermaid-svg-EwBHeXA8vDEOQf5K .image-shape .label,#mermaid-svg-EwBHeXA8vDEOQf5K .icon-shape .label{text-align:center;}#mermaid-svg-EwBHeXA8vDEOQf5K .node.clickable{cursor:pointer;}#mermaid-svg-EwBHeXA8vDEOQf5K .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EwBHeXA8vDEOQf5K .arrowheadPath{fill:#333333;}#mermaid-svg-EwBHeXA8vDEOQf5K .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EwBHeXA8vDEOQf5K .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EwBHeXA8vDEOQf5K .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EwBHeXA8vDEOQf5K .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EwBHeXA8vDEOQf5K .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EwBHeXA8vDEOQf5K .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster text{fill:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K .cluster span{color:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K 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-EwBHeXA8vDEOQf5K .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EwBHeXA8vDEOQf5K rect.text{fill:none;stroke-width:0;}#mermaid-svg-EwBHeXA8vDEOQf5K .icon-shape,#mermaid-svg-EwBHeXA8vDEOQf5K .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EwBHeXA8vDEOQf5K .icon-shape p,#mermaid-svg-EwBHeXA8vDEOQf5K .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EwBHeXA8vDEOQf5K .icon-shape .label rect,#mermaid-svg-EwBHeXA8vDEOQf5K .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EwBHeXA8vDEOQf5K .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EwBHeXA8vDEOQf5K .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EwBHeXA8vDEOQf5K :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
'用户叫小明
喜欢川菜'
Mem0
提取事实
已有类似?
更新/合并
存入向量库
Mem0的局限
免费版有调用次数限制 ,生产环境要付费。而且它对中文支持有时候不太准------提取关键事实时偶尔会漏掉一些信息。
生产建议:免费版用来做原型和小流量产品,大流量上付费版或者自建。
本章的坑
-
向量数据库不是万能的。 它的检索是基于"语义相似度",不是"绝对正确" 。有时候语义相近但事实相反的文本也会被检索出来,模型会照单全收然后答错。关键事实要人工校验。
-
Embedding模型选错,效果会差很多。 不同语言、不同领域要用不同的Embedding模型。中文场景推荐用:
text-embedding-v3(阿里通义)bge-large-zh(BAAI开源)- 不要用英文模型处理中文------降维打击
-
文档切分粒度是个大坑。 太粗(一整篇文章作为一个chunk)→ 检索不准;太细(每句话一个chunk)→ 丢上下文。经验值:500字左右为一个chunk,重叠50字。
-
Mem0的免费版有调用次数限制。 跑Demo够用,生产环境要付费或者自建。
-
不要把所有对话都存进长期记忆。 重要性低的对话(比如"你吃饭了吗?")会污染记忆库。至少做简单的过滤------比如只在用户说出关键信息时才存。
-
"重要性打分"是主观的。 让LLM评估一条记忆"重不重要"有时候不靠谱。同样的事,不同prompt、不同模型,评估结果都不一样。生产环境可以加规则做硬过滤。
-
上下文窗口不是越大越好。 GPT-4.1的128k tokens看着多,但长上下文模型更贵、更慢、还有"Lost in the Middle"问题 。该用向量库就老老实实用,别硬塞。
-
记忆会过期。 用户的偏好会变(以前喜欢川菜,现在不爱了)。记忆要有"遗忘"机制------比如超过6个月没被检索过的记忆自动降低权重。
本章配套论文
-
MemGPT (UC Berkeley, Packer et al., 2023):把操作系统的虚拟内存管理搬进LLM,突破上下文窗口限制。Letta项目(30k+⭐)就是这个论文的开源实现。
-
Generative Agents (Stanford, Park et al., 2023):25个AI在虚拟小镇生活,提出"记忆流+反思+规划"三大机制,证明了带记忆+反思+规划的Agent能涌现出复杂行为。
📌 怎么读这两篇? 重点看Introduction和Method,别一上来啃Related Work。MemGPT的"分层内存"设计和Generative Agents的"重要性打分"是核心,其他都是工程实现。
实战作业
挑一个做完,做完发评论区我给你看:
作业1:给第4章的客服Agent加记忆功能
要求:
- 用户告诉Agent自己的订单偏好(比如"我的快递一般都放快递柜"),Agent要记住
- 下次用户问"我的快递怎么处理"时,Agent能调用之前的记忆
作业2:搭建一个私人知识库Agent
要求:
- 准备5-10个文档(txt/markdown/pdf都行)
- 用ChromaDB存成向量
- 写一个Agent,能基于这些文档回答问题
作业3:跑一遍Generative Agents的开源实现
GitHub搜generative-agents,有官方复现的项目(5k+⭐)。跑起来看看25个AI自己生活是什么样子。
下一章预告
第6章我们进入Agent最核心的"思考"能力:规划与推理------Agent的思考方式。
你会学到:
- ReAct:让Agent边想边做(所有Agent框架的祖宗)
- CoT / ToT:让模型"一步一步想"
- AutoGPT的规划模块源码拆解
- Plan-and-Solve:先想好再做
这些是Agent的"脑子怎么转"的核心机制。掌握了这章,你才算真正理解了Agent的"智能"从哪里来。
下一章我们一起揭开Agent思考的秘密。