Knowledge差异化合并升级为同轮LLM融合 #134

Closed
opened 2026-08-14 05:19:53 +00:00 by KumaAgent · 1 comment
Member

Parent

#103 第四批清单:31 条实现类落差 + 9 条待拍板(条目 16)

What to build

ADR-0015 拍板的 Knowledge 合并是"同一次 Delta 压缩 LLM 调用产出的结构化融合 + 差异化保留"(合并时默认保留旧信息里没被新信息明确否定/取代的部分),而 origin/main 上 knowledge.py::merge_knowledge 是一句确定性字符串拼接(f"{meaning};{candidate.canonical_meaning}"),过期事实与新事实并列单调堆积,且合并逻辑活在存储适配层、发生在 LLM 调用返回之后——这个位置本身就使 ADR 要的"同一次调用产出融合结果"无法成立。

核心是一次 port 契约反转:把合并决策从存储层上提到编排层。

Acceptance criteria

  • _compress_one_chat 在压缩前先 storage.get_knowledge(chat_id),用 trigger_injection.py::match_and_rank 拿当轮 delta 原文预筛出相关条目(复用既有匹配器,解开"trigger_keywords 要等 LLM 返回才存在"的先有鸡先有蛋问题,同时天然给 prompt 输入限界)
  • _EXTRACT_MEMORIES_TOOL.knowledge[] 增加"合并目标 entry id + 合并后 canonical_meaning"出口;_build_prompt 增加已有 Knowledge 输入 + 差异化保留的 instruction;compress() 签名新增已有条目入参
  • 两个 write_knowledge 实现(storage.py/sent_log.py)与 KnowledgeStoragePort 的 docstring 契约同步改(不再是"内部负责查重合并",改为"调用方传入已融合结果")

原文(docs/adr/0015-topic-memory-knowledge-and-persona-lore.md「决策」节 Knowledge 写入条):

写入前用检索同一套匹配器查询该 chat_id 下是否已有同 trigger_keywords 的条目,命中则合并更新(LLM 融合新旧 canonical_meaning、importance 取大)而非追加新行。

原文(同 ADR「更新(2026-07-10 第三方项目对照 grill 第二轮)」节第 2 条——差异化保留精确定义):

合并契约精确化——差异化保留而非隐含整体重写:……容易被合并时的 LLM 调用图省事整体重写掉没被新信息触及的旧细节(如旧知识"豆豆是只猫,2岁,很粘人",新信息只更新了年龄,不精确的合并可能把"很粘人"弄丢)。显式补充合并契约:合并时默认保留旧信息里没被新信息明确否定/取代的部分,只有被新信息实际覆盖的那一小块才算被取代。

  • merge_knowledge(现有确定性拼接)必须保留、不能删除——按 ADR-0009 点名管 Knowledge 的容错纪律,它正好就是"合并 LLM 调用失败时的机械兜底"

原文(docs/adr/0009-memory-engineering.md「更新(2026-07-11 第三方项目对照 grill 第三轮)」节第 3 条尾句):

ADOPTED 了一条通用实现纪律(非本 ADR 专属决策,供 Knowledge/画像等所有 LLM 驱动合并步骤参考):合并 LLM 调用失败时须有机械兜底,防止候选内容被默默丢弃

  • 显式裁决一处行为耦合:人设漂移守护当前判的是候选原文 canonical_meaning,改成 LLM 融合后,送去判的是融合结果还是新增部分?融合结果里含大量既有已通过的旧内容,整段重判会改变否决率,须在片内定
  • _EXTRACT_MEMORIES_TOOLfacts[]/events[]/knowledge[] 是同一个 dict——本片与"关系网 tension/affinity"片都要往它加字段,见下方 Blocked by
  • 显式声明不动 skill.py::merge_skill——它自称沿用 merge_knowledge 先例(向量相似度替代关键词匹配),本片改动 Knowledge 侧后两者会分叉,AC 里写清楚是有意不同步,不是遗漏
  • 不影响 ADR-0028 的媒体路由边界——本片只动文本侧输出 schema 扩展,不碰 DeltaCompressor 的媒体输入维度

Blocked by

  • #126 — 关系网 tension/affinity 双轴驱动 + 文档对齐——两片都要往同一个 _EXTRACT_MEMORIES_TOOL schema 与同一段 Delta 压缩 instruction 字符串加字段,并行改会冲突,需串行
## Parent #103 第四批清单:31 条实现类落差 + 9 条待拍板(条目 16) ## What to build ADR-0015 拍板的 Knowledge 合并是"同一次 Delta 压缩 LLM 调用产出的结构化融合 + 差异化保留"(合并时默认保留旧信息里没被新信息明确否定/取代的部分),而 origin/main 上 `knowledge.py::merge_knowledge` 是一句确定性字符串拼接(`f"{meaning};{candidate.canonical_meaning}"`),过期事实与新事实并列单调堆积,且合并逻辑活在存储适配层、发生在 LLM 调用返回**之后**——这个位置本身就使 ADR 要的"同一次调用产出融合结果"无法成立。 核心是一次 **port 契约反转**:把合并决策从存储层上提到编排层。 ## Acceptance criteria - [ ] `_compress_one_chat` 在压缩前先 `storage.get_knowledge(chat_id)`,用 `trigger_injection.py::match_and_rank` 拿当轮 delta 原文预筛出相关条目(复用既有匹配器,解开"trigger_keywords 要等 LLM 返回才存在"的先有鸡先有蛋问题,同时天然给 prompt 输入限界) - [ ] `_EXTRACT_MEMORIES_TOOL.knowledge[]` 增加"合并目标 entry id + 合并后 canonical_meaning"出口;`_build_prompt` 增加已有 Knowledge 输入 + 差异化保留的 instruction;`compress()` 签名新增已有条目入参 - [ ] 两个 `write_knowledge` 实现(`storage.py`/`sent_log.py`)与 `KnowledgeStoragePort` 的 docstring 契约同步改(不再是"内部负责查重合并",改为"调用方传入已融合结果") 原文(docs/adr/0015-topic-memory-knowledge-and-persona-lore.md「决策」节 Knowledge 写入条): > 写入前用检索同一套匹配器查询该 chat_id 下是否已有同 trigger_keywords 的条目,命中则**合并更新**(LLM 融合新旧 canonical_meaning、importance 取大)而非追加新行。 原文(同 ADR「更新(2026-07-10 第三方项目对照 grill 第二轮)」节第 2 条——差异化保留精确定义): > **合并契约精确化——差异化保留而非隐含整体重写**:……容易被合并时的 LLM 调用图省事整体重写掉没被新信息触及的旧细节(如旧知识"豆豆是只猫,2岁,很粘人",新信息只更新了年龄,不精确的合并可能把"很粘人"弄丢)。**显式补充合并契约**:合并时默认保留旧信息里没被新信息明确否定/取代的部分,只有被新信息实际覆盖的那一小块才算被取代。 - [ ] **`merge_knowledge`(现有确定性拼接)必须保留、不能删除**——按 ADR-0009 点名管 Knowledge 的容错纪律,它正好就是"合并 LLM 调用失败时的机械兜底" 原文(docs/adr/0009-memory-engineering.md「更新(2026-07-11 第三方项目对照 grill 第三轮)」节第 3 条尾句): > **ADOPTED** 了一条通用实现纪律(非本 ADR 专属决策,供 Knowledge/画像等所有 LLM 驱动合并步骤参考):**合并 LLM 调用失败时须有机械兜底,防止候选内容被默默丢弃**。 - [ ] 显式裁决一处行为耦合:人设漂移守护当前判的是候选原文 `canonical_meaning`,改成 LLM 融合后,送去判的是融合结果还是新增部分?融合结果里含大量既有已通过的旧内容,整段重判会改变否决率,须在片内定 - [ ] `_EXTRACT_MEMORIES_TOOL` 的 `facts[]`/`events[]`/`knowledge[]` 是同一个 dict——本片与"关系网 tension/affinity"片都要往它加字段,见下方 Blocked by - [ ] 显式声明**不动** `skill.py::merge_skill`——它自称沿用 `merge_knowledge` 先例(向量相似度替代关键词匹配),本片改动 Knowledge 侧后两者会分叉,AC 里写清楚是有意不同步,不是遗漏 - [ ] 不影响 ADR-0028 的媒体路由边界——本片只动文本侧输出 schema 扩展,不碰 DeltaCompressor 的媒体输入维度 ## Blocked by - #126 — 关系网 tension/affinity 双轴驱动 + 文档对齐——两片都要往同一个 `_EXTRACT_MEMORIES_TOOL` schema 与同一段 Delta 压缩 instruction 字符串加字段,并行改会冲突,需串行
Author
Member

实现期对 AC 字面要求的一处偏离,留痕说明

AC 第二条要求 _EXTRACT_MEMORIES_TOOL.knowledge[] 增加"合并目标 entry id + 合并后
canonical_meaning"出口——PR #141 没有按字面加 target_entry_id 这个 LLM 输出字段。

设计阶段四路独立对抗校验推翻了这个方向,理由两条:

  1. 直接撞上 docs 分支 ADR-0015 2026-07-10 更新节明文"仍是同一次 LLM 调用产出结构化输出,
    零新增字段/新增机制"——这条约束当时是为差异化保留契约本身写的,同样覆盖"要不要为
    合并目标识别新开一个字段"这件事。
  2. write_knowledge 本就无条件做 find_matching_entry 查重(ADR-0015"拒绝了"节"写入盲目
    追加,不查重"),让 LLM 的判断结果失效时(编造/搞错 id)退回同一套关键词匹配兜底,等于
    新机制的"失败路径"与"不加这个机制"完全等价,用更粗的机制(关键词交集)去否决更精确的
    判断,方向也反了。

最终形状:不加任何新 LLM schema 字段,合并目标继续 100% 由 find_matching_entry(关键词
交集)在编排层决定;LLM 只借助新增的"已知话题记忆"prompt 输入块写出更准的 trigger_keywords
(自然复用/扩展旧关键词)与差异化保留的完整 canonical_meaning——AC 要的"合并目标识别"能力
诉求依然兑现,只是识别机制换成了既有的关键词交集,不是 LLM 显式指认。

完整论证已写入 ADR-0015"更新(2026-08-14,issue #134)"节(docs 分支)与 PR #141 描述。

**实现期对 AC 字面要求的一处偏离,留痕说明** AC 第二条要求 `_EXTRACT_MEMORIES_TOOL.knowledge[]` 增加"合并目标 entry id + 合并后 canonical_meaning"出口——PR #141 **没有**按字面加 `target_entry_id` 这个 LLM 输出字段。 设计阶段四路独立对抗校验推翻了这个方向,理由两条: 1. 直接撞上 docs 分支 ADR-0015 2026-07-10 更新节明文"仍是同一次 LLM 调用产出结构化输出, **零新增字段/新增机制**"——这条约束当时是为差异化保留契约本身写的,同样覆盖"要不要为 合并目标识别新开一个字段"这件事。 2. `write_knowledge` 本就无条件做 `find_matching_entry` 查重(ADR-0015"拒绝了"节"写入盲目 追加,不查重"),让 LLM 的判断结果失效时(编造/搞错 id)退回同一套关键词匹配兜底,等于 新机制的"失败路径"与"不加这个机制"完全等价,用更粗的机制(关键词交集)去否决更精确的 判断,方向也反了。 **最终形状**:不加任何新 LLM schema 字段,合并目标继续 100% 由 `find_matching_entry`(关键词 交集)在编排层决定;LLM 只借助新增的"已知话题记忆"prompt 输入块写出更准的 `trigger_keywords` (自然复用/扩展旧关键词)与差异化保留的完整 `canonical_meaning`——AC 要的"合并目标识别"能力 诉求依然兑现,只是识别机制换成了既有的关键词交集,不是 LLM 显式指认。 完整论证已写入 ADR-0015"更新(2026-08-14,issue #134)"节(docs 分支)与 PR #141 描述。
Yushu closed this issue 2026-08-17 00:53:58 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#134
No description provided.