fix(LongMemEval): 让 L2 在保持可检索陈述的同时保留来源证据,避免抽取、分层和向量索引的静默失败,并确保扩大的 L2 不干扰去重。 - #42
fix(LongMemEval): 让 L2 在保持可检索陈述的同时保留来源证据,避免抽取、分层和向量索引的静默失败,并确保扩大的 L2 不干扰去重。#42openjiuwen-sync-bot[bot] wants to merge 4 commits into
Conversation
|
|
|
head_sha: 变更摘要本 PR 引入了一项可选的「无损源快照」(lossless source snapshots)功能:当配置项 主要改动
|
|
head_sha: 代码审查审查总结对全部 18 个变更文件逐一审查完毕。发现 2 个问题,均为 P2 级别,位于
各文件审查结果:
整体风险判断:中低。 核心 snapshot 功能的逻辑设计合理,
💬 仅评论 |
| self._kv.insert(scope, messages_key(u.id), dumps(u)) | ||
| insert_idempotently(u) | ||
| evicted = 0 | ||
| for key, _u in historical[self._recent_originals_limit:]: |
There was a problem hiding this comment.
head_sha: 9605580454c80012608285d2514f9277cbfa9e3c
🟡 Medium Priority
变更行:_persist_and_maintain_messages 的 insert_idempotently 内联函数(第 816-822 行)与删除循环(第 863 行)的交互。
证据链:
- 当
units中的某个单元在 KV 已存在(重试场景),其旧条目通过kv.list加载到historical中(第 836-841 行)。 - 由于
existing_keys集合已包含该 key,该单元不会被再次添加到historical(第 847 行if key not in existing_keys跳过)。 - 第 860-861 行先调用
insert_idempotently(u)—— 因内容相同,ConflictError被捕获,静默成功(no-op)。 - 第 863 行
for key, _u in historical[self._recent_originals_limit:]执行淘汰删除:若该单元的旧条目因t_ingest排序落到了保留窗口(默认 10 条)之外,其 key 被self._kv.delete删除。
失效模式: 重试时,若该单元原本在 /messages/ 的旧记录因其他新消息的插入被挤出保留窗口,insert_idempotently 的 no-op 不产生新记录,而后续删除循环会删掉唯一的旧记录——导致该消息从 /messages/ 静默丢失。旧代码在此场景会因 kv.insert 抛 ConflictError 而响亮失败;新代码静默丢数据,更危险。
建议:方案一(最小改动):在删除循环中跳过本轮 unit 的 key。在删除循环前构造 current_keys = {messages_key(u.id) for u in units},循环内 if key in current_keys: continue。方案二(语义更清晰):将 insert 移到删除之后执行,这样即使旧记录被淘汰也会被重新写入。
4c70206 to
ca5cb78
Compare
5dcf42f to
35155d2
Compare
Paired: GitHub #42 ↔ GitCode !158
What type of PR is this?
/kind
Self-checklist:(请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入)
本次修改为 infer=true 增加了默认关闭的无损 Source Snapshot:抽取成功后,每份原始输入只额外保存并索引一次,供普通召回补回 LLM 漏抽的信息,但不会参与后续抽取、L0/L1 分层、去重、合并、关联或遗忘;同时通过去重扩窗避免 Snapshot 挤占语义候选,并用确定性 ID 和幂等重试防止重复写入。