目录
- 一、它记住什么,不记什么
- 二、记忆是怎么写进去的
- 1. 每轮结束时的认知结算
- 2. 直接说「记住」
- 3. 改它写的代码
- 三、下一次对话时,记忆怎么用上
- 四、在记忆中心查看和清理
- 五、在设置里控制它记多少
- 六、怎么让它记得更准
- 七、它做不到的地方
- 小结
用 AI 写代码,最烦的一件事是重复交代:这个项目的错误统一用errors.Wrap包一层,接口统一返回{code, msg, data},测试用表驱动。昨天刚说过,今天新开一个对话,又得再说一遍。
WES Code 的做法是:记忆按项目存在本机,每轮对话结束时把这一轮「结算」一次,把偏好、纠正、项目事实留下来,下次对话自动带上。
这篇讲清楚几件事:它会记住什么,什么时候写进去,下次对话怎么用上,怎么查看、清理和关掉它,最后说说它做不到的地方。
一、它记住什么,不记什么
跨对话保留的
关于你和这个代码库的结论,不会因为关掉一个对话就失效。下面这些会跨对话保留:
| 类型 | 例子 |
|---|---|
| 偏好 | 缩进用 tab;回复用中文 |
| 纠正 | 「错误要用 %w 包装,不要直接返回」 |
| 项目事实和约定 | 项目用 PostgreSQL;接口统一返回{code, msg, data} |
| 经验教训 | 这个仓库要先跑make gen再编译 |
| 踩过的 bug 和回归 | 某次改动引起的回归 |
只属于当次对话的
一次对话的上下文快照、某个任务拆出来的计划,只属于那次对话,不会带到别的对话里。
不会记的
- 低置信度的推测:结算时只有高、中置信度的条目才可能被保存
- 一次性的要求:比如「这次先别写测试」
- 敏感信息:密钥、账号这类,不要让它记
二、记忆是怎么写进去的
1. 每轮结束时的认知结算
每轮任务结束后,WES Code 会让对话模型把这一轮「结算」一次,按固定格式输出四样东西。
| 输出 | 内容 | 用在哪 |
|---|---|---|
| 会话状态 | 没做完的请求(保留原话)、做过的操作、关键决定、被否掉的方向、待办 | 这个对话的下一轮 |
| 记忆条目 | 跨对话仍然有用的偏好和事实 | 长期记忆 |
| 反思 | 方法上的经验 | 够格的写进这个助手以后的系统提示词 |
| 纠正和约定 | 你明确表达过的纠正和偏好 | 长期记忆 |
结算要求模型输出的格式是这样的(结算提示词里的示例,原样照搬):
{"session_state":{"pending_task":"用户最近未完成的请求(原文引用,无则 'None')","goal":"整体目标","current_phase":"分析中/实施中/验证中/完成/interrupted","completed_actions":[{"action":"READ store.go:478","result":"发现字节截断 BUG","tool":"read_file"}],"key_decisions":["影响后续的决策"],"rejected_paths":["被否定的方向"],"action_items":["按 docs/plan.md 第 2 节补缓存层","把 parseConfig 的错误往上抛"],"file_states":[{"path":"store.go","status":"modified","summary":"添加了 error handling"}],"open_questions":["未解决问题"],"constraints":["用户声明的约束(原文)"],"plan":null},"memory_entries":[{"content":"用户偏好 4 空格缩进","kind":"preference","scope":"global","confidence":"high"}],"reflections":[{"category":"approach_quality","content":"应该先用 grep 缩小范围再 read","severity":"lesson"}],"learnings":[{"type":"correction","content":"函数命名用 camelCase","action":"persist"}]}提示词里定了几条规矩,决定了它记得少而准:
- 低置信度的不写,只有高、中置信度的才可能被保存
- 一次性的上下文不记,跨对话还有价值的才留
- 宁少勿多:错误的记忆比没有记忆更有害
- 只有你明确说出来的纠正才会保存;它自己推断出来的模式,只当建议
- 对话顺利时,不强行反思
「宁少勿多」这一条,是我最认同的。记错一条偏好,比没记住还麻烦:它会在之后每个相关的对话里,坚持一个你早就不要的写法。
2. 直接说「记住」
想让它马上记下,就直接说:
记住:这个项目的接口统一返回 {code, msg, data},错误码都定义在 internal/errcode 里它会调用记忆工具memory,存成一条记忆。工具收到的参数大致是这样(具体内容由 AI 自己概括):
{"action":"save","kind":"fact","content":"接口统一返回 {code, msg, data},错误码定义在 internal/errcode","tags":["api","convention"]}kind有三种:fact(事实,默认)、preference(偏好)、experience(经验)。内容建议控制在 500 字以内。
比起等一轮结束后的结算,这样更直接。
3. 改它写的代码
这一条不用说话,改代码本身就是反馈。编辑器会留意三种动作:
| 你的动作 | 判定条件 | 记成什么 |
|---|---|---|
| 马上撤销 | AI 改完 2 秒内,你在附近 3 行内删掉了内容 | 这种写法是错的,类似场景别再这么写 |
| 接受后微调 | 接受后 10 秒内,你在附近 5 行内做了修改 | 类似场景优先用你的写法 |
| 拒绝后自己写 | 拒绝后 30 秒内,你在同一个文件里写了超过 5 个字符 | 类似场景照你的思路来 |
这三种都会作为「纠正」存进角色记忆,同样的内容 10 分钟内只记一次。另外,AI 写过的文件,你过一阵子再改、保存时内容变了,也会作为一次修改反馈回去。
举个「接受后微调」的例子。AI 写了一个查用户的函数,你接受了:
funcGetUser(ctx context.Context,idstring)(*User,error){u,err:=repo.Find(ctx,id)iferr!=nil{returnnil,errors.New("user not found")}returnu,nil}接受后几秒钟内,你把错误那一行改成用%w包装,保留原始错误:
iferr!=nil{returnnil,fmt.Errorf("get user %s: %w",id,err)}这一改就会被记成一条纠正,内容大致是这样(原文是英文):
User accepted AI edit but immediately tweaked it in go file.
AI wrote:
return nil, errors.New("user not found")User changed to:
return nil, fmt.Errorf("get user %s: %w", id, err)Prefer the user’s version in similar contexts.
下次它在这个项目里写类似的错误处理,这条纠正就有机会被召回。
三、下一次对话时,记忆怎么用上
每轮按相关性召回
每一轮,WES Code 都会按你这条消息去召回相关的记忆:关键词和语义一起算分,再考虑时间远近,最多 20 条,相关性低于 0.3 的不要。
环境信息、共享的约定和规则,则每轮都在系统提示词里。
过期和冲突的记忆不再自动带上
- 一条偏好或纠正,30 天里一次都没被召回过,会被标记为过期,不再自动带进对话
- 两条记忆说法相反,或者新的一条明确否定了旧的,会被标记为冲突,也不再自动带上
被排除的记忆并没有删掉,主动搜索还能找到。想让 AI 翻一下记忆,直接说「查一下你记得的错误处理约定」,它会用同一个记忆工具去搜:
{"action":"search","query":"错误处理的约定","limit":10}主动搜索不受过期和冲突的限制,被标记的记忆也能搜出来。
同一个对话,接着上次的进度
在同一个对话里中断了,隔天回来接着说,上一轮结算出的会话状态会带上:你没做完的请求、做过什么、定了什么、哪些方向被否掉了、接下来要做什么。不用从头再讲一遍。
四、在记忆中心查看和清理
左侧活动栏里有一个灯泡图标,就是「记忆中心」。
分组
| 分组 | 内容 | 能删吗 |
|---|---|---|
| 关于我 | 你的编码偏好和习惯 | 能 |
| 角色记忆 | 每个 AI 助手各自积累的经验,前面说的「纠正」就在这里 | 能 |
| 本地共识 | 这个工作区里所有助手共享的约定 | 能 |
| 环境信息 | 引擎感知到的工具链和项目约定 | 只读 |
| 会话记忆、工作缓存 | 运行时状态,随任务产生和回收 | 只读 |
能做的操作
- 搜索:按语义匹配,搜「错误处理」,能找到相关的偏好和纠正
- 删除:删掉单条,或者清空一组
- 导入:每行一条,默认导入到「关于我」,也可以选角色记忆或本地共识
目前没有编辑入口。一条记忆记得不对,就删掉,再跟它说一次正确的。
按项目隔离
每个工作区的记忆分开存放。切换项目,整套记忆一起换;切回来,原来的记忆还在。
记忆存在本机的数据目录里,每个工作区一个ws-开头的子目录,记忆在其中的state.db里。macOS 上可以这样看(用只读方式打开,别直接改库):
# 每个工作区一个 ws- 开头的目录ls~/Library/Application\Support/wescode/cells/# 换成你自己的 ws- 目录名,按类型统计记忆条数DB=~/Library/Application\Support/wescode/cells/ws-xxxxxxxx/state.db sqlite3-readonly"$DB""SELECT kind, COUNT(*) FROM wes_memories GROUP BY kind;"# 再看看从没被召回过的有多少sqlite3-readonly"$DB""SELECT kind, COUNT(*) FROM wes_memories WHERE recall_count = 0 GROUP BY kind;"统计结果里常见的类型有fact、preference、correction、convention、lesson、environment,以及只属于当次对话的context。从没被召回过的偏好和纠正,放满 30 天就会被标成过期。
清理之前先备份
在记忆中心清空一组之前,可以先关掉 WES Code,把数据目录整体备份一份:
cp-R~/Library/Application\Support/wescode/cells ~/wescode-cells-backup-$(date+%Y%m%d)五、在设置里控制它记多少
打开设置,「AI 引擎」下面的「记忆偏好」,有三档写入策略:
| 策略 | 效果 |
|---|---|
| 静默写入(默认) | AI 记住你的偏好时不提示,不留审计记录 |
| 记录审计 | 照常写入,每成功写入一条,就留一条审计记录 |
| 禁止写入 | 拒绝一切记忆写入,这个工作区不会积累任何记忆,也不是排队等审批 |
同一页还能设条数上限:角色记忆默认 1 万条,会话记忆默认 5000 条。超出上限时,按召回次数、最近访问时间和创建时间综合打分,分低的先清掉。
做敏感项目、不想让它积累任何东西,选「禁止写入」就行。
六、怎么让它记得更准
纠正时说清楚范围。说「这个项目里错误统一用errors.Wrap包一层」,比只说「不对」有用得多。结算只保存你明确表达过的纠正。
一次性的要求,说明只是这一次。比如「这次先别写测试」,免得被当成长期偏好。
项目换了规范,去记忆中心删掉旧的。不然新旧两条说法相反,会被标成冲突,不再自动带上。
几个项目共用的习惯,每个项目各说一次。记忆按工作区隔离,在 A 项目教的,B 项目不知道。
密钥、账号别让它记。
七、它做不到的地方
- 不跨项目:A 项目里教会的,B 项目要重新教
- 结算靠模型判断:可能漏记,也可能记偏;记偏了,到记忆中心删掉
- 不能直接编辑:只能删掉重说
- 太久不用会冷掉:30 天没被召回的偏好和纠正,不再自动带上,要用的时候得主动搜
- 记忆存在本机,但用到的时候,会作为上下文发给你配置的模型
小结
- 偏好、纠正、项目事实跨对话保留;一次对话的上下文和计划,只属于那次对话
- 写入有三条路:每轮结束的结算、你直接说「记住」、你改它写的代码
- 每轮按相关性召回最多 20 条,过期和冲突的不自动带上
- 记忆中心能搜、能删、能导入;设置里能改写入策略和条数上限
文中的记忆功能都在 WES Code 里,官网是 weisyn.com。你们平时最常跟 AI 重复交代的是哪件事,欢迎评论区聊聊。
觉得有用的朋友,欢迎点赞、收藏、关注,后面会继续分享 AI 编程的实战经验。