# 记忆与知识架构 > 本文定义 1.0 的记忆所有权、写入、版本、检索和上下文装配边界。字段与稳定枚举以 `docs/contracts/` 和后续 OpenAPI 3.1 为准。 ## 1. 边界 - `Message` 是不可被记忆覆盖的原始交流记录;编辑产生 Revision。 - `MemoryCandidate` 是待判定的提取结果,不参与正式召回。 - `Memory` 是稳定标识;`MemoryVersion` 是不可变内容版本,当前版本仅由 `Memory` 指针引用。 - `KnowledgeDocument` 保存外部资料和世界设定;其切片与索引是可重建投影,不冒充人物经历。 - Character baseline、用户资料、关系、知识和记忆分别建模;任何记忆策略都不能直接修改 CharacterVersion。 - 对话压缩、工作上下文和 Provider Prompt Cache 是运行期派生状态,不属于长期记忆。 - 1.0 不定义可绕过治理的 `WorkingMemory` 类型;当前分支消息和 Run 临时上下文始终按 Personal Domain/Workspace、Character、Conversation、Branch 与 Run 授权,不能因“临时”跳过隔离。 1.0 的权威记忆是可检查、可纠正的文本或结构化记录。KV cache、隐藏状态和模型权重适配不作为权威记忆,也不进入 1.0 记忆可携格式。 ## 2. 所有权与作用域 每条 Memory 必须属于且只属于一个授权边界: | 所有权 | 必需关联 | 可选关联 | 用途 | | --- | --- | --- | --- | | Personal Domain | `personal_domain_id` | `character_id` | 用户级或私密角色级记忆 | | Workspace | `workspace_id` | `character_id` | 经成员权限允许的协作记忆 | 约束: - `personal_domain_id` 与 `workspace_id` 二选一;在数据库层使用检查约束落实。 - `character_id` 只能引用同一所有权边界内的 Character。 - `conversation_id`、`message_id`、`content_block_id`、`run_id` 和 `tool_call_id` 是来源或适用条件,不是授权边界。 - 角色间共享通过显式授权和独立引用完成,不复制一份失去来源关系的 Memory。 - 子 Agent 只读父 Run 已批准的召回快照;默认没有创建、批准、纠正或删除长期记忆的能力。 - 社区 Release、市场交付物和推荐特征不得包含 Personal Domain Memory。Workspace 内容发布前同样经过独立发布审查。 ## 3. 记忆分类 1.0 只定义四类可解释长期记忆;稳定值登记在[协议与稳定标识](../contracts/README.md#memory_kind),并在实现前进入 OpenAPI/Schema: | 类型 | 含义 | 默认写入要求 | | --- | --- | --- | | `fact` | 可核对的人、事、状态或约束 | 有明确来源;冲突时生成纠正候选 | | `preference` | 用户或角色明确表达、或系统推断的偏好 | 显式与推断分开;推断偏好需要置信度 | | `event` | 带时间范围的经历或事件 | 保留时间语义和来源 | | `relationship` | 人物间关系及其变化 | 高影响,默认人工确认 | 身份基线、人格设定、权限、秘密、工具定义和知识文档不塞入上述类型。需要新类型时先更新契约和评测,不使用任意 metadata 绕过类型系统。 ## 4. 写入与版本 ```mermaid flowchart LR S[Source] --> E[Extract] E --> C[Candidate] C --> P{Policy} P -->|approve| V[MemoryVersion] P -->|review| H[Human review] H -->|approve| V P -->|reject| X[Rejected] H -->|reject| X V --> A[(Authoritative DB)] A --> I[Indexes] I --> R[Retrieve] R --> M[ContextSnapshot] ``` ### 4.1 来源 Candidate 至少记录: - 所有权边界、目标 Character(如有)和候选类型; - 精确来源引用,包括 Message/Block、KnowledgeDocument chunk 或 ToolCall 的 ID 与版本; - extractor、prompt、parser 和 policy 版本; - 候选正文、结构化时间、置信度、敏感度和创建时间; - 来源内容 hash 与候选 fingerprint,用于幂等和去重。 自动提取由 Message 完成后的 Outbox/Job 异步触发,不延长消息与 Run 的原子创建事务。重复消费相同来源与 extractor 版本必须返回同一候选或明确的去重结果。 ToolResult、网页、文件和模型输出都只是观察。它们可以产生 Candidate,但未经来源校验与 Policy 判定不能直接成为事实。 ### 4.2 审批 - 用户显式创建可直接进入批准流程,但仍执行 Schema、所有权、敏感度和冲突检查。 - 敏感资料、第三方个人信息、关系结论、高影响推断和隐式偏好默认需要人工确认。 - 低风险自动候选只有在策略明确允许的白名单内容上才能自动批准,并必须附带撤销窗(写入后一段时间内一键撤销且不留检索痕迹);策略版本必须进入审计。白名单外内容一律进入人工审核。 - Candidate 的批准或拒绝是幂等命令;批准时在一个事务写 Memory/MemoryVersion、AuditEvent 和 OutboxEvent。 - Candidate 不使用 `memory_status`;其生命周期与正式 Memory 分开定义。 ### 4.3 纠正与并发 - 创建、纠正、取代和恢复均创建新的 MemoryVersion,不原地覆盖历史内容。 - PATCH Memory 必须携带 `If-Match`;并发版本不匹配返回 `412 precondition_failed`。 - 用户纠正优先绑定上一次召回的 Memory ID/Version ID,避免仅凭自然语言重新搜索后误改同名记忆。 - 纠正后的旧版本保留谱系但不再参与召回;恢复旧内容也创建新版本。 - 删除立即阻止读取与召回,清除所有版本中的原文及派生索引,只保留不含原文的最小墓碑和审计元数据。 ### 4.4 归真作用域 记忆候选与手动入忆必须携带并保留来源界域 `canonical_scope`(见 [ADR-020](../decisions/README.md#adr-020对话三界与归真作用域)): - **真界**(`reality`):按既有候选、审批与敏感度规则进入角色正式经历记忆。 - **境界**(`world`):归真只形成该世界的知识候选(境忆),进入 KnowledgeDocument 与世界实体体系,不进入角色真界经历记忆,也不影响现实关系数据。 - **幻境**(`simulation`):不自动形成长期记忆候选;用户可将启发、观点或假设手动入忆,强制标注性质(事实/观点/启发/假设),且仍走敏感度与确认规则——幻境不得成为绕过敏感审批的通道。 界域来源不可事后静默更改;跨界引用只提供来源,不改变目标记忆的作用域。 ## 5. 衰减、有效期与整理 - `valid_from`/`expires_at` 表达事实有效期;过期版本在召回资格过滤阶段排除,但仍可按授权查看历史。 - 衰减只影响排序或生成归档候选,不静默改写、删除或降低用户已确认事实的真实性。 - 用户可固定重要记忆;固定状态仍不能绕过删除、撤权或有效期。 - 去重、合并、冲突检测和归档由异步 Job 执行,任务带租约与幂等键;失败不影响权威版本和在线对话。 - 自动整理结果仍是 Candidate 或新版本提案,不能绕过审批策略。 具体衰减函数和阈值必须通过评测确定,不在架构层虚构固定数值。 ## 6. 检索管线 检索严格按以下顺序执行: 1. 根据 actor、Personal Domain/Workspace 和 Character 在数据库查询层限定可见集合; 2. 过滤非 active、已过期、已撤权、已删除和被取代版本; 3. 并行生成全文、语义和结构化关系候选; 4. 按 Memory ID/Version ID 合并去重并重排; 5. 应用敏感度、用途、数据驻留和 Run 权限策略; 6. 按 token/条目/延迟预算选择进入上下文的结果; 7. 将召回证据固化到 ContextSnapshot,供用户解释和受保护诊断。 禁止先跨域全量召回再在应用层过滤。向量分数不能替代授权、来源可信度或有效期判定。 公开 Memory Search 只返回调用者有权查看的命中项,并包含命中版本、来源、各检索通道分数、重排结果、召回说明和是否进入上下文。被权限过滤的对象不能以计数、分数或错误细节泄露存在性。 ## 7. 上下文装配 上下文顺序沿用 [Agent 运行时](agent-runtime.md#7-上下文装配):工具定义 → 稳定指令 → 当前分支消息 → 获准记忆与知识 → 动态运行上下文 → 当前输入。 ContextSnapshot 对每个候选记录: - Memory ID、Version ID、来源引用和内容 hash; - 召回通道、原始分数、重排分数和策略结果; - 是否选中、未选原因、估算 token 和最终顺序; - 检索器、embedder、reranker、policy 与装配器版本。 ContextSnapshot 不保存隐藏推理。普通 Run API 只返回用户可理解的来源摘要;详细分数、排除原因和版本信息遵守 DiagnosticGrant。 ## 8. 索引与故障语义 - PostgreSQL/SQLite 中的 Memory、MemoryVersion 和来源关联是权威事实;全文、pgvector 和图关系是可重建投影。 - 权威事务通过 Outbox 驱动索引更新。索引延迟时,新版本可暂时降级为关系数据库检索,旧版本不得继续被召回。 - 删除与撤权事件优先于普通重建任务;消费者按 event ID 幂等。 - 无法证明索引已清除时,对目标 Memory fail closed,并记录待修复状态,不能继续返回旧结果。 - 图投影只用于结构化关系检索;没有量化多跳收益前不引入专用图数据库。 ## 9. 插件边界 Memory extractor、deduper、reranker、decay 和 context provider 可以由插件贡献。Core 始终负责: - 身份、所有权和授权过滤; - Candidate/Version 状态迁移与事务; - 敏感度、审批、删除、审计和 Outbox; - 插件输入输出 Schema、资源预算和版本快照; - 最终 ContextSnapshot 与召回证据。 插件只能提出 Candidate、分数或排序,不能直接写权威 Memory、扩大作用域、读取未授权来源或阻止删除传播。 ## 10. 评测与验收 WP-04 至少留下以下可重复证据: - **写入质量**:事实、偏好、事件、关系的提取 precision/recall,以及敏感内容错误自动批准率; - **召回质量**:长对话、多会话、时间推理、冲突纠正和多跳关系的 Recall@K、MRR/nDCG 与最终问答正确率; - **安全正确性**:跨用户、跨角色、跨 Workspace、跨 Conversation/Branch/Run、已删除、已过期和已撤权内容的召回率必须为 0;Candidate、来源 Prompt Injection 和插件输出不能扩大 scope 或绕过审批; - **可追溯性**:每个进入上下文的 Memory 都能定位到当前版本和未删除来源; - **恢复能力**:索引全量重建、重复 Outbox、乱序消费和删除重放后结果一致; - **性能成本**:写入延迟、检索 p50/p95、候选数、rerank 时延、上下文 token 和单次召回成本。 LoCoMo、LongMemEval 等公开数据集可用于回归,不替代 Hunjing 自有的中文、多角色、分支、敏感审批、删除和越权测试集。阈值在实现前通过基线实验写入发布门,不引用外部项目宣传分数作为验收结果。 ## 11. MemOS 采纳边界 参考基线:MemTensor/MemOS commit `28dfb4e7d3adad1c93fd5574675f913921367d36`,Apache-2.0。详细证据见[参考项目研究](../research/reference-projects.md#memos)。 采纳:类型化且可检查的记忆、来源追踪、分层检索、快速摄取后异步精炼、后台整理、基于已召回 ID 的纠正、可重复评测。 不采纳:把 MemCube 当作 Hunjing 授权边界、原地更新权威记忆、开放式 metadata 代替契约、运行时隐式建表、把向量/图存储作为事实源、保存或回放隐藏状态/KV cache、在 1.0 用参数记忆修改模型权重。