Skip to content

Latest commit

 

History

History
546 lines (360 loc) · 16.9 KB

File metadata and controls

546 lines (360 loc) · 16.9 KB

核心记忆系统设计文档

目的

为 Chatbox 增加一套长期记忆系统,使应用能够在多轮会话之间保存少量、高价值、可长期复用的信息,并在后续对话中稳定召回与使用。该系统既要支持用户画像类记忆,也要支持助手工作方式、项目约定、环境经验等系统级记忆,同时避免把普通聊天流水、附件内容和一次性任务错误地写入长期记忆。

本设计文档同时作为需求文档与技术设计文档,后续实现、测试与交互设计都应以此为准,并遵循 00.rules.md 中的通用规范。

适用范围

  • 适用于聊天主流程中的长期记忆读写与管理。
  • 适用于桌面端 Chatbox 的前后端联动实现。
  • 适用于记忆设置页、记忆管理页以及主对话运行时的记忆注入。

不包含:

  • 短期上下文窗口管理。
  • 对图片、PDF、网页、代码、日志本身做知识库存储。
  • 面向通用文档检索的大规模 RAG 系统。

设计目标

  1. 让模型在新对话中记住用户稳定信息、重要计划和长期偏好。
  2. 让模型记住与当前应用、项目和工作方式相关的长期约定。
  3. 让记忆在回答前自动参与推理,但不破坏主聊天链路的稳定性。
  4. 让记忆写入尽可能自动化,同时保留清晰的人工管理能力。
  5. 在没有向量能力时仍可用,在启用 embedding 后可获得更好的召回质量。
  6. 保持架构简洁,优先服务当前 Chatbox 场景,而不是过度设计成通用知识平台。

核心原则

1. 记忆不是聊天流水

长期记忆只保存会在未来持续影响对话质量的信息,不保存一次性请求、普通寒暄、工具输出和外部素材内容。

2. 核心记忆优先

系统优先维护一小组高密度、可直接注入系统提示词的核心记忆,而不是无限膨胀的记忆列表。

3. 读写解耦

回答前做检索召回,回答后异步做记忆编码,二者互不阻塞。

4. 失败不影响主流程

记忆模块任何一步失败,都不能导致聊天主流程失败,只允许降级或静默跳过。

5. 规则约束与模型判断结合

系统通过边界规则过滤明显不该保存的内容,同时把“是否值得记住”“新增还是替换”的语义判断交给专用 Memory Agent。

6. 渐进增强

第一层能力依赖 SQLite + FTS 即可运行;向量召回、生命周期管理、冲突处理作为增强能力逐步加入。

术语定义

1. 核心记忆(Core Memory)

直接注入主 Agent 系统提示词的小规模长期记忆块,用于稳定传达用户画像和系统长期约定。

2. 检索记忆(Retrieval Memory)

回答前按当前用户消息动态召回的历史记忆片段,只在本轮对话中作为背景信息使用。

3. 用户记忆(Target=user)

用户身份、长期偏好、稳定事实、重要计划、长期状态等。

4. 助手记忆(Target=memory)

与项目、工作环境、工具经验、用户明确要求长期遵守的工作方式相关的记忆。

5. 记忆编码

对本轮用户消息做长期价值判断,并在合适时写入、替换或删除记忆。

总体架构

系统采用“两层记忆 + 两阶段处理”的结构:

  1. 启动阶段加载记忆存储、检索器、生命周期管理器。
  2. 每次发起聊天时,把核心记忆快照注入主 Agent 的系统提示词。
  3. 回答前,按当前用户消息检索相关记忆,并作为背景上下文注入。
  4. 回答完成后,异步调用 Memory Agent 对本轮消息进行记忆编码。
  5. 后台周期性执行巩固、遗忘和矛盾检测。

逻辑分层

1. 存储层

职责:

  • 持久化记忆数据。
  • 提供增删改查、分页、统计、软删除能力。
  • 提供 FTS5 / LIKE 检索与 embedding 存储能力。

2. 检索层

职责:

  • 基于关键词、全文索引、向量相似度和元数据进行混合召回。
  • 对召回结果做打分、排序和裁剪。

3. 记忆代理层

职责:

  • 执行记忆读写的语义判断。
  • 决定是否新增、替换或忽略一条潜在记忆。
  • 处理相对时间到绝对时间的转换需求。

4. 主聊天集成层

职责:

  • 在聊天前注入 core memory 与 retrieval memory。
  • 在聊天后异步触发记忆编码。
  • 将记忆系统作为可配置能力挂接到主聊天链路。

5. 管理与生命周期层

职责:

  • 提供记忆管理页面与设置入口。
  • 维护 embedding 配置、统计、忘却、重要度提升和冲突处理。

数据模型设计

长期记忆应以单表为核心,使用统一的数据结构承载用户记忆与助手记忆。

记忆主表字段

  • id:主键。
  • summary:记忆标题,用于概括与辅助检索。
  • content:完整记忆文本,要求将时间、地点、人物、情绪、约束等都直接写入自然语言内容。
  • type:记忆类型,枚举值为:
    • fact:长期稳定、不易变化的事实。
    • information:可变化的偏好、状态、习惯、背景信息。
    • event:带时间锚点的具体事件或计划。
  • target:记忆目标,枚举值为:
    • user
    • memory
  • source:来源,例如 agentmanuallegacy
  • char_count:记忆内容长度,便于核心记忆容量控制。
  • embedding_id:关联 embedding 记录的主键,可为空。
  • is_forgotten:是否已遗忘。
  • recall_count:被召回次数。
  • last_recalled_at:最后一次召回时间。
  • last_used_at:最后一次使用时间。
  • created_at / updated_at:时间戳。

历史兼容字段

允许保留旧版本遗留字段,仅用于数据迁移与兼容读取,不再作为新版本写入结构的一部分。

embedding 表字段

  • id
  • memory_id
  • vector
  • model_name
  • dimensions
  • schema_version
  • created_at
  • updated_at

容量规则

核心记忆需要受限,避免无限膨胀:

  • target=user 总字符数限制为 1375。
  • target=memory 总字符数限制为 2200。

超限时不允许直接新增,应优先替换、合并或删除旧条目。

核心模块设计

1. Memory Storage

职责:

  • 负责记忆表与 embedding 表的初始化与迁移。
  • 提供记忆写入、替换、软删除、恢复、分页查询、统计查询。
  • 提供 core memory 快照渲染能力。
  • 提供 FTS5 检索与 LIKE 降级检索。

要求:

  • 所有数据库操作必须收敛在 backend/storage 或记忆子存储模块中。
  • 需提供明确的错误返回,供上层做降级处理。

2. Core Memory Renderer

职责:

  • target=usertarget=memory 分别渲染核心记忆块。
  • 将当前已生效记忆组合为可直接注入主 Agent system prompt 的文本。
  • 展示当前容量使用情况,便于后续调试和管理。

输出要求:

  • 文本结构稳定。
  • 内容精炼。
  • 不包含内部实现细节和数据库字段。

3. Hybrid Searcher

职责:

  • 先用 FTS / LIKE 做文本召回。
  • 在 embedding 可用时增加向量召回。
  • 结合重要度、信任度和时间新鲜度做综合排序。

打分因素至少包括:

  • 文本匹配得分
  • 向量相似度得分
  • 时间衰减得分
  • 重要度
  • 信任度

4. Memory Agent

职责:

  • 作为专用代理负责长期记忆的读写策略。
  • 在检索模式下,通过 read_memoryget_current_time 等工具返回精简的相关记忆列表。
  • 在编码模式下,根据用户最新消息与现有记忆快照做 add / replace / remove / no-op 判断。

约束:

  • 不向用户暴露内部工具、字段名、数据库 ID 或系统实现。
  • 相对时间必须先换算为绝对日期。
  • 不能把图片、文件、网页、代码、日志等外部素材内容存为长期记忆。

5. Memory Runtime Tools

主 Agent 运行时需要暴露两类记忆相关工具:

  • memory
    • 仅用于核心记忆管理。
    • 动作为 add / replace / remove
    • 目标为 user / memory
  • session_search
    • 用于搜索历史聊天中的一次性信息。
    • 与 core memory 区分开,避免长期记忆被滥用为全量会话存档。

6. Memory Lifecycle Manager

职责:

  • 定时提升高频召回记忆的重要度。
  • 检测疑似矛盾记忆并调整旧记忆信任度。
  • 对低价值、低信任、少召回的记忆执行自动遗忘。

说明:

  • 第一版允许使用启发式规则。
  • 生命周期任务必须是后台异步任务,不能阻塞聊天入口。

核心流程设计

1. 启动流程

  1. 初始化主数据库连接。
  2. 初始化 memory storage。
  3. 自动迁移记忆表与 embedding 表。
  4. 执行历史字段迁移。
  5. 初始化混合检索器。
  6. 根据设置决定是否恢复 embedding 能力。
  7. 启动生命周期管理器。

2. 聊天请求前流程

  1. 读取应用设置,确认记忆系统是否开启。
  2. 渲染 core memory 快照。
  3. 将 core memory 追加到主 Agent 的 system prompt。
  4. 根据用户输入抽取关键词。
  5. 使用 Hybrid Searcher 检索相关记忆。
  6. 将召回内容格式化为 <memory-context> 背景块。
  7. 注入到当前用户消息前方或多模态消息的文本部分前方。

要求:

  • 召回内容只作为背景,不可视为新的用户输入。
  • 注入内容必须进行围栏清洗,避免嵌套污染。

3. 聊天响应后流程

  1. 判断本轮是否为普通主链路结束。
  2. 复制本轮消息上下文,异步触发记忆编码。
  3. 提取最后一条用户消息。
  4. 判断是否有非文本附件,是否属于对外部内容的问答。
  5. 若值得分析,则把“现有核心记忆快照 + 最新用户消息”交给 Memory Agent。
  6. 由 Memory Agent 决定新增、替换、忽略或删除。
  7. 若有新记忆写入,后台补齐 embedding 并刷新缓存。

要求:

  • 编码必须是异步的。
  • 同一时刻只允许有限的编码并发,避免资源争抢。
  • 任意 panic 或错误都不能影响本轮聊天结果。

检索策略设计

1. 检索触发

  • 只要用户消息不是空消息或极短噪声,就应尝试记忆检索。
  • 不依赖固定关键词表作为触发条件。

2. 关键词提取

  • 基于标点、空格进行切分。
  • 对极短消息执行短滑窗拆分,提高短句召回率。
  • 对结果去重并限制数量。

3. 召回顺序

  1. 优先使用混合检索。
  2. 若无 embedding,则使用 FTS5。
  3. 若 FTS5 不可用或命中为空,则降级为 LIKE。
  4. 若仍无结果,则返回少量最重要记忆作为兜底。

4. 结果格式化

每条记忆格式化为:

  • [日期] 标题:内容摘要

要求:

  • 控制总长度,避免过度占用上下文窗口。
  • 单条内容过长时需要截断。

写入策略设计

1. 允许写入的内容

  • 用户明确要求记住的信息。
  • 用户的稳定身份、偏好、约束、背景、沟通习惯。
  • 用户未来会反复提及的重要计划、决定、安排。
  • 项目约定、环境坑点、长期工作方式。

2. 禁止写入的内容

  • 图片、文件、PDF、网页、代码、日志、表格本身的内容。
  • 工具调用结果、搜索摘要、引用内容。
  • 助手自己的解释、推断、复述。
  • 普通寒暄、确认、一次性命令、单轮任务。
  • “这张图里有什么”“这个文件说了什么”这类对外部素材的问答内容。

3. 时间处理

  • 所有相对时间表达必须在写入前转换成绝对日期。
  • 最终写入 content 的文本必须能脱离上下文独立理解。

4. 去重与合并

第一原则:

  • 语义去重主要依赖 Memory Agent。

执行方式:

  1. 编码前先把现有核心记忆快照注入给 Memory Agent。
  2. 若同主题信息已有记录,应优先 replace 合并。
  3. 只有确认不存在对应条目时,才允许 add

数据库层可保留轻量保护:

  • 对完全相同标题做精确拦截,避免重复插入。

5. 多模态输入保护

当用户消息带有图片、文件等非文本输入时:

  • 如果用户是在询问附件内容本身,不做记忆编码。
  • 如果消息中包含长期有效的用户披露,则允许只提取该披露参与编码。

生命周期管理设计

1. 巩固

  • 对高频召回的记忆提升重要度。
  • 目标是让真正常用的记忆在后续更稳定地被召回。

2. 矛盾检测

  • 对标题高度相似但内容冲突的记忆做疑似矛盾标记。
  • 当前版本可采用简化规则,例如摘要前缀相似但内容不同。
  • 处理方式优先为降低旧记忆信任分。

3. 遗忘

  • 对长期未召回、低重要度、低信任度的记忆做软删除式遗忘。
  • 遗忘应具备保护条件,避免误删高价值或近期新增内容。

4. 可恢复性

  • 自动遗忘的记忆不是物理删除,而是 is_forgotten=true
  • 用户可在管理页面手动恢复。

配置与开关设计

系统至少需要支持以下设置项:

  • 是否启用记忆系统。
  • 是否启用向量检索。
  • embedding provider。
  • embedding base URL。
  • embedding API key。
  • embedding model。

行为要求:

  • 关闭记忆系统后,聊天主流程不进行记忆注入与异步编码。
  • 关闭向量检索后,自动回退到纯文本检索。
  • embedding 配置变更后,需要重建检索器并触发后台补齐。

前端管理需求

1. 记忆设置入口

需要提供记忆系统相关设置页,至少包括:

  • 总开关
  • 向量搜索开关
  • embedding 配置表单
  • 状态与统计展示

2. 记忆管理页面

需要提供记忆管理页,支持:

  • 分页查看记忆
  • 按关键词筛选
  • type 筛选
  • target 筛选
  • 查看已遗忘记忆
  • 手动编辑记忆
  • 手动删除与恢复记忆

3. UI 规则

界面必须遵循项目基础规范:

  • 提供浅色、深色两种主题
  • 支持显示大小档位适配
  • 所有文案需要国际化,至少支持简体中文和英文

后端接口需求

后端需要提供以下能力:

  • 获取记忆列表
  • 获取单条记忆详情
  • 更新记忆
  • 删除记忆
  • 恢复记忆
  • 获取记忆统计
  • 配置 embedding
  • 禁用 embedding
  • 获取可用 embedding provider 列表

接口要求:

  • 公共服务方法按项目现有 Wails 绑定风格设计。
  • 错误返回遵循项目统一错误约定。
  • 方法与 DTO 命名遵循 00.rules.md

异常与降级策略

1. 存储初始化失败

  • 记忆系统整体禁用。
  • 主聊天功能继续可用。

2. embedding 初始化失败

  • 自动降级为 FTS / LIKE。
  • 在日志中记录失败原因。

3. 检索失败

  • 不注入 retrieval memory。
  • 本轮对话继续执行。

4. 编码失败

  • 不写入本轮记忆。
  • 本轮对话继续执行。

5. 生命周期任务失败

  • 跳过本轮后台维护。
  • 不影响前台聊天和记忆读写。

非功能性要求

  • 稳定性:记忆模块不得阻塞主链路。
  • 可维护性:存储、检索、代理、生命周期职责清晰分离。
  • 可扩展性:后续可增加更强的冲突检测与多级记忆能力。
  • 可观测性:关键步骤需要日志记录,包括初始化、降级、召回、编码、补齐 embedding。
  • 性能:检索与注入需控制上下文体积;embedding 回填应后台批量执行。

实现边界建议

第一期必须实现:

  • 记忆主表与 CRUD
  • core memory 注入
  • retrieval memory 召回
  • 回答后异步编码
  • FTS / LIKE 检索
  • 记忆管理页
  • 记忆开关与 embedding 配置

第一期可简化实现:

  • 启发式生命周期规则
  • 基础矛盾检测
  • embedding 回填策略
  • 更细粒度的时间解析
  • 基于用户确认的记忆审核模式
  • 更强的历史会话搜索与记忆联动

后续演进方向:

  • 更稳健的语义冲突合并
  • 多级记忆体系

验收标准

  1. 当记忆系统开启时,新的聊天请求能够自动附带核心记忆快照,且主 Agent 可稳定利用这些信息进行回答。
  2. 当用户输入与历史长期记忆相关时,系统能够在回答前召回相关记忆,并以背景信息形式注入,不把它当作新的用户输入。
  3. 回答完成后,系统能够异步分析最后一条用户消息,并在符合规则时写入或更新长期记忆;失败不会影响本轮回复结果。
  4. 对图片、文件、网页、代码等外部素材内容的问答,不会错误写入长期记忆。
  5. 在未配置 embedding 的情况下,系统仍能通过 FTS / LIKE 正常工作;配置 embedding 后可触发向量补齐与混合检索。
  6. 用户可以在管理页面查看、筛选、编辑、删除、恢复记忆,并看到基础统计信息。
  7. 记忆相关设置、管理界面文案全部支持简体中文和英文,并适配浅色、深色主题。
  8. 生命周期任务可在后台运行,对重要度、信任度和遗忘状态进行维护,且不会阻塞主聊天链路。

变更记录

  • v1.0:初始版本,定义核心记忆系统的目标、架构、数据模型、运行流程、管理能力与验收标准。