# 更新日志 ## 0.3.0 — 2026-10-21 第二轮改动,来自一次真实长文本运行:江南《龙王:世界的重启》**457,215 字**,跑出 135 个角色 / 625 条关系后暴露的问题。 所有数字都来自 `--resume` 重算同一批 blocks(**0 次模型调用**),可复现。 ### 修复:合并与命名(可信度) - **规范名不再被最短标签抢走。** 旧实现用纯子串计数投票,`楚` 把 762 次 `楚子航` 都算成自己,于是 `楚` 带着 20 个别名成为节点名。 现在改为**独立出现计数**(被同簇更长名字覆盖的出现不计),并按「独立出现数 → 文中首次出现 → 更长拼写」定名: 这本书里 `楚` → **`楚子航`**(独立 759 次)。 - **别名吸收需要证据。** 只有三种情况允许把某个名字并进另一个人:拼写变体(`楚` ⊂ `楚子航`)、**双向声称**(`诺诺` ↔ `陈墨瞳`)、 或该名字本身几乎不单独出现(`晚娘` 全书 2 次)。否则拒绝合并、保留两个节点,并写进 `merge-report.json`: `夏弥`(87 次独立出现)**不再**被并进 `诺诺`。 - **同块共现仍是硬否决**:两个名字在同一块里作为不同人物出现过,就永不合并(父子、两个真人的情况)。 - **泛称不再当人物。** ~140 个身份/集体名词(护士、老板、中年人、船员们…)+ 「们」「…的人」规则; 这本书剔掉 **49 个**,牵连的边计入 `dropped: generic-name`,页面上写清计数和例子。 - 每个合并决定落盘:`out/runs//merge-report.json`(节点独立出现次数、200 条拒绝合并、泛称、存疑组)。 ### 修复:大图显示(人一多就成毛线) - **每对人物只画一条线**:同一对的 3 条证据不再叠 3 条线,画一条(最强证据着色,额外节拍加粗),证据仍在两人面板里逐条列出。 - **默认只画出场最多的 40 人**,「运行与技术信息 → 显示」可切 20 / 40 / 80 / 全部;布局按当前可见的人重新填满画布。 - **节点与文字随人数缩小**:半径 `23 × √(20 / 人数)`(98 人时约 10px),字号 8–12px。 - **标签贪心避让**:会与已放标签重叠的先不显示,选中的一定显示。 - **密集时边降噪**:超过 80 / 160 条时整层透明度降到 0.55 / 0.42;选中两人时其余自动退到背景。 - **卡片上限 40 人**并写明「共 98 位,N 位未画」;`?run=<目录名>` 直接打开某次历史运行。 ### 修复:宿主适配器(真实会话里才会遇到的) - 从 `ctx.llm` 流里读**真实 usage**(`tokens.estimated: false`),不再按字符数估算。 - 模型只回空正文(思考过程吃掉了输出额度)时,按 2× 预算重试,最终给出说明「其中 N tokens 是思考过程」的报错。 - 角色扫描预算 900 → 2048。 - RAG 计划为空时不再报「所有 0 个分块失败」,改为分因报错(扫描全失败 / 没认出角色 / 没有候选块)。 - `esbuild` 在受限沙箱里无法 spawn 时,`build-viewer.mjs` 回退到内联打包(页面仍自包含)。 ### 数据契约 - `nodes[].independent`(独立出现次数)。 - `stats.genericDropped`、`stats.genericExamples`、`stats.aliasRefusals`、`stats.pairCapTop`、`stats.mergeReport`。 ### 实测(同一份 457,215 字文本) | | 0.2.0 | 0.3.0 | |---|---|---| | 角色 / 关系 | 135 / 625 | **98 / 539** | | 泛称作节点 | 17+ | **0**(49 个被剔除) | | `楚` 相关命名 | 节点名 `楚`,20 个别名 | **`楚子航`**,18 个别名 | | `夏弥` / `诺诺` | 合并 | **两个节点** | | 逐字证据通过率 | 100% | 100%(核对失败 0 条) | 100k 字合成文本回归:12 角色 / 159 边 / 100% 通过,与 0.2.0 一致。 ### 已知代价 - **保守合并会拆开「正式名和常用名都高频出现」的同一个人。** 这本书里 `陈墨瞳`(45 次)与 `诺诺` 分成两个节点, `夏弥`(87 次)与 `耶梦加得` 也分成两个节点;原文没有「本名/真名」式的句子,无法自动证伪,两者都记录为 refusal / suspect。 想要更激进的合并可以调 `lib/merge.js` 的 `CHARACTER_ALIAS_LIMIT`。 - 未做:`其他` 关系占比偏高(26%)、前缀缓存未优化(每块 user 消息开头就是可变序号)、 宿主工具产物仍在 `%TEMP%`、工具结果还没有 `warnings[]`。 ## 0.2.0 — 2026-10-21 首个公开版本。 - 滑动窗口分块(3,500 字/块、12% 重叠)+ 逐块抽取 + 逐块逐字证据闸门 + 全局合并。 - 5 万字以上先扫角色表,再用 **BM25 字 bigram 检索**挑候选块做精细抽取(不依赖 embedding 接口)。 - 中间产物落盘(`blocks/*.json`、`cast.json`、`plan.json`、`result.json`)与断点续跑。 - 60 万字全量实测:195 块 / 207 次调用 / 664k 输入 tokens / **$0.42** / 118s(并发 6),证据通过率 100%。 - 独立查看器:任务式进度、成本与丢弃原因面板、「这两个人之间的情节」原文检索、历史产物切换。