1. 如何设计一个高效的 Agent 上下文维护方案?
参考口述答案:
核心思路是分层管理。我会把上下文分成三层:
- 最上面是固定信息,比如系统角色、安全规则,一直放在 system prompt 里不变。
- 中间是近期对话,保持完整原文,保证多轮连贯。
- 更早的历史则定期让模型自己做摘要,用一两句话替换掉原始大段对话。
除此之外,真正重要的跨对话知识(比如用户偏好)会存到向量数据库,新会话开始时按需检索再注入上下文。这样既省 token,又不丢关键信息,很多框架比如 LangChain 的 ConversationSummaryBufferMemory 就是这个思路。
messages = [
{"role": "system", "content": "你是专业助手,偏好表格回答。"},
{"role": "user", "content": "[历史摘要] 前面聊了 Python 性能优化。"},
{"role": "user", "content": "那具体怎么用 cProfile?"},
{"role": "assistant", "content": "你可以这样导入..."},
]
### Token 超限时,把旧消息压缩为摘要
if token_count(messages) > 6000:
old = messages[1:6] # 跳过 system,取旧消息
summary = llm.summarize(old)
messages = [messages[0]] + [
{"role": "user", "content": f"[历史摘要] {summary}"}
] + messages[6:]
2. 主流模型上下文长度
参考口述答案:
目前 GPT-4 o、GPT-4 Turbo 一般是 128 k token,Claude 3 系列 200 k,谷歌 Gemini 1.5 Pro 可以到 100 万甚至 200 万 token。国内 Kimi 主打 200 万字上下文,通义千问有 100 万 token 版本,DeepSeek-V 2 是 128 k。
虽然窗口越来越大,但有效注意力在中后段会衰减,而且长文本调用又贵又慢,所以上下文管理仍然是工程里的刚需。
3. 讲一下 Agent 中的“长短期记忆”
参考口述答案:
可以类比人:
- 短期记忆就是当前对话窗口里的全部交互历史,存在内存或 Redis 里,会话结束就可丢弃。
- 长期记忆是跨会话持久化的,通常存向量库或关系数据库。下次新对话时,根据当前问题去检索相关记忆,再拼进上下文。
所以短期记忆解决“这次聊得连贯”,长期记忆解决“下次见你还记得你”。
### 存储
memory_store.add(
user_id="u1",
content="用户喜欢表格回答",
embedding=embed("用户喜欢表格回答"),
)
### 检索
query_emb = embed("怎么展示数据")
results = memory_store.search(user_id="u1", embedding=query_emb, top_k=3)
system_prompt += "\n已知用户偏好:" + results[0].content
4. 什么样的信息应该放在长期记忆,什么样的信息放在短期记忆?
参考口述答案:
- 短期记忆放当前任务强相关的即时信息:用户刚问的问题、工具返回结果、中间推理步骤、临时状态。
- 长期记忆放跨对话还有价值的东西:用户画像(喜好、身份)、历史任务总结、经验教训、用户主动告知的事实(如公司名、deadline)。
判断标准很简单:如果下次新对话时你还得知道这些,就应该进长期记忆。
5. 长期记忆与短期记忆的压缩方案
参考口述答案:
短期记忆压缩,常用摘要+滑动窗口:每隔 N 轮让模型把前一段对话总结成简短摘要,替换掉原始长消息;或者只保留最近 K 轮完整消息,更早的用一句话概括。
长期记忆压缩,更多靠结构化和去重:存的时候只保留核心信息和摘要;后台定期聚类去重,合并相似记忆,淘汰低价值信息。
6. 长期记忆需要保存的核心内容
参考口述答案:
我会重点保存这几类:
- 用户画像:身份、偏好、习惯、技能栈。
- 任务成果:完成过的目标、产出的文件、重要结论。
- 反思与教训:从失败中总结的经验。
- 用户明确告知的事实:比如服务器地址、项目节点。
存的时候一定会带上时间戳、重要性评分和类型标签,方便后续检索和过期清理。
memory_entry = {
"id": "mem_001",
"user_id": "u1",
"type": "preference", # preference / fact / lesson
"content": "用户要求代码示例用 Python",
"importance": 0.9,
"created_at": "2026-07-17T10:00:00Z",
}
vector_db.upsert(memory_entry)
7. 如果要进行记忆压缩,通常有哪些方法?
参考口述答案:
常见方法有:
- LLM 摘要法:让模型把长文总结成几句。
- 关键信息提取法:抽取人物、事件、决策等结构化字段。
- 滑动窗口法:只保留最近 N 条完整消息,其余用摘要。
- 聚类去重法:把嵌入相近的记忆归为一类,只保留最有代表性的一条。
- 遗忘曲线法:按重要性+最近访问时间打分,低分自动淘汰。实际系统一般组合使用,比如“摘要 + 滑动窗口 + 重要性过滤”。
8. 长期记忆的压缩触发条件是什么?是基于 Token 阈值还是基于语义重要性?
参考口述答案:
我会采用混合策略:
- Token 阈值是硬底线:当上下文使用率达到 70%-80% 时,强制压缩短期记忆防止溢出。
- 语义重要性是质量过滤:存储时就打分,只有重要性超过阈值的才存;记忆库超量时优先淘汰低分记忆。另外还会设时间触发,比如每天定时整理记忆库,合并重复、清理失效信息。阈值保底,重要性过滤,两者互补。
9. 当对话轮数很多,上下文窗口不足时,有哪些处理策略?
参考口述答案:
我会按优先级用这几招:
- 滑动窗口 + 摘要:保留最近几轮完整对话,更早的用摘要替代。
- 向量检索召回:把历史存进向量库,每轮只根据当前问题检索最相关的几句,不全量携带。
- 阶段性主动总结:任务阶段切换时,生成进度总结,然后重置上下文,只带总结继续。
- 分层处理:近期用原文,中期用摘要,远期靠检索。
- 小模型压缩:用便宜模型先做摘要,大模型读压缩版。
def compress_context(messages, keep_recent=6):
if len(messages) <= keep_recent:
return messages
to_summarize = messages[:-keep_recent]
summary = llm.invoke("总结以下对话要点:" + str(to_summarize))
return [
{"role": "system", "content": f"[历史摘要] {summary}"}
] + messages[-keep_recent:]
10. 如果用户的 Prompt 特别长,导致上下文窗口溢出,除了截断,你有哪些简化上下文的策略?
参考口述答案:
直接截断太粗糙,我会用这几个方式:
- 摘要预处理:先用小模型把长 Prompt 压缩成结构化摘要,Agent 基于摘要工作。
- 分块处理:把长文本切成几块分别提取关键信息,汇总后再放上下文。
- 外部文件模式:长文本先存成文件,只把摘要和文件 ID 放上下文,需要细节时调“读文件”工具。
- RAG 式检索:提前给长文本建好向量索引,只把最相关的片段放进上下文。
核心思路就是把长文本变成可检索的外部知识,而不是全塞窗口。
11. 多 Agent/多异步任务下,如何防止上下文污染?
参考口述答案:
防止污染关键是隔离。
- 会话级隔离:每个 Agent 或任务有独立的 messages 列表,绝不共享。
- 消息总线通信:Agent 之间通过结构化消息传递结果,不直接拼接聊天记录。
- 记忆库分区:长期记忆按用户 ID 或 Agent ID 做命名空间隔离。
- 来源标注:引用其他 Agent 信息时,明确标记“据 Agent-A 反馈…”,避免模型误以为是自己经历。
这样能从根本上避免信息串扰和幻觉扩散。
12. Agent 是怎么实现上下文记忆的?
参考口述答案:
大模型本身是无状态的,记忆全靠工程层维护。
简单说就是维护一个 messages 列表,每次请求把整个列表带上,模型就能“记得”之前说过什么。
长期记忆则是另一套:在对话开始时或需要时,从外部数据库检索与该用户相关的历史信息,注入到系统提示或消息列表开头。
本质就是:短期记忆靠“消息历史拼接”,长期记忆靠“外部检索+注入”。
13. 上下文管理是怎么做的,如何进行记忆?
参考口述答案:
我会做一个上下文管理器模块,负责:
- 维护当前会话消息列表。
- 监听长度,超阈值时生成摘要替换旧消息。
- 识别并提取重要信息,异步写入长期记忆库。
- 新会话初始化时,根据用户 ID 从长期记忆库检索相关记忆,拼入系统提示。
这样就形成了一个“感知 → 存储 → 检索 → 注入”的完整闭环。
14. 如何构建工具实现 memory 记忆,让大模型在长期对话中学习用户习惯?
参考口述答案:
我会给 Agent 配置一套记忆管理工具,比如 remember_info、recall_info、forget_info。
在系统提示里明确告诉模型:“当你发现用户说了以后可能需要的信息,请调 remember 存下来;回答前可以先调 recall 查看相关画像。”
这样模型就能在对话中自发学会并记住用户习惯,下次自动应用。
tools = [
{
"name": "remember_info",
"description": "存储一条需要长期记忆的信息",
"parameters": {
"content": "string", # 要记住的内容
"category": "preference / fact / lesson",
},
},
{
"name": "recall_info",
"description": "根据关键词检索相关记忆",
"parameters": {"query": "string"},
},
]
15. 对 Cursor 记忆管理机制的了解
参考口述答案:
Cursor 的记忆管理和聊天 Agent 不太一样,它更偏向项目级静态上下文。
主要通过 .cursorrules 文件存储编码规范、项目约定、常用指令,每次 AI 请求都会带上。同时它会自动索引项目代码,生成向量嵌入,当你提问时检索相关代码片段。
最近版本也加了全局 Memory 设置,能记住一些全局偏好,比如默认语言、代码风格。
核心是“规则 + 代码索引”,而不是动态的长短期对话记忆。
16. Memory 上下文记忆功能的处理逻辑
参考口述答案:
整体处理逻辑是一个循环:
- 存储:对话中识别到重要信息,生成记忆条目,计算嵌入,存入向量库。
- 检索:新会话开始或需要时,用当前意图做查询,搜索相关记忆。
- 注入:将检索到的记忆拼接进上下文。
- 维护:后台定期清理过时、低价值或矛盾记忆。
这个闭环跑通后,Agent 就能表现出不错的“记性”。
17. 如何进行记忆管理,怎么处理长上下文,怎么进行持久化,后续怎么读取和关联?
参考口述答案:
我会这样设计:
- 短期上下文用 Redis 存消息列表,带会话 ID 和过期时间,读写极快。
- 长上下文处理:超长时做摘要,保留近期完整消息,远期用摘要替代,仍放短期存储。
- 长期记忆持久化:向量库存嵌入,关系库存元数据(用户 ID、时间、类型)。
- 读取和关联:短期直接用会话 ID 取;长期用用户 ID + 问题嵌入做向量检索,按相似度和时间排序取 Top N 注入。
### 持久化长期记忆
def save_long_term(user_id, content, embedding):
db.insert(
"memories",
{"user_id": user_id, "content": content, "embedding": embedding},
)
### 读取
def load_relevant_memories(user_id, query_emb, top_k=5):
all_mems = db.query(
"SELECT * FROM memories WHERE user_id=?",
user_id,
)
scored = sorted(
all_mems,
key=lambda m: cosine_sim(query_emb, m.embedding),
reverse=True,
)
return scored[:top_k]
18. 你的向量记忆库是如何更新用户画像的?如何区分短期记忆和长期记忆?
参考口述答案:
画像更新我分两条线:
- 实时小更新:当识别到画像类信息,直接增/改对应的画像记忆条目。
- 定时大聚合:后台任务定期对同一用户的所有记忆做聚类和总结,提炼成一份精炼的“用户画像文档”。
区分短期和长期记忆很简单:短期记忆就是消息列表里的内容,存在 Redis,不向量化;长期记忆一定进向量库并标记 type: long_term,生命周期完全不同。
19. 记忆更新时能否精准替换指定片段,还是需要全量清空重建?
参考口述答案:
完全可以精准替换,不需要全量重建。
给每条记忆分配唯一 ID,更新时带上 ID 和新内容,后端找到对应记录,修改内容和嵌入向量,向量数据库大多支持 upsert 操作。
全量重建只在极少数情况使用,比如索引结构改变或出现严重逻辑冲突需要重新梳理时。
20. 存储时如果出现前后不一致的情况如何解决?
参考口述答案:
矛盾有两种,处理方式不同:
- 随时间更新(如“用 Python”→“用 Go”):以时间戳为准,新覆盖旧,因为用户偏好可能改变。
- 逻辑直接冲突(如同时存“喜欢详细”和“喜欢简洁”):检索时把矛盾两条都提示给模型,让模型反问用户确认。
每条记忆加版本号和时间,冲突时保留历史版本但标记失效,做到可追溯。
21. 多轮对话的实现方案
参考口述答案:
多轮对话本质就是把历史消息带回去。大模型无状态,所以我们维护一个 messages 数组,按 user/assistant 交替存储,每次请求全量发送。
持久化方面,把数组存到 Redis 或数据库,用户下次回来加载出来就能无缝续聊。
再配合上下文压缩和长期记忆机制,就能支撑超长多轮对话而不会爆窗口或丢失重要信息。
session = load_session(user_id) # 从 Redis/DB 恢复
messages = session["messages"]
user_input = "帮我看看这个报错"
messages.append({"role": "user", "content": user_input})
response = llm.chat(messages)
messages.append({"role": "assistant", "content": response})
save_session(user_id, messages)
作者:爱吃肉的棒男孩 1
链接:https://www.nowcoder.com/
来源:牛客网
短期记忆 vs 长期记忆如何配合
核心思路
- 短期记忆(Working Memory):当前任务上下文(对话历史、当前计划、工具调用结果)
- 长期记忆(Long-term Memory):跨任务沉淀(用户偏好、知识库、历史经验)
协作方式
分层设计
- 短期记忆:放在 prompt / state(如 LangGraph state)
- 长期记忆:放在向量数据库(如 FAISS / Milvus / Chromadb)
工作流程
- 用户输入 → 触发任务
- 从长期记忆中 检索相关信息(RAG)
- 注入到短期记忆(prompt)
- 推理 + 工具调用
- 重要信息写回长期记忆(可筛选)
工程关键点
- 长期记忆不是全存,而是:
- 用户偏好
- 成功案例(few-shot)
- 高价值知识
- 短期记忆要控制长度(token budget)
来源拆分自:高德 Agent 研发面,记忆和评测问很细;以下保留原整理中的工程补充与校正。
如何设计 Agent 的记忆写入机制?
视频要点:旁路提取,而不是把所有对话都存进向量库
主对话模型继续服务用户,后台挂一个较便宜的小模型做异步记忆提取。视频以 8B 小模型为例,让它承担实体提取、分类和价值判断,从而降低主链路延迟与成本。
记忆是否准入,按三个维度判断:
| 维度 | 要问的问题 | 处理示例 |
|---|---|---|
| 持久性价值 | 下周或下次会话还能用到吗? | “下周三去北京出差”应持久化;“刚才很小声”只进短期上下文或直接丢弃 |
| 结构化程度 | 是自由文本,还是明确的实体、属性和关系? | “我和张三是同事”应抽成实体关系;普通对话可保留为文本记忆 |
| 个性化价值 | 能否帮助系统更懂用户? | 反复要求“说人话、别啰嗦”可归纳为表达偏好,而不是机械保存每句原话 |
存储层按查询模式分工:
- 向量库:保存可语义检索的文本、事件摘要和历史经验。
- 图数据库 / GraphRAG:保存实体关系,支持关系约束和多跳查询。
- 关系库或结构化 Profile:保存需要精确读写、去重、版本控制的事实与用户画像。
- 冷日志:保留低频事件,设置 TTL 或衰减规则,不占用高成本热存储。
写入后还需要生命周期管理:
- 按重要性、时效性、使用频率和置信度评分。
- 合并重复记忆,发现新旧冲突时保留来源与版本,而不是简单覆盖。
- 定期做 Reflection:把一周内的零散事件提炼为更高层洞察。
- 对日志做衰减或归档;核心画像长期保存,但必须支持用户更正和删除。
flowchart LR
A["用户对话"] --> B["旁路小模型:提取与分类"]
B --> C{"持久性 × 结构化 × 个性化"}
C -->|自由文本与经验| D["向量库"]
C -->|实体与关系| E["图数据库"]
C -->|精确事实与画像| F["关系库 / Profile"]
D --> G["评分、去重、衰减与反思"]
E --> G
F --> G
G --> H["按当前任务检索并注入上下文"]
可直接口述的回答
我不会把所有对话直接写入向量库,而是用旁路小模型做异步提取,先按持久性、结构化程度和个性化价值做准入筛选。自由文本与经验进入向量库,实体关系进入图存储,需要精确更新的用户画像进入结构化数据库。写入后再做重要性评分、去重、冲突处理、冷热分层和定期反思;召回时按任务类型路由,并保留来源、时间和置信度,避免过期或错误记忆污染后续决策。
补充与校正
- “长期记忆”不等于“向量数据库”。更完整的分类是语义记忆(事实)、情景记忆(过去经验)和程序性记忆(规则与行为方式);它们的写入、更新和召回策略应不同。CoALA 论文、LangMem 官方概念文档
- GraphRAG 适合实体关系丰富、多跳推理或全局主题分析,但索引成本更高。微软官方文档估计,标准 GraphRAG 中图抽取约占索引成本的 75%,所以不能默认所有记忆都建图。GraphRAG 索引方法
- Reflection 只能基于可追溯证据做合并和归纳,不能把模型猜测直接升级为“用户事实”。敏感信息还要有最小化收集、授权、删除和审计机制。
相关笔记
- 智能体记忆系统 — 完整工程设计
- 智能体记忆研究脉络 — 方法演进与论文
- 记忆安全与隐私 — 投毒、泄漏与删除治理
- 上下文与记忆 MOC