Skip to content
AceGuru-mjh edited this page Oct 1, 2026 · 4 revisions

cs-mem 认知记忆

💡 记忆 · 🏠 首页 › cs-mem

Home Version Kotlin Modules Tools License

cs-mem typing

📑 本页目录

platform/cs-mem 是本项目的差异化核心。它不是"给 LLM 塞一段历史", 而是一套把屏幕感知转化为可复用程序性记忆的完整管线。 对标调研见 docs/memory-and-workflow-research.md(MemGPT/Letta、Mem0、A-MEM、Zep/Graphiti、Voyager)。

1. 管线全景

flowchart TB
    subgraph INGEST["🔵 摄取侧 —— 每次动作后自动触发"]
        direction LR
        A["👁 感知<br/>getUiTree()<br/>Root / Shizuku / Shell"]
        B["✂️ 语义降维<br/>UiTreePruner<br/>剔除不可见与装饰节点<br/>体积 -90%+ · 指纹 SHA-256"]
        C["Δ 差分摄取<br/>DifferentialIngestor<br/>只存状态跃迁<br/>压缩 95%+"]
        D["✉️ 串行写入<br/>MemoryWriterActor<br/>有界邮箱 256 · 背压"]
        A --> B --> C --> D
    end

    E[("🗄 MemoryGraphDatabase<br/>Room · schema v3<br/>nodes · edges · episodes<br/>fsm_macros · migration_map")]
    D --> E

    subgraph CONSUME["🟢 消费侧"]
        direction LR
        R1["召回工具 ×3<br/>memory_search_nodes<br/>memory_recent_episodes<br/>memory_recall_macro"]
        R2["轨迹蒸馏<br/>TraceDistiller<br/>锚点提取 → 动作压缩<br/>→ FSM 编译"]
        R2 --> M["FSMMacro 宏技能"]
        M --> BY["⚡ 旁路回放<br/>BypassExecutionEngine<br/>指纹命中 → 绕过 LLM<br/>微秒级 · 0 token"]
    end

    E --> R1
    E --> R2

    IMM["🛡️ MemoryImmuneSystem<br/>摄取前免疫检查<br/>悬浮窗 / 敏感词 / 完整性 / 隔离"] -.检查.-> INGEST
    DR["🌙 DreamRenderer(WorkManager)<br/>息屏+充电+WiFi 时巩固<br/>能量衰减 · 晶化 · 拓扑迁移"] -.维护.-> E
Loading

2. 记忆的两种形态

形态 模型 产生 消费
陈述性记忆 SemanticNode 语义图 + Episode 情景 + GraphEdge(SPATIAL / CAUSAL / SEMANTIC 三类边) 每次动作后 CsMemSessionManager.afterAction() 捕获差分 memory_search_nodes / memory_recent_episodes 召回工具;记忆屏可视化
程序性记忆 FSMMacro 有限状态机宏技能 任务成功后 TraceDistiller.distill():锚点提取 → 动作压缩 → FSM 编译 BypassExecutionEngine.tryBypass():指纹命中即绕过 LLM 直接回放(微秒级 / 0 token)

Note

"陈述性 vs 程序性"借鉴认知科学:前者是"知道某件事",后者是"知道怎么做"。 后者才是本项目"肌肉记忆"的来源。

3. 关键组件

组 组件 作用
会话 CsMemSessionManager 会话生命周期,动作后触发摄取
降维 UiTreePruner · NodeFingerprint 剔除不可见/装饰节点(体积 −90%+),对每个节点算 SHA-256 内容指纹
差分 DifferentialIngestor 只存状态跃迁而非整帧快照(再压 95%+)
写入 MemoryWriterActor 串行 mailbox actor,有界邮箱 256 + 背压,避免并发写库
存储 MemoryGraphDatabase · MemoryGraphStore(Impl) Room schema v3,5 张表:nodes edges episodes fsm_macros migration_map
蒸馏 TraceDistiller ReAct 轨迹 → 锚点提取 → 动作压缩 → FSM 编译成宏
回放 BypassExecutionEngine 指纹命中 → 0 token 直接回放动作序列
旁路执行 BypassExecutionEngine + 宏实体 支持"偏离即中止":任一动作的预期指纹不匹配就退回 LLM
对外 CsMemRecallTools 3 个记忆召回工具注册到 ToolRegistry
DI CsMemModule Hilt 模块

4. 存储演进(schema v3)

  • 边 ID 从"帧内自增计数器"改为"内容哈希": SHA-256(源指纹 | 目标指纹 | 关系) 的前 16 位 —— 同一条拓扑边在任意两帧拥有相同 ID, 差分语义与跨 Episode 删除才正确;
  • v2→v3 Room 迁移:清理历史重复边 + 建 (episode_id, edge_label) 唯一索引 + 删除操作增加 episode 作用域。

Warning

数据库升级必须显式提供 Room Migration,仅降级允许 destructive 重建。 这是保护长期记忆不被静默清空的硬约束 —— 记错一次,用户积累几周的记忆就没了。

5. 差分摄取到底省了什么

原始 UI 树(每次 dump)      ████████████████████████  100%
  ↓ UiTreePruner(语义降维)
可见语义节点流              ██                        ≤10%(−90%+)
  ↓ DifferentialIngestor(只存跃迁)
入库的差分跃迁             ▌                         ≤0.5%(再 −95%+)

换来的是能在手机上长期跑:几百 KB 的差分库 vs 若干 GB 的全帧录像。

6. 0 token 的旁路回放是怎么发生的

sequenceDiagram
    participant U as 用户请求
    participant E as Agent 引擎
    participant BY as BypassExecutionEngine
    participant DB as Room 图库

    U->>E: "再打印一次 HELLO"
    E->>BY: tryBypass(currentFingerprint)
    BY->>DB: 查 migration_map 别名 → 查 FSMMacro
    alt 命中且可执行
        DB-->>BY: FSMMacro(动作序列)
        BY->>BY: 逐步执行,每步校验预期指纹
        BY-->>E: 已完成(0 LLM 调用,微秒级)
        E-->>U: 结果(UI 标注"来自肌肉记忆")
    else 未命中 / 中途偏离
        DB-->>BY: null
        BY-->>E: 未命中 → 正常走 ReAct
    end
Loading

Tip

中途偏离(UI 改版导致某一步的指纹不再匹配)会立即放弃回放并退回 LLM, 而不是继续执行可能危险的动作。

7. 记忆里的"免疫"与安全

见 记忆生命周期:摄取前检查悬浮窗覆盖、 敏感词分级、结构完整性、包名可信分级,可疑指纹进隔离区(Quarantine)。

8. 调试 / 观测入口

入口 看什么
应用 记忆屏 Episode 统计、宏技能数、近期情景、删除操作
AppLogger(core:logging) 摄取 / 蒸馏 / 回放的结构化日志(分类 LogCategory)
房间初始值 导出 MemoryGraphDatabase 的 Room 数据库可用 Android Studio App Inspection 查看

9. 相关页面

footer

🏠 返回首页 · 📚 文档索引 · ❓ FAQ · 🔧 故障排查 · 🗺️ 路线图 · 🐛 提 Issue

Android Guru Agent · v1.4.4 · Kotlin 2.0.21 · Compose · PRoot · Room

Clone this wiki locally