记忆与知识
任务状态、用户偏好和外部资料都可能影响一次回答,但它们不应使用同一种存储和加载机制。aibuddy 将三类信息分别保存在任务、用户和文档作用域,并在进入模型工作集之前执行不同的筛选。
三类信息使用不同作用域
| 信息系统 | 适合保存 | 生命周期 | 进入当前任务的路径 |
|---|---|---|---|
| 任务上下文 | 当前目标、计划、工具结果和执行状态 | 单个任务 | 由运行时装配,并在达到阈值后压缩 |
| 用户记忆 | 稳定偏好、行为反馈和不可重新获取的项目背景 | 单个用户、跨任务 | 先选择轻量索引,再读取命中的正文 |
| 知识库 | 需要保留来源和章节结构的资料 | 个人或系统范围 | 发布并挂载到任务后,由知识子 Agent 按需读取 |
例如,“本次报告使用简洁格式”只影响当前任务;“以后所有周报都使用简洁格式”可以成为用户记忆;公司制度则应保留为可审核、可引用的知识文档。作用域分离避免将临时状态固化为长期偏好,也避免用无来源的记忆代替正式资料。
记忆是可维护的用户记录
每条记忆是一个独立的 Markdown 记录。frontmatter 保存名称、描述、类型、来源与召回统计,正文保存完整内容。当前类型用于表达信息用途,而不是简单复刻对话主题:
| 类型 | 保存内容 |
|---|---|
user | 用户角色、专业背景和稳定偏好 |
feedback | 用户对 Agent 工作方式的纠正或确认 |
project | 无法从项目文件或连接系统重新获得的长期项目背景 |
reference | 外部系统、页面或资料位置的引用 |
显式记忆工具写入的来源为 manual,后台提取的来源为 auto;来源由系统设置,模型不能自行声明。新建和更新使用不同操作,更新会保留原始来源、recallCount 和 lastRecalledAt,从而避免同名覆盖破坏记录连续性。
Agent 可保存、召回、更新或删除单条记忆。清空全部记忆属于用户侧管理能力,不暴露为 Agent 记忆工具,避免一次模型调用移除整个用户记忆集。
记忆按用户隔离,并独立于任务沙箱持久化。存储层只需要实现列出、读取、写入和删除四类窄接口,因此文件系统、对象存储或数据库可以复用相同的维护与召回语义。
召回先选择索引,再读取正文
运行时不会把全部记忆加入每次模型请求。当前召回分为三个步骤:
- 扫描记忆 frontmatter,构建只含类型、文件名、更新时间和简短描述的 manifest。
- 独立的轻量模型根据当前请求,从 manifest 中选择明确相关的记录。
- 校验文件名后读取所选正文;当前单次最多返回 5 条。
这条路径将“判断相关性”和“加载完整内容”分开:选择器可以进行语义判断,而长期记录只有命中后才占用主任务上下文。模型选择不可用时,记忆工具仍可退化为基于描述和正文的词面匹配;选择或读取失败返回空结果,不中断主任务。
当前索引窗口最多扫描 200 条记忆,并按最近修改时间排序。成功召回会更新 recallCount、lastRecalledAt 和文件活跃时间,使仍在使用的记忆继续留在活跃窗口中。记忆工具结果参与后续推理时会压缩为命中数量和状态,完整命中内容仍可在客户端展示,但不会在后续步骤中反复占用输入。
自动提取是一条受约束的写入路径
后台提取不会把每次对话总结成记忆。任务结束时,系统只检查最近 3 组用户与助手消息,并先用确定性线索判断其中是否可能包含稳定信息。没有偏好、身份、反馈或持续项目线索时,不会启动模型提取;最近消息已经显式调用记忆写入、更新或删除时也会跳过,避免重复维护。
候选信息还必须满足“与用户或持续项目相关、预计持续有效、无法从文件或连接系统重新读取”。写入前继续执行冲突处理:
- 丢弃低显著性候选。
- 与现有内容等价时不执行写入。
- 同类型描述相似度达到当前阈值
0.6时复用原记录,避免近重复文件。 - 自动提取不能覆盖
manual来源的记忆。 - 更新沿用原文件名、来源和召回统计。
因此,自动提取是一个“线索门控—模型判断—相似性合并—来源保护”的协调过程,而不是对话归档。任何阶段失败都会被记录并跳过,不影响任务完成。
知识必须先发布,再进入任务
知识导入保留 Markdown 结构,并解析标题层级、稳定章节锚点、行范围和估算大小。文档摘要用于建立轻量文档地图,它以非阻塞方式生成:摘要失败不会丢失正文,也不会阻断审核流程。
新导入或重新摄取的文档进入 pending,只有 ready 文档可用于 Agent 检索。系统范围文档由管理员审核,个人范围文档由其所有者管理;正文变更会重新解析目录并使旧摘要失效。这样,未经确认或结构仍有问题的资料不会直接进入回答路径。
一次检索最终还要同时满足三个条件:
- 文档处于
ready状态; - 当前用户对系统或个人文档具有可见权限;
- 文档已包含在当前任务选择的知识集合中。
任务中的知识选择是一项可编辑资源。用户调整后,新集合从下一条消息开始生效,已经生成的历史消息保持不变。
知识正文按地图、大纲和章节逐级展开
aibuddy 不会在任务开始时加载所有知识正文,也不会把底层知识工具直接铺到主 Agent。只有能力可用且任务实际挂载了文档时,系统才提供内置知识子 Agent;文档导航在其独立上下文中完成。
| 阶段 | 内部工具 | 暴露的信息 | 决策目的 |
|---|---|---|---|
| 文档地图 | 任务初始化 | 标题、范围、摘要和章节数量 | 选择需要检查的文档 |
| 文档定位 | read_doc / search_docs | 目录或带章节锚点的搜索结果 | 确定相关章节 |
| 证据读取 | read_section | 一个有界章节页、子章节与后续游标 | 读取回答所需正文 |
search_docs 在章节级别排序结果,兼顾英文词、中文字符与双字组合,并支持带引号的精确短语;同一章节只返回一个代表片段,避免重复命中淹没结果。read_section 使用稳定锚点定位正文,并以游标分页限制单次读取规模。
渐进式披露使知识规模和单次上下文成本解耦:文档可以持续增长,模型只展开与当前问题有关的部分。知识子 Agent 最终向主 Agent 返回综合答案、文档标题和章节引用;知识库未覆盖问题时,它会明确报告缺失范围,而不是用通用知识补全。完成检索后,中间正文可被压缩,只保留文档与章节指针用于追踪。
设计边界
- 用户记忆适合保存稳定的用户特定信息,不是无来源事实库,也不应复制可从项目文件重新获得的内容。
- 知识库适合结构化、可审核的资料,不用于隐式记录用户偏好或当前任务进度。
- 知识搜索采用章节结构和关键词排序,而非向量分块;它优先服务结构清晰的内部文档,不宣称覆盖所有语义检索场景。
- 当前知识导入支持标准 Markdown 和 UTF-8 纯文本;PDF、DOCX、OCR 等格式需要先转换。
- 记忆选择、自动提取与摘要生成均为辅助模型路径;失败时采用空结果、词面召回或跳过更新,不阻断主任务。
实现锚点
| 设计职责 | 对应模块 |
|---|---|
| 记忆记录、来源保护与召回统计 | MemoryService |
| manifest 语义选择 | memory-recall |
| 自动提取、去重与冲突处理 | memory-extraction |
| 知识发布、可见性和章节检索 | KnowledgeService |
| 隔离的渐进式知识读取 | knowledge-subagent |
这些模块通过窄接口组合:更换持久化实现或轻量模型不会改变任务上下文、用户记忆和知识文档之间的作用域边界。