← 返回资讯
林远舟
技术编辑
已审核

滑动窗口丢上下文,向量召回劝退,混用才是AI记忆的正解

上周我的 AI 助手在第 12 轮对话时突然问我:“对了,你刚才说的那个 Bug 是用什么框架来着?”——那一刻我意识到,这家伙的记性比我还差。

滑动窗口丢上下文,向量召回劝退,混用才是AI记忆的正解

滑动窗口丢上下文,向量召回劝退,混用才是AI记忆的正解


你的 AI Agent 记性差?聊聊短期记忆管理的三种方案

上周我的 AI 助手在第 12 轮对话时突然问我:“对了,你刚才说的那个 Bug 是用什么框架来着?”——那一刻我意识到,这家伙的记性比我还差。

好吧,可能跟我连续写了 6 小时代码也有关系。

今天聊聊这个让无数开发者抓狂的问题:怎么让 AI Agent 在长对话里记住事儿,又不把 Token 烧光。我踩过不少坑,总结出三种方案。不一定都对,但至少能让你少走点弯路。


先说结论

嗯...这个我后面细说。


为什么短期记忆是个大问题?

想象一下这个场景。

你在用 AI Agent 调试一个分布式系统的 Bug。前 20 轮对话你告诉它:系统架构、报错日志、你试过的三个方案、为什么都不行...然后到第 21 轮,它开始胡言乱语。

不是它笨。

是它的“工作记忆”爆了。

以 GPT-4 为例,128K 上下文看着挺大对吧?但实际跑起来,一个稍微复杂的 Agent 任务——比如代码审查 + 多轮推理 + 调用几个工具——轻松吃掉 30K-50K Token。我测过,GPT-4-turbo 在 2024 年 4 月那版,跑一个带工具调用的 debugging 任务,平均消耗 42K Token。

不做记忆管理的话,就两条路:丢信息,或者烧预算。

我去年 9 月做一个客服 Agent 项目,用的是当时最新的 gpt-4-0125-preview。上线第一天,客户就怼过来:“你们的 AI 怎么跟金鱼一样,7 秒记忆?”——原话。我当时那个脸啊...


方案一:滑动窗口——简单但不傻

思路简单到爆:只保留最近 N 轮对话,旧的直接扔掉。

PYTHON
class SlidingWindowMemory:
 def __init__(self, max_turns=10):
 self.max_turns = max_turns
 self.messages = []
 
 def add_message(self, role, content):
 self.messages.append({"role": role, "content": content})
 # 超过窗口大小就截断
 if len(self.messages) > self.max_turns * 2:
 self.messages = self.messages[-(self.max_turns * 2):]
 
 def get_context(self):
 return self.messages

实际体验

我在一个内部工具里用了这个方案,窗口设的 8 轮。

效果嘛...有好有坏。

等等,这里我要更正一下——上面说“10 行代码”其实不太准。如果你要处理 system prompt、要区分 user 和 assistant 消息的角色标记,实际得 30 行左右。我上面那个代码是简化版的。

适合什么场景?

任务明确、不需要长期上下文的。比如单次代码生成、翻译、或者就聊两句就结束的那种。如果你的 Agent 需要“记住用户是谁”,光靠这个不够。

我一般拿它当兜底方案。


方案二:摘要压缩——把历史“蒸馏”一下

这个思路是:用 LLM 把历史对话压成一段摘要,只留关键信息。

PYTHON
class SummaryMemory:
 def __init__(self, llm_client):
 self.llm = llm_client
 self.summary = ""
 self.recent_messages = []
 
 def compress_history(self, messages):
 prompt = f"""
 将以下对话历史压缩为关键摘要,保留:
 - 用户的核心需求
 - 已做出的决策
 - 重要的技术细节
 
 对话:
 {json.dumps(messages, ensure_ascii=False)}
 """
 self.summary = self.llm.complete(prompt)
 self.recent_messages = []

我踩过的坑

去年 11 月,我尝试用摘要压缩做个“长期陪伴型”学习助手。想法很美:每次学习要点压缩一下,下次对话时注入摘要。

结果呢?

翻车翻得很彻底。我喝了三杯咖啡才搞明白问题在哪:

1. 细节丢失严重。用户说“我喜欢用 VS Code 的 Vim 插件,keybinding 改成了 Ctrl+J”,压缩后变成“用户使用 VS Code”——Vim 插件和自定义 keybinding 全丢了。这就导致后续对话里,Agent 推荐快捷键时完全不考虑用户的肌肉记忆。

2. 压缩成本不低。每次压缩都要额外调一次 LLM。我用的是 Claude 3 Haiku 做压缩(便宜),但如果频繁压缩,一个月下来也多了 200 多刀。

3. 错误累积很可怕。这是最让我头疼的。如果摘要本身有偏差——比如把“用户在考虑用 Redis”压缩成“用户已使用 Redis”——后续对话会在错误的基础上继续,越跑越偏。我遇到过连续 5 轮都在讨论一个不存在的 Redis 配置,用户最后直接打了“???”。

一个意外的补救方案

后来我改成分层摘要。

把“用户画像”(长期不变的偏好、习惯、技术栈)和“任务上下文”(当前这次任务的目标、进展)分开压缩。用户画像压缩一次管很久,任务上下文每次任务结束再压缩。

效果提升了,但工程复杂度直接翻倍。我跟同事吐槽说:“这玩意儿维护起来比我前女友的情绪还复杂。”


方案三:向量召回——需要的时候再找

向量召回不压缩也不丢弃,而是把所有历史存进向量数据库,需要的时候检索最相关的片段。

PYTHON
class VectorMemory:
 def __init__(self, vector_store):
 self.store = vector_store
 
 def add_interaction(self, user_msg, assistant_msg):
 doc = f"User: {user_msg}\nAssistant: {assistant_msg}"
 embedding = get_embedding(doc)
 self.store.insert(embedding, doc)
 
 def retrieve_context(self, query, top_k=5):
 query_embedding = get_embedding(query)
 results = self.store.search(query_embedding, top_k)
 return "\n".join(results)

一个让我凌晨 3 点被叫醒的案例

三个月前,2024 年 12 月,我在做一个代码审查 Agent。用户可能随时提到“上次那个 PR 里的 SQL 注入问题”。用滑动窗口肯定不行——可能已经是 50 轮之前的事了。用摘要也不行——摘要不会保留具体代码细节。

向量召回看起来是完美方案。

我用的是 ChromaDB + text-embedding-3-small。上线第一周,凌晨 3:07,PagerDuty 响了。

出了什么问题?

用户说“那个 SQL 的问题”,向量检索返回了所有包含“SQL”的对话片段。12 个历史片段里有 8 个跟当前问题完全不相关——用户之前讨论过 SQL 优化、SQL 索引、甚至一个 SQL 相关的烂梗。但 Agent 不知道“那个”指的是哪个,直接返回了一堆无关信息。

还有一个更隐蔽的问题:召回的相关性严重依赖 embedding 模型质量。text-embedding-3-small 在处理技术术语时,会把“SQL injection”和“SQL optimization”当成相似度 0.85 的东西——据我了解,这是因为它对专业术语的语义区分不够细。

我的补救方案

现在这个系统终于稳定了,召回准确率大概在 87% 左右。但说实话,调参调得我想转行卖咖啡。


到底该怎么选?

我现在都是组合拳,根据场景搭配:

| 场景 | 推荐方案 | 原因 |

|------|---------|------|

| 简单问答 / 单次任务 | 滑动窗口 | 够用、省事 |

| 长期用户画像 | 摘要压缩 | 信息密度高 |

| 知识密集型任务 | 向量召回 | 精准检索 |

| 复杂 Agent 系统 | 三者结合 | 各取所长 |

我现在的实战配方

CODE
滑动窗口(最近 8 轮,保底)
+ 摘要压缩(每 20 轮压一次,用便宜的 Haiku 做)
+ 向量召回(存在 ChromaDB,检索 top 5)
= 成本可控,记忆不丢

Token 消耗大概上涨了 15%,但用户满意度从 3.2 涨到了 4.5。我觉得值。


最后想说的

做记忆管理这事儿,没有银弹。

我花了半年时间在各种方案之间反复横跳,LangChain 的 Memory 模块试了个遍,LlamaIndex 的那套也搞过,最后发现关键是想清楚你的场景——用户在什么情况下会说“上次那个”?你需要在多大范围内保持一致性?

我现在的做法是:先上线最简单的滑动窗口,跑一周看数据。然后根据用户反馈,看哪些信息丢了最要命,再有针对性地加摘要或召回。别一上来就搞大而全的架构,大概率会后悔。

好了,我去续杯咖啡了。最近迷上了云南保山的豆子,做冷萃很不错。

你的 Agent 项目用的什么记忆方案?有没有遇到过“金鱼脑”的尴尬时刻?评论区聊聊,我会认真看每一条。尤其想知道你们在生产环境里是怎么处理这个问题的。


#AI #Agent #LLM #Memory #工程实践

112
3765 阅读
3 评论
分享
链接已复制
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年06月27日 17:32

林远舟

技术编辑

全栈工程师出身,做过 5 年技术社区运营。对 AI 编程工具、开发者生态有深入研究,喜欢用实测数据说话。

读者评论 3

M
创业者Mark 2周前
正在做相关方向,这篇文章给了我不少启发。
回复 点赞 (7)
老李 3天前
有个小问题想请教,文中提到的那个方案在大规模场景下性能怎么样?
回复 点赞 (5)
运营小陈 6天前
转发到团队群了,大家都觉得有参考价值。
回复 点赞 (4)