Skip to content

v7.0.2 — 精准记忆/召回/极限压缩

Choose a tag to compare

@MnemosyneOS MnemosyneOS released this 15 Sep 14:11
· 35 commits to main since this release

Mnemosyne OS 7.0.2 — 精准记忆 / 精准召回 / 极限上下文精确压缩

这一版的唯一目标:让「精准记忆 · 精准召回 · 极短上下文下的精确压缩」从声称的能力
变成可复现、可断言的事实。

为什么要出这一版

7.0.1 已经把向量模型与向量库接上了,但精准仍然达不到"可以承诺"的程度。深查之后确认:
问题不在参数没调好,而在机制本身——以下几条让"100% 精准"在结构上不可能达成:

# 症状 根因
P0-1 长会话「越聊越偏」,正确答案从 rank1 掉到 rank3 access_boost 是加性且上限 +0.20(与整路权重同量级),而计数对"凡进入结果列表"无条件累加
P0-2 无关查询也返回高分;一切"分数阈值"规则失效 五路打分各自 x/max(x) 归一化 → 最高分恒为 1.0 → 融合分没有绝对含义(实测无关查询 top1 1.0200 > 相关查询 0.6922),且旧行为无论如何填满 k 条
D1 graph_query("用户") 恒为空 抽取器把 用户的显卡是 RTX 4090 的主语抽成 用户的显卡 → 图节点永远不是 用户;5 路融合里权重 0.10 的图通道长期空转
D3 budget_tokens=40 实际塞进 150+ token 无分词器时兜底用「4 字符 ≈ 1 token」(英文经验值),中文被低估 3~4 倍 → 压缩降级路径永不触发
D6 同一条偏好被反复重述 → 库里堆多条 0.98+ 重复 写入侧无语义去重(只有事后 dedup)
D7 熔断窗口内的向量写入被静默丢弃,那批记忆永久失去语义索引且无人察觉 插件 add() 裸 return(返回 None),调用方无法区分"成功 / 真失败 / 被丢弃"
D8 正确答案因"多了一个字"丢掉图通道的分 记录侧图节点取自 entities 的中文滑窗碎片,切出什么高度依赖字数对齐 —— 本质是抽签
D9 边的 memory_id 全是 NULL → "这条记忆连了哪些图节点"永远查不到 add_edges(memory_id=…) 对 dict 型边完全忽略该参数
D10 正文里写了日期反而被扣分 时间通道用正文抽出的 event_time:"购于 2026-03-15"被衰减到 ≈0.24,而"备用显卡"(无日期)拿 1.00
D11 纯改写问句被相关性下限误杀(问"我喜欢什么"得到"没有相关记忆") 改写对余弦 0.4900 与无关项 top1 0.5275 分布重叠 → 单一阈值无法两全,必须靠结构化标签通道兜住

新增:AIC 记忆胶囊(Adaptive Information Capsule)

问题的本质:用户端上下文常常只有 1~2 轮、几百 token。传统做法把"压缩"等同于
"丢记忆"(模型看不到信息)或"生成式摘要"(有损改写,会凭空造出原文没有的数字/时间/
结论)——两者都让"精准"变成概率事件。

这一版的做法:把压缩重新定义为「分层 + 可寻址」。压缩产物不是更短的近似文本,而是

{稳定指针 ref} + {结构化事实} + {内容原子} [+ {抽取式要点}]

由此同时满足三条可断言的硬性质:

性质 含义
无损可逆 ref 指回原文;expand(ref) 逐字取回,并校验内容哈希(错指针/被改写的记录不会被静默交付)
零幻觉 要点是抽取式的(句子必须逐字来自原文),事实来自规则三元组,全程不做任何生成
事实守恒 数字 / 日期 / 金额 / 型号 / URL / 邮箱 / 引号原话("原子")在所有压缩层级都完整保留

分层阶梯:full(原文)→ gist → facts → pointer → atoms(仅指针+原子)。
指针与原子永不裁剪——它们分别是"可逆"与"事实不丢"的唯一凭据。
于是"预算不够"不再是"信息消失",而是"精度分层":预算再小,可被追问的事实
(多少钱、什么时候、哪个型号)依然在场。

胶囊是内容寻址的:同一记忆在同一预算下产出逐字节相同的胶囊 →
上游 LLM 的前缀/KV 缓存能稳定命中。省钱与"精准"在这里不冲突。

新增 MCP 工具

  • capsule:取单条记忆的胶囊(预算内),返回 text / ref / level /
    atoms / tokens / min_tokens / lossless / over_budget + 自检结果。
  • expand:按指针逐字取回原文,返回 verified(哈希校验)。
  • recall_health:召回质量只读指标 —— 空结果率 / top1 分趋势 / 相关性下限剔除量 /
    置信带与通道分布 / 延迟分位 / 向量后端成败 / 胶囊缓存命中率 / 图边规模 / 最近 20 轮明细。
  • 工具数 18 → 20(7.0.1 为 14)。

修复清单

  • P0-1 access_boost:加性 +0.20 → 乘性、封顶 +5%;计数语义收窄为"融合分 ≥ top1 的
    90% 才 +1"、上限 5。实测对照:仅因"先前问过 6 个无关问题",干扰项 +0.12
    (= 6 × 0.02,与公式逐位吻合)——这是"越聊越偏"的直接机制,上下文再大也救不了。
  • P0-2 相关性下限:阈值由实测标定(相关簇 cosine min 0.5222 / 无关簇 max 0.4064
    → REL_MIN_SEMANTIC=0.45),未过线者在排序之后剔除(不动候选下标,避免与倒排/doc_tf
    的下标语义错位)。允许返回空结果:对 Agent 而言"没找到相关记忆"比"给 5 条无关记忆"安全得多。
    边界:目标定位(forget / 更正 / dedup)走 apply_floor=False —— 用户描述天然含糊,
    返回空等于"无法遗忘";安全性改由 dry_run 先行 + 报告带置信带保证。
  • 置信带跨调用污染(本轮新发现):_relevance_band 挂在跨调用共享的索引记录 dict 上,
    导致"取完结果 A 后再发一次无关查询 B"会把 A 的置信带静默改写(实测复现)。
    修法:输出边界做快照(返回副本)+ 每轮打分前清标记 + 缓存命中重贴 + sync_record 保持
    访问计数会话内一致。
  • 图通道:模式化正则优先(A的B是C → 主语取 A、属性进 qualifier)+ 主语去定语归一 +
    查询侧代词归一(我/我的→用户)+ 邻接图多跳。实测 graph_query('用户') 由空 →
    10 个邻居节点;并新增存量数据图边懒回填(幂等)——只修抽取器只能让新写入有图,
    老记忆仍然查不到,"改好了"必须真的能被用户看到。
  • budget_tokens 真正参与取舍:continue → prefix packing;装不下原文时
    降级为胶囊而非丢弃,装不进正文的进 precision_index(指针+原子,不占正文预算)。
  • 预算口径诚实:改用 CJK 感知的保守估算(CJK 逐字计 1、拉丁按词计 1),
    避免"预算 40 却塞进 150+ token"的假通过。
  • 写入侧语义去重 + 原子守恒硬约束:近似重复(≥0.95)并入既有记忆(内容以最新为准、
    tags 取并集、置信度取高者、version+1);但凡"改一个字就是另一个事实"的片段不同者,
    相似度再高也绝不合并 —— 否则"用户的年假是 5 天"会吃掉"…15 天",数据没丢但事实被改错,
    且用户与审计都看不出发生了什么。方向取舍:宁可漏合并,绝不误合并。
  • 编码单一收口:sanitize_str() 成为唯一实现(sqlite_backend._sanitize 委托调用),
    带按来源计数;订正 encode(errors='replace') 用 ?(U+003F) 而非 U+FFFD。
  • 向量写丢弃可见化:插件 add() 返回布尔,丢弃原因分开计数
    (dropped_breaker 可重试 / dropped_unavailable / dropped_no_collection);
    doctor 新增 vector_ops / vector_backend(含熔断器剩余时间)/ graph 三段。
  • F9-b 确证修复:recall 输出投影带出 superseded_by(实测)。
  • 内容原子补 num3 / ident 两条规则:6333、1024、bge-m3、gpt-4o、H100
    这类"取值与身份标识"过去不算原子("嵌入模型是多少维"的答案 1024 会被丢掉);
    并把计数归一为"原文里的字面出现次数",消除多规则命中同一片段的计数膨胀。

验收(全部实测,三套缺一不可)

验收 结果
scripts/verify_recall_quality.py(端到端质量对照,需真实向量栈) 10/10 通过
— precision@1 8/8(冷启动)· 8/8(预热后)· 8/8(先问 4 个无关问题后)· 8/8(先问 28 个无关问题后)← 7.0.1 同类实验退化到 6/8
— 假阳性 无关查询返回 0 条(7.0.1 行为是无论如何填满 5 条)
— 极短上下文 30 token 预算下 8/8 问句的关键取值仍可见
— 延迟 召回 p50 0.21 ms
scripts/verify_memory_lifecycle.py(MCP stdio,需真实向量栈) 35/35 通过
scripts/verify_precision_recall.py(离线回归,不连外部服务) 94/94 通过
分层阶梯 实测 full → gist → pointer → atoms 随预算收缩逐级降级
expand 可逆性 逐字往返字节一致(116/116);错哈希被拒(verified=false)
py_compile 60 文件 / 0 失败
文档完整性 96 处版本声明升级;含 127.0.0.1 的行零破损

为什么必须三套都跑:只有离线跑通,不代表 MCP 面可用;只有 MCP 跑通,
也不代表机制没退化("分数全塌到常数底"时 MCP 断言仍可能全绿);
而前两者都通过,也不代表排序正确 —— D8–D10 就是这样躲过前两套、
最终被"端到端质量对照"照出来的。

兼容性

记忆库格式、MCP 协议版本、CLI 命令面、配置文件全部不变,已有记忆库可直接沿用。
存量数据会在首次 recall / graph_query 时自动补齐图边(幂等)。

相关性下限的复标定(0.45 → 0.55)

初版 0.45 在8 条记忆(无关项与查询毫无话题交集)上标定,太乐观;补上同主题干扰项
("备用显卡"/"病假天数"/"备用端口")后复标定:

阈值 无关查询放过的条数 相关查询正确答案保留
0.45 5 8/8
0.55 0 8/8
0.60 0 7/8(丢掉那条真答案)

已知边界:相关簇下沿(0.5708)与无关簇上沿(0.5275)只差 0.043,该阈值对语料分布
敏感。因此 recall_health 新增 sem_top1 / sem_background 供发现"整库同主题"
后复标定。

已知未做(诚实标注)

  • 词表/键控注入式数据投毒、跨用户推理数据泄漏(memory/claim 的信任边界)
    仍属 7.0.1 已标注的开放项,本版未触碰。
  • 纯改写且与库内内容无词面/标签锚点的问句,可能被判为"无相关记忆"(实测该情形余弦
    0.4900 与无关项 top1 0.5275 分布重叠,单一阈值无法两全)。本版用标签通道兜住了
    偏好/意图类(最常见的一类),更泛化的改写仍可能落空 —— 这是刻意的保守取舍
    (返回空比给错证据安全)。
  • 图通道仍为规则抽取(无 LLM 参与):中文复杂句(多从句、省略主语)的召回率有限,
    它只是 5 路融合中权重 0.10 的一路,不承担主要召回职责。

English summary: 7.0.2 turns "precise memory / precise recall / precise compression under
tiny context" from a claim into an assertable fact. It fixes the mechanisms that made it
structurally impossible (access-count feedback loop, missing relevance floor, dead graph
channel, no-op token budget, dishonest token accounting, silent vector-write drops) and adds
AIC memory capsules: compression is redefined as layered + addressable — a stable
pointer plus structured facts plus "atoms" (numbers, dates, amounts, model IDs, URLs) that are
preserved at every level, with expand(ref) returning the original verbatim and
hash-verified. Extractive only, so zero hallucination; content-addressed, so byte-identical
capsules keep upstream KV caches warm. Acceptance: 34/34 lifecycle assertions (real vector
stack) and 94/94 offline precision assertions. Backward compatible; existing stores keep working.