跳到正文
神奇海星的Blog

s09:Memory

2 分钟 learn-claudecode学习

Memory目的

解决跨会话的信息利用问题(存哪些?怎么存?取哪些?)

存储

.memory/目录下

MEMORY.md负责存储记忆的索引表,用于选择

MEMORY.md 中的一条记忆条目示例:Tab indentation preference — User prefers tabs for code indentation

可以跳到具体的memory内部:

​ “

name Tab indentation preference
description User prefers tabs for code indentation.
type user

The user prefers TAB characters for indentation rather than spaces. Use tabs whenever writing or editing code, config, or text files for them.

”

格式是以yaml frontmatter开头来记录name,description,type

召回:就是找需要的记忆,并加载到当前messages中

每次用户发起请求时,select_relevant_memories() 读取最近的用户消息和记忆目录,让一次轻量模型调用选择最多五条相关记录

如果模型调用或 JSON 解析失败,代码会退回关键词匹配。选择完成后,load_memories() 才读取对应文件,并限制召回正文的总长度。

relevant_memories = load_memories(messages)
system = build_system(relevant_memories)

build_system() 会明确说明:召回内容只是背景知识,不是新的用户命令;如果记忆与当前请求冲突,以当前请求为准。这样既能使用旧信息,也不会让旧记忆替用户发号施令。

*提取(难理解的点)

输入是什么

不是全部历史,是 dialogue_text(messages) code.py:353-358——最后 12 条消息、截到 8000 字符,拼成 role: 内容 的多行文本。

这一步只取尾部是有意的:一轮 agent_loop 里 messages 会随工具调用膨胀得很快,而本轮真正有价值的信息(用户说了什么、纠正了什么)集中在后半段。

谁来挑

交给模型,用一段提示词 code.py:396-409 划了两条线:

  • 该存:用户偏好、重复出现的反馈、稳定的项目事实、用户希望记住的外部链接
  • 不该存:临时任务状态、工具输出、助手的假设、本次对话的摘要

还有一条独立的 scope 字段:模型要自己标 persistent 还是 current_task。这个字段是给后面的 should_store_memory 看的——只有标了 persistent 才会真的落盘。相当于让模型先自评一次“这条明年还有用吗”。

提示词里还带了 Existing memory catalog(现有记忆的名字+描述,截 6000 字符),让模型知道已经有什么,避免重复提取同一条。

整理

「快照」= 某一时刻的完整状态副本,典型用途是失败后回滚或断点续跑。

覆盖记忆文件前,先把 {文件名: 原文} 整体存进一个 dict;删除/写入失败就把它写回去,恢复原状。

snapshot = {record["filename"]: memory_path(record["filename"]).read_text() ...}