代码讲解.md 3.5 KB

S09 Memory 代码讲解

这一节只讲相对 S08 新增的内容:

让 Agent 把用户偏好、项目事实和历史反馈保存下来,并在下一次对话中重新加载。


1. 本节新增内容

  • .memory/:记忆文件目录。
  • MEMORY.md:记忆索引。
  • write_memory_file():写入单条记忆。
  • _rebuild_index():重建记忆索引。
  • list_memory_files():读取所有记忆及其元数据。
  • select_relevant_memories():从记忆列表中挑选相关记忆。
  • load_memories():把相关记忆注入当前上下文。
  • extract_memories():从最近对话中提取新记忆。
  • consolidate_memories():定期合并、去重、删除过期记忆。

2. 记忆目录结构

.memory/
  MEMORY.md
  user-style.md
  project-facts.md
  feedback-tabs.md

MEMORY.md 是索引,里面只放简短描述。

每个单独的记忆文件存完整内容。


3. 单条记忆的数据结构

一个记忆文件是 Markdown + YAML frontmatter:

---
name: user-style
description: 用户喜欢中文解释,代码注释要适合教学
type: user
---

用户偏好:
- 回答用中文
- 代码讲解要适合基础较弱的学生

程序读进来后,会变成字典:

{
    "filename": "user-style.md",
    "name": "user-style",
    "description": "用户喜欢中文解释,代码注释要适合教学",
    "type": "user",
    "body": "用户偏好:..."
}

4. write_memory_file()

作用:把一条记忆写成一个独立 .md 文件。

输入参数:

name: str
mem_type: str
description: str
body: str

写完后调用:

_rebuild_index()

这样 MEMORY.md 会同步更新。


5. _rebuild_index()

作用:扫描 .memory/ 里所有记忆文件,重新生成索引。

索引内容类似:

- [user-style](user-style.md) — 用户喜欢中文解释
- [project-facts](project-facts.md) — 当前项目是 Coding Agent 教学项目

System Prompt 里只放这个索引,而不是每次都塞完整记忆。


6. select_relevant_memories(messages)

作用:根据最近几轮用户输入,从记忆目录里挑选相关文件。

流程:

读取所有记忆文件元数据
提取最近 3 条用户消息
构建 memory catalog
让 LLM 返回相关记忆的下标数组
如果 LLM 失败,用关键词匹配兜底

LLM 期望返回:

[0, 3]

代表选择第 0 条和第 3 条记忆。


7. load_memories(messages)

作用:把选中的记忆文件完整内容拼成一段文本:

<relevant_memories>
...记忆 1...

...记忆 2...
</relevant_memories>

然后在当前用户消息前注入,让模型这轮能读到相关历史。


8. extract_memories(messages)

作用:从最近对话中提取新的长期信息。

它会让模型返回 JSON 数组:

[
    {
        "name": "user-prefers-short-docs",
        "type": "user",
        "description": "用户喜欢短而清晰的讲义",
        "body": "..."
    }
]

如果没有新记忆,就返回:

[]

9. consolidate_memories()

当记忆文件太多时,会触发整理:

合并重复记忆
删除过期记忆
保留重要偏好
控制总数量

这类似 Agent 的“睡眠整理”或 “Dream” 机制。


10. 本节课堂重点

Memory 不是把所有历史都永久塞进上下文。

更合理的结构是:

索引常驻 System
相关记忆按需注入
新信息轮后提取
记忆过多时合并整理