给 #14 补点料:两个现成记忆实现里踩过的坑 #5908
Replies: 2 comments
|
我就是用 TencentDB-Agent-Memory 设计 分层记忆L0-L3 让AI 写了记忆系统 + 自进化系统 Agent 自进化系统设计方案
1. 背景与命题模型权重固定的前提下,agent 的"聪明"是外部化的:它等于上下文窗口中可召回的高质量经验与程序性知识。"自动进化"即存在一个闭环,把"本次执行的结果"持续转写回"下次执行的上下文"。没有闭环,会话次数增长不产生任何复利。 本方案定义这个闭环的完整设计:信号采集 → 经验提炼 → 人工审核 → 固化分流 → 度量验证 → 治理回收。 2. 目标与非目标目标
非目标
3. 设计原则
4. 总体架构组件与载体对照
4.1 插件归属(v0.2 裁决)不新增独立插件。 进化的"自动半程"全部作为 dsmem-host v2.5 的包内扩展模块(新增 推演过程(记录备查):曾考虑新增 evolve-host 独立包("仓库同置、插件分离"),理由是治理契约冲突。复审后放弃——细化职责后,插件从不写任何全局通道:它只写①轨迹/证据(自有 SQLite 独立表)②提案文件(自有队列目录);AGENTS.md/技能库/composition 的写入全部发生在会话内、人工批准之后。爆炸半径论证不再成立,独立包只剩成本没有收益。 规模与演进边界(对应"为增长设计"):
5. 信号层5.1 信号分类(判定标准必须是可操作的)
5.2 轨迹记录 schema(JSONL,一行一事件){"ts":"2026-09-01T10:00:00Z","sessionId":"...","project":"wanhu",
"signal":"S1","taskId":"修复登录500",
"summary":"drizzle migrate 引用了 schema 中不存在的列",
"evidence":"exit code 1 + 报错栈关键帧(脱敏)",
"rework":2,"userQuote":null,"resolved":true,
"artifacts":["src/db/schema.ts"]}要求:
5.3 存储与生命周期
6. 提炼层6.1 触发时机
6.2 输入 / 输出契约
6.3 提炼提示词骨架(v1 直接可用)6.4 查重与冲突预检
7. 审核闸门7.1 提案队列
7.2 提案文件模板---
id: prop-2026-0007
type: rule | skill | memory | tool
target: "~/.dsh/AGENTS.md §6" | "skill:drizzle-migration" | "memory:fact" | "plugin:..."
status: pending
confidence: 0.85
evidence: ["traj-xxx-001", "traj-xxx-003"]
budgetImpact: "+240B / 64KB (AGENTS.md)"
reviewAfter: 2026-12-01
---
## 教训(一句话)
迁移前必须先核对 drizzle schema 与数据库实际列,再执行 migrate。
## 提议变更(精确 diff 或新文件全文)
...
## 证据
- S1+S2: <摘要,脱敏>
## 反面考虑(为什么不固化成另一种形式)
...7.3 审核流程用户说"看提案" → agent 列出 pending 清单 → 逐条"批准 / 否决 / 改" → 批准后 agent 执行落盘(编辑目标文件 / 安装 skill / memory_save)→ 更新状态。固化层全部文件纳入 git 管理,可回滚。支持快捷批注:"全部批准" "只批 rule 类" "#3 改成 … 再批"。 7.4 写权限矩阵(治理核心)
8. 固化层分流(准入与淘汰标准)
tool 类提案必须先回答:"为什么现有工具组合不够?"——防止为进化而进化。 9. 度量层:回放集9.1 任务卡 schema---
id: bench-001
origin: "traj-xxx(真实历史任务)"
task: "为 X 函数补充空值校验并用测试证明"
verify: ["pnpm test -- filter.null 红转绿", "biome check 通过"]
historicalFailure: "首轮未覆盖 null 导致 NPE(见 traj-xxx)"
---
9.2 回放流程workflow 编排:每张任务卡 → 独立 subagent 在隔离 worktree 执行 → 收集 verify 结果 → 汇总 delta 报告。约束:不污染主工作区;每卡限时;模型与关键参数固定保证可比。 9.3 指标与回归门
10. 治理与防漂移
规则生命周期:提案 → 生效 → 复用/命中统计(人工粗粒度)→ reviewAfter 复审 → 修订或 retired(原文留存归档,可回滚)。 11. 实施路线
依赖:M2 依赖 M0 的轨迹;M3 依赖 M1 的提案质量经人工确认稳定;M4 依赖 M3 的自动采集。 12. 与 DSH 现状对齐已确认事实(本方案依赖)
实施前 Inspect 确认(2026-09-01 已完成,不猜测;详见 §14.1)
13. 开放问题(需用户裁决)
14. M3 详细设计:dsmem-host v2.5
|
| 信号 | 事件(mode) | 关键载荷 | 捕获动作 |
|---|---|---|---|
| T0 会话开 | agent/session-start(emit) |
agent, source |
登记会话上下文(workspace → <project>) |
| 逐轮收口 | agent/turn-stopping(serial) |
agent, turn |
本 turn 聚合的信号暂存,等待落盘钩子 |
| S1 工具失败 | tools/result(emit) |
exec.name/arguments, result.isError, error |
命令非零/测试红/工具报错 → S1 轨迹行 |
| S1 步骤错误 | agent/error(emit) |
turn, step, error |
步骤级异常 → S1 |
| S1 模型请求失败 | agent/request-error(waterfall) |
provider, failure |
只读旁观,next() 原样透传 |
| S2 返工 | tools/result + fs/write-intent / fs/edit-intent / fs/observed |
displayPath, kind |
同文件编辑计数:非计划性第 ≥3 次、同错误重试 ≥2 → S2 |
| S3 用户纠正 | session/event(emit,post-commit) |
user/message 文本 |
消息级模式匹配(否定/改口/"不要/以后/记住")→ 候选行,source:"message" |
| 持久化对齐 | session/flush(parallel,awaited) |
session |
缓冲轨迹统一追加落盘并 fsync |
| 会话终 | session/disposed(emit) |
session |
末次 flush + 计数器清理 |
实现注记(v2.5.0):S2 的同文件编辑计数以持久 session 日志的
tool/call(含 arguments)与tool/result(含 turn/step/error)配对实现,替代观察fs/write-intent等 waterfall——信息等价(工具名/路径/错误码)且自带 turn 归属与子代理过滤;fs/*事件面保留为未来细化手段。S1 主源同理取 session 流内tool/result(持久侧自带 error 字段)。
14.2 架构约束(继承 §12 dsmem-host 关键立场)
- 宿主受信代码直接
node:fs追写~/.dsh/evolution/trajectories/<project>/YYYY-MM.jsonl,无沙箱问题;写权限与 §7.4 允许自动写清单一致,不越线。 - 铁律「绝不阻塞会话」:监听器只做内存环形缓冲聚合,仅在
session/flush/session/disposed落盘;单行 ≤2KB、脱敏与 M1 skill 同规;监听器自身异常全吞,只进 host 日志。 - waterfall 类事件(
request-error/write-intent/edit-intent)零决策零改写,只读旁观。 - 独立 SQLite 表
evolve_trajectories,与召回层隔离:不注册为 fact/episodic、不进注入管线(M3 验收条款"不污染召回")。 - 证据链接:轨迹行携带 sessionId + turn + seq,可回指持久 session 日志原始
tool/result(含error:{name,code})。
14.3 与 M1 约定路径的关系
- 机制化只接管捕获(S1/S2/T0 全自动;S3 消息级候选);提炼与提案仍走 M1 skill,人工闸门不变。
- M1 skill 的 S1/S2 判定改为"优先复用 evolve 已落盘轨迹,避免重复记录";无 evolve 数据时维持现状(向下兼容)。
- prop-2026-0002(无信号留痕)仍建议批准:M3 落地前的过渡期干净收尾可计数;M3 落地后 no-op 台账由 evolve 接管。
14.4 验收标准(对齐 §11 M3 行)
- 连续 ≥3 个外部项目会话在零人工提示下自动出现轨迹行,且召回注入零污染;
- 证据链接 fact 提取:fact 记忆携带 sessionId/seq 引用;
- 回归:dsmem-host 既有冒烟断言全绿;新增 evolve 模块单测覆盖缓冲/落盘/脱敏/降级四路径。
15. 注入预算与在场保证分级(v0.3 增补,2026-09-01 用户批准)
背景:固化通道见效后,注入侧膨胀成为主要长期风险。AGENTS.md 超限行为已查实(agent-instructions
render.ts):不是报错,而是静默截断——先丢最不具体的文件,最终整体替换为一行提示,规则悄悄失效。故膨胀治理必须在触及硬墙前主动执行。
15.1 AGENTS.md 三道线(硬性标准)
| 线 | 值 | 效力 |
|---|---|---|
| 宿主硬墙 | 64KB(agent-instructions maxBytes,部署配置) |
超限静默截断,绝不可触及 |
| 体检水位线 | 24KB | 触达即强制出「规则体检提案」(合并/精简/退役),新增 rule 提案冻结至水位回落 |
| 铁律层软上限 | 16KB | 仅保留违反即事故的硬约束;常规指导走召回层/流程层 |
提炼流程水位线检查(执行载体:prop-2026-0003 修订 SKILL.md):出 rule 提案前必测 ~/.dsh/AGENTS.md 大小——≥24KB 先出体检提案;≥16KB 新提案须同时提名一条退役候选。
15.2 在场保证四级分层(§6.3 步骤 4「选通道」增补)
| 层 | 载体 | 在场保证 | 准入 |
|---|---|---|---|
| 铁律层 | AGENTS.md | 100% 常驻 | 违反即事故的硬约束,≤3 行 |
| 召回层 | dsmem 记忆(instruction/fact) | 场景相关时高概率在场(语义触发,不依赖用户关键词) | 场景型约束、项目事实 |
| 触发点层 | tools/pre-execute 事件拦截(M4+ 可选) |
触发点 100% | 危险动作前置提醒,须节流(同规则每会话 ≤1 次) |
| 流程层 | skill | 主动调用(惰性加载) | ≥3 步可复用流程 |
skill 的关键词依赖弱点由召回层补位;100% 保证只存在于铁律层与触发点层,其余按性价比取舍。
15.3 agent-memory 注入块分段预算(现状源码查实 buildRecallText,即硬性规范)
| 段 | 预算 | 机制 |
|---|---|---|
| 用户画像摘要(L3' digest) | ≤800 字符 | 每 personaDigestEveryN(30) 条新全局记忆重归纳 |
| 用户画像与长期规则 | ≤ recallTop(6) 条 × recallCharsPerMemory(200) |
按 priority 降序截取,其余退到 memory_search 检索层 |
| 主题场景 | 段 ≤ recallTotalChars/3(500),每条 ≤400,至多 16 段 |
L2-lite 场景压缩 |
| 相关记忆(动态召回) | ≤ recallTotalChars(1500) |
逐轮 BM25/向量检索 |
| 记忆工具 | 固定 ~250 | — |
全块理论上限 ≈4.4KB,结构性有界,不随日积月累增长。
治理条款(新增,防 priority 通胀——本块唯一真实风险):
- 新 instruction 默认 priority ≤70;90+ 仅限核心红线级约束。
- instruction 合并/退役纳入每月规则体检提案;被挤出常驻层(top-6)的条目自动降级为检索层,无需删除。
- 调整
recallTop/recallTotalChars/sceneMaxCount前须按本表核算全块 ≤4.5KB,并写入提案budgetImpact。
定稿前本文件为唯一事实来源;定稿后以 git 提交为版本锚点。
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
看到 #14 在求 memory 方案,正好最近把两个带生产记忆的 agent 项目读了一遍(deer-flow 和腾讯的 TencentDB-Agent-Memory),说几个我印象深的点,给想实现的人省点弯路。
第一个是删除 agent 后记忆还在偷偷写。deer-flow 就踩过(issue #5037):缓冲的抽取任务挂在全局,agent 都删了,防抖定时器到点照样把记忆写回去。他们后来加的是按 agent 取消。另一个是清空记忆和写入赛跑(#5093),也修了两轮才稳。腾讯那边踩的坑是写入粒度:Codex 一轮任务里同一个用户消息被写了 8 次(#1245),因为归档钩子挂在每个请求流的尾巴上,而 Codex 每轮工具循环都会重发历史——请求级写入、任务级语义,不事前定死事后补去重特别痛。
两家互不认识却踩了几乎同一批坑,所以我觉得这些大概率是躲不掉的坑而不是实现问题。对 DSH 来说最顺的路可能是把 memory 做成一个插件挂进 agent scope(随 agent 一起卸载,生命周期问题直接没了),后端做成可插拔的——真要把 codex/claude code 的记忆迁过来,写个 import 后端就行。
具体代码位置和 issue 都可以点进去看,我就不贴一堆了。有没有人已经在搞这块的,想拉个群聊聊。
All reactions