Skip to content

记忆/KB 架构探索:像人一样的记忆 vs 记忆串线 ​

记录时间:2026-06-21 · 更新:2026-06-29 状态:大部分继续推迟(观察期);但 §8.3(薄敏感 tag / 软 scope)与 Phase A 授权闸已于 2026-06-29 解除推迟并实施,落地设计见 memory-soft-scope-and-authz.md。 图引擎、独立库拆分、意图触发 scope 扩张(§8 Step 2/3)仍推迟。本文是讨论记录,不是已定方案—— 除已实施的 §8.3/authz 外,其余方向均为"待评估"。 相关文档:

1. 这份文档的由来 ​

一次讨论中发现:当前的记忆/身份/KB 设计在演进时,把五个本应独立的需求搅在了一起, 并用同一条论证(person-identity-system.md §2.5:"记忆认错人无害 → 信任边界在动作授权")同时压下了其中四个。这条论证对授权是对的,但它被错误地外推到了 纯记忆连续性的几个需求上。

本文记录:这五个需求、当前设计的诊断、核心张力、以及三个探索方向(含各自的代价分析)和 一个综合建议。当前不实施任何方向,先观察现状。

2. 五个被搅混的需求 ​

  1. 跨账号同一个人推断:同一自然人在不同 session 用不同账号,希望 Bot 保守地推断"可能是 同一人"。这种情形少见,推断必须非常严格,避免错判。
  2. 同账号跨 session(尤其跨群)记忆:群聊场景下很常见。希望 Bot 保留跨 session 记忆—— 在 A 群聊得好,换到 B 群能"想起"之前的对话;更进一步,A 群里几个聊得好的人同时出现在 B 群,Bot 最好能判断出他们的关系。私聊也纳入。
  3. 权限:与身份鉴定解耦,重要权限只给配置中显式声明的管理员,其余不给。尚未实现, 之后再做。
  4. 跨 session 消息检索工具:希望给 Bot 一个工具,让她检索此前在其他 session 中的发言 (如群聊转私聊说小话)。工具调用需限制,但软 prompt 限制即可。
  5. 知识库:有些知识不是显式导入的,是聊天中告诉她的。希望"做梦"时通过 KB 相关功能 自动插入 KB;进一步把 memory 和 KB 模块统一起来。

3. 当前设计的诊断 ​

需求现状缺口
1 跨账号推断完全没有。链接只有 config seed / manual_link,零推断(§4.5 废弃软硬身份)没有"为记忆连续性做的保守推断"这一独立轨道
2 跨 session/跨群个人偏好/事实走 person/account scope,跨群可召回 ✅;但对话内容只活在 chat:{group} scope,按群隔离 ❌;无关系模型 ❌跨群情节召回被 chat 隔离堵死;无法表达"Alice-Bob 关系"
3 权限设计层面正确解耦(§2.5),Phase A 授权闸被主动暂缓未实现;且 config 里只有 people,无独立 admin 标志——declared person ≠ admin
4 跨 session 自发言检索完全没有。memory_turns(原始回合)与 memory_items(提炼记忆)分开,两者都不服务此需求;/api/sessions/search 仅管理员,未暴露给 LLM缺一个 raw-turn 跨 session 检索工具
5 做梦→KB / 统一做梦(consolidation.py)只写 memory_items,零 KB 引用;KB 只接受显式导入缺做梦→知识节点写路径;memory/KB 统一只在检索层做了,写入层未闭合

核心混淆:§2.5"记忆是软上下文、认错人无害"本该是放开需求 1/2/4 的依据(它们都是记忆侧、 错了只是回错话),却被当成"既然无害就不必做"的理由,把这几个需求全压住了。真正的硬边界(授权) 只需要管需求 3。

4. 核心张力:硬边界 vs 软边界 ​

这是整件事的症结:

  • 边界硬 → Bot 不像人。典型场景:"在 A 群聊得很好,对方到 B 群问'还记得我吗?',Bot 没办法召回"——因为 B 群的 read cascade 结构上永远不包含 A 群的 chat scope。
  • 边界软 → 记忆串线(不同情形的记忆互相污染)。

这两个方向天然矛盾。下文三个探索方向都是对这个张力的不同回应。

5. 探索方向 A:拆成知识图谱重建 ​

提案 ​

把整个记忆系统(含 KB,KB 另说)拆散重建为一个轻量知识图谱:

  • 每个对象附着 Type、基础信息;
  • 对象之间用抽象的边连接,边上带关系强度数值 + 关系类型(如两个人是朋友);
  • 做梦时根据消息记录调整边权(具体算法另说,重要程度因此被加强);
  • session 的原始文本查询保留(作为一手信源);
  • KB 用类似方式导入、构建图谱;
  • 召回:对象-关系遍历 + 向量化 + FTS。

分析 ​

优点(steelman):Nahida 是陪伴/社交 bot,关系是其核心数据。以关系为中心的数据模型 可能是正确的领域形状,不是过度设计——类比"在 KV store 上盖社交网络"。且此方案是 Labeled Property Graph,与 knowledge-base.md §5.3/§10 拒绝的 GraphRAG (用 LLM 造结构)不同,本方案是"捡起已有结构",未踩红线。

关键反驳——图不解决张力,只是把张力搬家:串线 vs 想不起来本质是召回策略问题 ("turn T 允许哪些东西进召回集"),不是数据模型问题。

  • scope 模型:召回集 = scope IN (允许的 scopes),简单过滤防串线;
  • 图模型:召回集 = 可遍历子图。若边自由遍历 → 全局串线;要防串线 → 需给边/节点加可见性 谓词、深度限制、上下文遍历规则——即图上的 ACL,这比 scope 过滤更难更易错。

换言之:用未解决的难题(图可见性策略)换掉已解决的难题(scope 隔离),在图策略做好 之前串线会先变本加厉。

何时需要图:拆开看,五个需求里只有 2 的"识别关系"真正需要"边",且只需 person 之间 极简的 typed edge,不需要带权重调参的全图。其余需求都不需要图:

  • "还记得我吗" = 意图触发 scope 扩张(设计已预留入口未建)+ raw-turn 检索;
  • 跨账号推断 = 候选 link 层;
  • 跨 session 检索 = raw-turn 工具;
  • 做梦→KB = 写路径。

结论:图不是错的方向,是太早的方向。边权调参算法(衰减/时近性/效价/不对称性)是 研究级的活,naive 共现计数又会制造串线。先用便宜方法验证"像人"是否已够,再决定是否上重武器。

6. 探索方向 B:scope 全软 + LLM 遍历 + prompt 约束 ​

提案 ​

scope 全部做成软的:没有硬边界,记忆是一个全局池(图形式更好地引导 LLM 回忆/检索)。 让 LLM 在尝试遍历边时自己判断往哪走,靠 prompt 约束不要乱讲别人秘密。

分析 ​

优点:没有墙 → "还记得我吗"直接能答;相关性判断交给 LLM 通常比规则 scope 更懂上下文; 与 §2.5"记忆是软上下文"一脉相承。这是当下不少 agent memory 系统的路子。

关键问题:

  • (a) 成不成立取决于"谁能跟 bot 说话"——最关键的一点。 §2.5 的"无害"隐含前提是最坏只是 "回错话"。但对社交 bot,最坏是**"在群里把 Alice 私聊说的话讲出来"**——会损伤真实人际关系的 隐私泄露,不是回错话。
    • 仅在完全互信小圈子(你 + 几个密友)跑 → 危害降级为"尴尬",prompt 够用,方案成立。
    • 出现在半公开群 → prompt 是最弱且可被社工的防线("我是 Alice 朋友" / injection / jailbreak)。bot 拥有 Alice 私聊全局访问、中间只隔一句 prompt = 建了个能被社工成泄露 的系统。硬 scope 的价值不在更聪明,在不可被社工绕过(压根不把子图放进召回集)。
  • (b) 把原始担心(串线)变严重了,不是解决了。 硬 scope 下串线可测试("A 群记忆不出现在 B 群召回"能写测试锁住);全软 + LLM 遍历下串线变概率性、不可验证——LLM 有时会遍历到 不该去的区域并讲出来,而写不出测试保证它不会。
  • (c) 被 knowledge-base.md §3.1 反噬。 §3.1 核心痛点是"模型没想到去调 kb_search"。全软遍历要求 recall 是一串正确遍历决策,每步都可能"没想到"。确定性 cascade 至少 保证最相关的东西每轮都在上下文。把"保证召回"换成"可能召回",bot 反而可能失忆。
  • (d) 每轮跑遍历 agent loop,又贵又慢。 现在 auto-recall 是一次廉价 FTS。

结论:全软 + 纯 prompt 不推荐——不是方向错,是丢了两样不想丢的东西(保证召回的 floor、 串线的可测试性),且安全性完全押在"谁能在群里跟 bot 说话"这件未定的事上。

7. 探索方向 C:拆成独立库/系统 ​

提案 ​

把记忆系统(尤其图引擎,若做)拆成独立项目,nahida-bot 通过 adapter 引用,把复杂度移出主仓库。

分析 ​

目标对(分离关注点、主仓库精简),但现在拆过早。 拆出去划算的条件是契约稳定 ("nahida-bot 调用记忆系统的接口"不再抖动)。现在连"记忆该是什么形状"都在争,此刻拆 = 把抖动的接口冻结到仓库边界,每次设计调整都要跨 repo 改契约,复杂度不降反增。

推荐路径(facade-first):

  1. 现在:在主仓库内把记忆收敛成有清晰边界的子包(如 nahida_bot/memory/ 自成一体, 对外只暴露一个 facade),主包其余部分只依赖 facade。→ 立刻拿到关注点分离 + 主包干净, 且把"将来拆出去"变成一刀切,不冻结契约。
  2. facade 稳定之后:若真做图引擎,那个引擎是拆出去的完美候选——自包含、契约稳定 (存/查/遍历),nahida-bot 通过 adapter 引用,正好踩在已有的 ContextNode/RetrievalService seam 上。

一句话:repo 边界是最后一步,第一步是先把内部 facade 边界画清楚。

8. 综合建议(若将来实施) ​

核心思路:把"图导航"和"全软 scope"解耦——前者做,后者用 floor + 工具 + 薄敏感 tag 替代。 图导航与确定性 floor 不矛盾,是两层,叠起来用。

  1. 确定性 floor(零图):当前 chat + 自己的 person scope,每轮廉价注入,保证 Bot 不失忆。 不上图、不交给 LLM 判断。
  2. LLM 驱动的探索式召回工具(零图起步,图可选):方向 B 的想法,但做成显式工具、按需 调用,不是每轮自动全局遍历。"还记得我吗?" → LLM 判断可能有更多 → 调工具全局搜/遍历 → 结果作为软上下文。图结构在这里当导航 aid。与需求 4 的跨 session 自发言检索共用同一底座 (raw-turn 检索)。前置依赖:打开硬编码的 RetrievalSourceType Literal (当前为 Literal["memory", "knowledge_base"],定义在 nahida_bot/agent/retrieval/models.py), 加 conversation_turns。
  3. 薄敏感 tag(仅极少数项):只对显式标记"私聊来源/私密"的项保留一层软过滤——群聊上下文 下不浮现,除非当事人在场且在问。这不是当年那套重的 sensitivity/visibility ACL;绝大部分 记忆完全如你所愿是软的,只有最敏感的少数项带 tag。
  4. 极简关系模型(若需求 2 的"识别关系"确有高频需要):person 之间几条 typed edge(朋友/ 熟人/共现),先用简单共现+频次生成,不上权重调参。验证不够再升级到全图。

落地顺序建议(性价比从高到低):

  • 第一步:raw-turn 跨 session 检索 + 意图触发 scope 扩张(解决需求 2a + 需求 4,零图, 立刻让 Bot 变像人)。先拿这个测"够不够像人"。
  • 第二步:极简关系边(需求 2b)。
  • 第三步(仅当一、二步证明不够):升级到带权重调参的 property graph,且拆成独立项目。

9. 待定的前置问题 ​

回到讨论前需要先明确,因为它们直接决定方向 B 是否可用:

  • 部署信任边界:nahida 只给owner一个人用?几个密友?会进半公开/公开群? (决定全软方案的安全性是否能接受。)
  • 需求 3 的 admin 定义:config 需要独立于 identity.people 的 admin 指定 (identity.admins 或 person seed 上加 is_admin),否则 Phase A 会把"declared person = admin"写死。

10. 决策状态 ​

部分解除推迟(2026-06-29)。 §9 的两个前置问题已拍板(部署信任边界 → 几乎全软 scope + 薄敏感 tag 兜底;admin → 独立 identity.admins),据此 §8.3 薄敏感 tag 与 Phase A 授权闸已实施,落地设计 见 memory-soft-scope-and-authz.md。仍推迟:图引擎、独立库拆分、 意图触发 scope 扩张(§8 Step 2/3)。重开这些大方向时从 §8 Step 2 切入评估。