deskpaw-memory/docs/architecture.md

151 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DeskPaw 连续智能体与记忆架构
DeskPaw 对用户提供一个持续存在的智能体身份。上层负责理解、承诺、决策和调度;Pi 等执行者负责受限任务;记忆系统维护可追溯的经历、事实和约束,并在相关时提供给上层。会话身份持久存在,不要求任何一个模型的上下文无限增长。
## 改造前的实现
上层目前通过一次 `completeSimple` 调用产生包含 `action`、`reply`、`objective` 等字段的 JSON。运行时从文本的第一对外层花括号之间截取内容,解析并路由到九种固定动作。对话回复与控制指令耦合,回复又被截断到 2000 字符。它没有独立工具循环,也不直接共享 Pi 的全部消息列表。
Pi 使用持久化 JSONL 会话文件;Runtime SQLite 保存交互、执行队列、日程和事件。Memory SQLite 保存任务卡、话题、事实和资料夹,Markdown 是投影。模型输出 JSON、JSONL 审计文件、JSON Lines 本地通信是三个不同问题,不能通过替换文件格式来解决语义和调度耦合。
当前上层先等待问答同步和记忆召回,然后调用模型。较完整的整理由执行队列中的 `memory_maintenance` 完成,依赖下层空闲。任务完成、阻塞等事件主要进入执行日志和展示渠道,尚未形成有版本校验的上层事件收件箱。自然语言暂停还会等待 Pi 停止;直接 `/v1/stop` 则已经能够先确认请求。
## 架构原则
1. 上层是记忆的主要消费者和任务意图的管理者。后台整理者不能改变用户目标、授予操作权限或自行恢复暂停任务。
2. Runtime 是任务状态的权威,Executor 是动作回执的来源,Memory 是记忆记录的权威。检索索引和 Markdown 都可重建,不形成第二份可独立修改的事实库。
3. 上层不等待电脑任务或后台整理完成。不能安全继续的任务可以等待证据,整个上层仍可接收新消息和控制请求。
4. 原始观察、执行者报告、用户陈述、验证结果和模型推断分开记录。动作成功不等于业务完成。
5. 所有跨异步边界的结果带来源、对象、请求标识和版本。迟到结果可以归档,不能覆盖更新的约束或作用于另一任务。
6. 至少一次投递与幂等提交构成可靠性基础,不假定跨数据库事务或端到端恰好一次。
## 组件与责任
```text
用户和消息入口 → 上层收件箱 → Supervisor → 经校验的控制命令
↑ ↓
事件筛选与回调策略 Runtime 与日程调度
↑ ↓
记忆召回结果 Pi 等执行者 → Executor
↑ ↓
上层上下文投影 ← Memory ← 有界事件与证据引用
↑
后台观察和整理 Worker
```
Supervisor 只持有控制和只读查询能力。发送任务后立即获得持久化任务回执。对用户的文字与工具参数分离;JSON 继续作为通信和模式校验格式,但不再要求每次聊天都是一个控制 JSON 对象。
Runtime 管理队列、取消、任务版本和执行资源。一个物理桌面同一时刻只能有一个有副作用的执行所有者。未来研究、文件解析和记忆 Worker 可以并行,但不能绕过桌面资源所有权。已发出的原子操作无法保证撤回;不确定结果应暂停后续动作并核验。
Memory 分为接入、状态投影、观察提取、合并复核、检索和上下文组装。模型只生成受校验的记忆提案,程序负责事务、来源校验、生命周期、索引和预算。
这些是逻辑边界。首阶段后台 Worker 复用 Agent 的模型适配层,但拥有独立队列,不占 Pi 执行队列;Memory 仍通过本地协议独立运行。后续可将模型 Worker 和 Pi Runner 迁到独立进程。首阶段不宣称提供进程级实时隔离。
## 对象与记忆模型
对象标识与会话标识分离。对象包括长期责任领域、有限项目、持续维护资产、可复用流程、周期计划和一次执行。项目休眠只表示当前不活跃,不表示其记忆失效。
报销领域包含报销规则和资料入口;每月报销是独立项目;每日整理和每月提交是不同计划;每次操作是执行实例。软件资产保留仓库、部署和故障经历,某次修复则是关联该资产的独立任务。没有下一次计划时间的资产也可以在事件或问题命中时恢复上下文。
事件可以关联多个对象,保留一个主要归属以支持低成本路由。多设备、多用户扩展必须增加明确的所有者和授权范围;当前统一会话不能被解释为可以跨用户共享全部记忆。
记忆分为以下类型:
- 当前状态:当前讨论、活跃任务、未兑现承诺、阻塞和等待确认。任务状态由程序投影。
- 经历:目标、关键操作、结果、失败方法、剩余事项及证据。经历按对象和事件段组织,工作日只是浏览维度。
- 事实和偏好:带范围、来源、有效时间与状态的原子陈述。
- 规则和纠正:注明约束对象、何时生效、是否取代旧规则。一次例外不自动成为全局规则。
- 操作经验:适用条件、步骤、失败条件和验证方法。候选经验不自动成为已批准技能。
- 召回线索:说明未来何种问题可能需要这段记忆。线索不是事实、命令或日程。
记录至少包含 `id`、`owner_scope`、`subject_id`、`kind`、`content`、`source_refs`、`observed_at`、`recorded_at`、`status`、`revision`。稳定条目再提供有效时间、复核时间和 `supersedes`。对象版本按对象递增,避免一个无关项目更新导致全库写入冲突。
## 记忆形成
接入用户消息、上层控制决定和承诺、Pi 阶段报告、Executor 有意义的观察与产物、Runtime 和日程事件。外部网页和屏幕内容只作为数据,不提升为用户指令。
普通鼠标动作和重复成功回执留在审计层。程序合并重复观察和同一错误,保留次数和时间范围;关键变化、错误、用户纠正、产物和终态进入记忆事件。图片、大段 UIA 和模型供应商原始响应不复制进记忆。来源引用不等于授权读取任意文件,读取证据仍需范围校验与脱敏。
事件先持久化,再异步发送。接收位置、已整理位置和已发布版本分开维护。高优先级批次可以先处理,但不能越过尚未处理的事件而使其永久丢失。以事件序号和 ID 去重,不以毫秒时间作为唯一游标。
状态通道立即更新确定性的任务变化。用户最新原话进入上层上下文,不等待语义整理。自然语言理解本身仍需模型;明确停止按钮和控制接口走快速通道。
语义通道按任务或对象构造有界工作包。首版普通事件按约 30 秒、20 条有效事件或输入预算触发;阻塞、结束和明确纠正优先。Worker 无新数据不调用模型。初始并发为 1,使用已配置文本模型,模型名称和超时独立可配。
观察者提取经历与稀疏候选条目;合并者在任务边界或对象记录过多时合并。每个候选都要能回到原始来源。缺少来源、扩大范围、试图覆盖较新纠正或包含敏感信息的提案不能生效。失败保留待处理事件并退避,成功提交后才消费来源。
用户明确陈述与模型推断保留不同标签。数次复述同一来源不增加独立证据数量。环境状态需要时重新检查,旧故障不能成为永远成立的操作前提。压缩后的文本不替代原始证据;重要条目仍能按引用展开。
## 记忆管理
候选、有效、被取代、过期和归档是记忆生命周期;活跃、休眠、完成是对象生命周期,两者独立。
纠正以新增版本和关联旧版本实现。最新规则优先的前提是同一对象、同一适用范围和相应有效时间;不能用简单的全库最后写入胜出。冲突无法消除时保留冲突标记,不暗中选择一个结果。
暂态观察按类型设置复核和保留策略。未完成承诺不能仅因长时间未访问被遗忘。用户要求删除时,应同时失效相关索引、上下文缓存和派生记录,按保留策略清理内容;审计机制不能成为拒绝删除的理由。
数据库与证据保留量可以增长,上层上下文必须有界。核心画像只保留少量稳定条目,休眠对象通过索引找回,不把全对象目录长期放入提示词。SQLite 负责权威记录;Markdown 用于查看与导出,外部编辑通过显式导入和版本校验。
## 召回与结果回调
召回是检索历史知识,回调是异步结果返回到接收者,两者用不同协议表示。
一次召回请求包含请求 ID、所有者范围、问题、对象或任务引用、用途、预算、发起意图版本和有效期。结果包含命中条目、证据引用、记忆版本、检索原因、缺口和完成状态。查不到、暂时不可用和记录已过期必须区分。
检索顺序为:权限和有效性过滤;确定对象及强制适用约束;关键词或结构化 ID 召回;必要时加入语义及关联线索召回;合并排序;展开少量证据;在预算内组装。强制约束不依赖相似度排名。未来混合通道可以使用 RRF 融合,向量索引可替换,不影响权威数据。
上层使用已发布快照加最新 Runtime 变化。缓存未命中时发起异步检索,不能因此把未知解释为不存在。涉及不可逆动作而依据不足时,仅让该任务等待上下文,不阻塞其他对话。
| 时机 | 召回内容 | 上层处理 |
| --- | --- | --- |
| 新用户消息或话题切换 | 当前对象、相关规则和经历 | 读取缓存,必要时异步补查 |
| 派发任务前 | 约束、验收条件、相关错误经验 | 形成带版本的任务工作包 |
| 下层遇到阻塞或重复失败 | 同对象历史原因和修复经验 | 合并事件,重新判断或请求用户输入 |
| 日程到期 | 对应计划、周期项目和未完成事项 | Runtime 触发,必要时让上层判断变化 |
| 重要观察与休眠资产相关 | 相关资产摘要和证据 | 后台匹配后按必要性唤醒 |
| 用户纠正或相关记忆更新 | 新约束及被取代版本 | 失效旧缓存,必要时改向正在执行的任务 |
| 普通点击或无变化观察 | 通常无 | 不唤醒上层模型 |
回调进入持久化上层收件箱,包含因果事件 ID、任务 ID、任务版本、请求 ID和优先级。用户消息优先,重复进度合并。回调过期或目标已变化时归档,不对新任务应用旧结果。模型生成控制命令后,执行前还要检查目标与版本,避免给任务 A 的修改落到刚接替的任务 B。
控制回执区分已接收、已开始、正在停止和已停止。上层不能在命令未持久化前声称已安排,也不能在原子操作结束前声称已经停止。后台记忆更新通常只替换快照,不每次触发聊天或继续执行。
## 三个项目的复用边界
源码基线为 T-Mem `dd9e152`、Letta Code `253a3bc8` 和 Mastra `e832eb4870`。
- T-Mem:复用原子条目到经历的证据关联、写入时形成召回线索以及 `stage6_retrieval.py` 的 RRF 算法。Python 数据集脚本和默认英文分词不作为生产接入层;其倾向完整提取的提示词需要改成有预算的稀疏筛选。触发线索不进入事实证据路径。
- Letta Code:复用常驻与按需加载的分层、按引用交接以及后台修改成功落地后才消费历史的规则。`memory-format.ts` 的路径判断可用于 Markdown 投影,`memory-handoff.ts` 的交接协议需换成我们的来源接口。当前本地初始化使用 MemFS v2,不直接沿用旧 `system/` 布局;按英文字符估 token 的方法不适合作为中文硬预算。
- Mastra:复用 `anchor-ids.ts`、观察分组与来源维护等可拆出的纯函数,以及安全批次边界、后台准备后激活和异步问答协议。`ObservationalMemory` 也提供独立 API,但直接采用仍需适配其消息与存储模型。首阶段摘取需要的模块和回归案例,不迁移整个 Agent 框架。部分激活路径可能等待后台作业,不能置于上层响应路径;提醒检索的英文正则必须补中文处理。
移植代码记录上游版本和对应许可证,保留要求的声明。T-Mem 为 MIT;所选 Letta Code 和 Mastra 非企业模块为 Apache 2.0。Mastra 的 `ee` 内容不纳入本次复用。
## 第一阶段实现边界
第一阶段实现事件接入、后台整理、来源可追溯的经历、基本索引召回、有界上层上下文与异步控制和结果收件箱。先沿用现有模型适配层与 SQLite,本地 JSON Lines 协议继续使用。
实施顺序:
1. 增加版本化事件协议、幂等接入和可恢复批次;保留现有原始记录。
2. 增加独立于 Pi 队列的观察 Worker,模型只处理有界事件并提交受校验提案。
3. 组装上层缓存和异步召回结果,当前任务状态始终覆盖旧快照。
4. 分离模型正文与原生控制工具,暂停先返回控制回执,补充任务目标校验。
5. 接通关键执行事件的上层收件箱,限制自动回调的权限和重试,避免自动执行循环。
6. 通过离线模型、隔离数据库和假 Executor 验证,不操作真实桌面。
首阶段不建设完整财务台账、发票解析、向量基础设施、多设备调度或自主技能发布。全量项目管理、语义索引和进程级隔离通过现有协议继续扩展。正式环境启用须在测试后单独部署;源码修改与部署是不同操作。
该阶段已在 `feat/supervisor-memory-v1` 分支实施一版。具体参数、协议、实测范围及尚未实现的边界见
[第一阶段说明](implementation-v1.md)。尤其要区分只读结果收件箱与自动续做:本阶段实现前者,不让回调擅自创建操作。
## 验收
- 上层聊天和暂停控制不等待记忆模型或 Pi 原子动作结束。
- 任务完成、阻塞和记忆召回结果有可恢复、幂等的回调记录。
- 迟到结果不覆盖更新约束,不对不同任务实施旧命令。
- 重启或模型错误不会使未完成整理的事件永久丢失。
- 普通操作洪流经过筛选,模型批次和上层上下文有明确大小上限。
- 中文报销、跨月份经历和休眠软件资产可以按相关对象或关键词找回。
- 工具成功与业务验证结果分开,网页指令、密码、隐藏推理不提升为长期规则。
- 已有任务、日程、技能和会话身份保持可用。测试记录明确哪些属于单元、协议、集成和实际硬件验证。