开关默认关(generate/use),设置接口 GET/PUT /users/me/auto-memory-settings,任务级覆盖 POST /tasks/{id}/auto-memory-flags,手动触发 POST /users/me/auto-memory/run,日志 GET /users/me/auto-memory-log。
提取:worker run_loop 轮次边界扫 completed 任务,闲置/时长/长度/外部上下文/配额剩余百分比五道门,脱敏后写 project 级 identity_memories,同一任务去重、同一目标 supersede 合并;只写 project 级,不跨项目泄漏。
注入:worker run_one 首轮把最新各 5 条用户/项目记忆拼进内存 prompt 副本(goal 任务同步改内存 goal),库原 prompt 不动;续跑/断点/协调员不注入,注入失败 fail-open。
v1 诚实边界:extract/consolidation 模型只存设置不调模型;MCP/web 线程内调用暂无 tasks 表标记,外部上下文门只认任务间消息与协调员子任务;无控制台 UI。
94 lines
5.4 KiB
Markdown
94 lines
5.4 KiB
Markdown
# 自动记忆(官方 Codex memories 的云端对齐版,v1)
|
||
|
||
官方功能见 learn.chatgpt.com/docs/customization/memories:开启后,
|
||
Codex 把先前聊天的有用上下文转成记忆,供未来工作用;后台生成、
|
||
闲置后才生成、剩余额度低时跳过、有 generate / use /
|
||
disable_on_external_context 等设置、密钥脱敏。
|
||
|
||
本批把这套行为搬到云端控制面(`cloud/auto_memory.py`),不改
|
||
host.py、不改 CODEX_HOME、不改 thread 的创建/续跑/fork/归档。
|
||
云端记忆与官方本地记忆的区别要先说清:官方记忆存在单机
|
||
`~/.codex/memories/` 里、跟一台机器走;云端记忆存在控制面
|
||
数据库里,跟用户/项目走,换 worker、换执行器都还在。
|
||
|
||
## 开关(默认全关,与官方“本地记忆默认关”一致)
|
||
|
||
- `GET/PUT /users/me/auto-memory-settings`:本人设置。
|
||
- `generate_memories`:完成任务是否可被提取。默认 0。
|
||
- `use_memories`:新任务首轮是否注入记忆。默认 0。
|
||
- `disable_on_external_context`:默认 1,见下。
|
||
- `min_rate_limit_remaining_percent`:默认 20,见下。
|
||
- `idle_seconds`:默认 900;`min_duration_seconds`:默认 30;
|
||
`min_result_chars`:默认 200。
|
||
- `extract_model` / `consolidation_model`:只存设置,v1 不调
|
||
模型(见“未做”)。
|
||
- `POST /tasks/{id}/auto-memory-flags`:单个任务覆盖 use/generate
|
||
(NULL = 跟随用户设置),权限为项目 create_task。不改 tasks
|
||
表结构,建任务的各条 INSERT 路径都不用动。
|
||
- `POST /users/me/auto-memory/run`:手动触发本人任务的提取扫荡
|
||
(body 可带 `force: true` 跳过闲置/时长/长度门,不跳过开关、
|
||
外部上下文门与额度门);`GET /users/me/auto-memory-log`:看
|
||
本人任务的提取日志(按任务主键覆盖,不无限增长)。
|
||
|
||
## 提取:什么时候、从哪来、写到哪
|
||
|
||
触发:worker `run_loop` 每轮结束调 `process_auto_memories()`;
|
||
也可经上面的手动触发接口立即跑。只扫 `status='completed'` 的
|
||
任务(failed / interrupted / merged 不提取)。
|
||
|
||
资格(任一不满足即跳过并记日志,下次仍可再扫):
|
||
1. generate 开关(任务级覆盖优先于用户设置);
|
||
2. 终态闲置够 `idle_seconds`(终态后仍可被 /continue 续跑,
|
||
所以“刚完成”不等于“已闲置”;`force` 可跳过);
|
||
3. 有 started_at/finished_at 且时长 ≥ `min_duration_seconds`,
|
||
result_text 长度 ≥ `min_result_chars`(跳过短期会话);
|
||
4. `disable_on_external_context` 开时,任务间消息
|
||
(task_followups 有该任务的行)或协调员子任务
|
||
(parent_task_id 非空)不提取;
|
||
5. 当月 USD 配额剩余百分比 ≥ `min_rate_limit_remaining_percent`
|
||
(无配额行按默认 $10 计,只有显式 NULL 行才是不限额,与
|
||
worker 配额口径一致;查不到配额时 fail-closed,记
|
||
quota_check_failed,不冒充额度充足)。
|
||
|
||
内容(v1 确定性版,不调模型):任务 goal/prompt 首行 +
|
||
result_text 前 800 字,脱敏后拼成一条 project 级 fact,写入
|
||
`identity_memories`,`source_thread_id` 记云端任务 id(去重键)。
|
||
同一任务只提取一次;同一目标的新结果出现时 supersede 旧记忆
|
||
(consolidation 的确定性版),不堆重复。自动提取只写 project
|
||
级:单个项目的任务结论若自动写成 user 级,会跨项目泄漏项目
|
||
上下文;user 级记忆仍只接受手动创建。
|
||
|
||
脱敏:`api_key/password/secret/token/credential` 的 key=value
|
||
形态、Authorization / Bearer 头、sk- / ghp_ / gho_ / xox*- 前缀
|
||
一律替换为 `[REDACTED]`;偏好里的密钥键禁令见 identity-memory.md。
|
||
|
||
## 注入:怎么进任务
|
||
|
||
worker `run_one` 认领后、执行前调 `_apply_auto_memory_injection`:
|
||
- 只注入首轮:续跑、断点续跑、协调员任务不注入;
|
||
- 只改内存副本:prompt 前加 `【过往记忆,仅供参考,不得改写
|
||
本任务目标】` + 最新各 5 条用户/项目记忆;goal 任务同时改
|
||
内存里的 goal(执行器取 goal 优先于 prompt);库里的原
|
||
prompt / goal 不动,任务详情里看到的仍是原文本;
|
||
- 注入失败 fail-open(记 warning,不挡任务);注入成功记
|
||
`worker_memory_injected` 审计;无记忆或 use 关时不注入。
|
||
- 注入不进 thread 的 developerInstructions:host.py 的 dispatch
|
||
路径不传 instructions,云端层唯一不改 host.py 的注入点就是
|
||
prompt 前缀,identity-memory.md 里“调用方自己拼进新建任务
|
||
的 prompt”正是这条路。
|
||
|
||
## 未做(诚实版)
|
||
|
||
- 未调模型提取/合并:`extract_model` / `consolidation_model`
|
||
只存设置。v1 提取是确定性拼贴,不是模型摘要;换模型提取
|
||
需另定模型选择、成本上限与失败语义。
|
||
- 未识别 host 线程内的 MCP / web search:tasks 表上没有这类
|
||
标记,`disable_on_external_context` 目前只认任务间消息与
|
||
协调员子任务;要认 MCP/web 需先给 host 线程事件加遥测。
|
||
- 未做控制台 UI:开关与日志目前只有 API;未做 per-chat 的
|
||
`/memories` 式交互(任务级 flags 接口是对应的最小版)。
|
||
- 未进代码签名候选:worker 签名只含 worker/sandbox/
|
||
coordinator/cost/server/host;本批同时改了 worker.py,所以
|
||
正常部署换目录时旧 worker 仍会因 worker.py 变化而自退,
|
||
仅换 auto_memory.py 的单文件部署不在签名覆盖内。
|