这一节只讲相对 S08 新增的内容:
让 Agent 把用户偏好、项目事实和历史反馈保存下来,并在下一次对话中重新加载。
.memory/:记忆文件目录。MEMORY.md:记忆索引。write_memory_file():写入单条记忆。_rebuild_index():重建记忆索引。list_memory_files():读取所有记忆及其元数据。select_relevant_memories():从记忆列表中挑选相关记忆。load_memories():把相关记忆注入当前上下文。extract_memories():从最近对话中提取新记忆。consolidate_memories():定期合并、去重、删除过期记忆。.memory/
MEMORY.md
user-style.md
project-facts.md
feedback-tabs.md
MEMORY.md 是索引,里面只放简短描述。
每个单独的记忆文件存完整内容。
一个记忆文件是 Markdown + YAML frontmatter:
---
name: user-style
description: 用户喜欢中文解释,代码注释要适合教学
type: user
---
用户偏好:
- 回答用中文
- 代码讲解要适合基础较弱的学生
程序读进来后,会变成字典:
{
"filename": "user-style.md",
"name": "user-style",
"description": "用户喜欢中文解释,代码注释要适合教学",
"type": "user",
"body": "用户偏好:..."
}
write_memory_file()作用:把一条记忆写成一个独立 .md 文件。
输入参数:
name: str
mem_type: str
description: str
body: str
写完后调用:
_rebuild_index()
这样 MEMORY.md 会同步更新。
_rebuild_index()作用:扫描 .memory/ 里所有记忆文件,重新生成索引。
索引内容类似:
- [user-style](user-style.md) — 用户喜欢中文解释
- [project-facts](project-facts.md) — 当前项目是 Coding Agent 教学项目
System Prompt 里只放这个索引,而不是每次都塞完整记忆。
select_relevant_memories(messages)作用:根据最近几轮用户输入,从记忆目录里挑选相关文件。
流程:
读取所有记忆文件元数据
提取最近 3 条用户消息
构建 memory catalog
让 LLM 返回相关记忆的下标数组
如果 LLM 失败,用关键词匹配兜底
LLM 期望返回:
[0, 3]
代表选择第 0 条和第 3 条记忆。
load_memories(messages)作用:把选中的记忆文件完整内容拼成一段文本:
<relevant_memories>
...记忆 1...
...记忆 2...
</relevant_memories>
然后在当前用户消息前注入,让模型这轮能读到相关历史。
extract_memories(messages)作用:从最近对话中提取新的长期信息。
它会让模型返回 JSON 数组:
[
{
"name": "user-prefers-short-docs",
"type": "user",
"description": "用户喜欢短而清晰的讲义",
"body": "..."
}
]
如果没有新记忆,就返回:
[]
consolidate_memories()当记忆文件太多时,会触发整理:
合并重复记忆
删除过期记忆
保留重要偏好
控制总数量
这类似 Agent 的“睡眠整理”或 “Dream” 机制。
Memory 不是把所有历史都永久塞进上下文。
更合理的结构是:
索引常驻 System
相关记忆按需注入
新信息轮后提取
记忆过多时合并整理