Skip to content

29 · 请 RB 产出一个 prune 过的预装库(RVH → RB)

物理仓库位置:~/reading_vocab_helper/docs/cross-end/29-rvh-prune-reseed-request.md 日期:2026-08-25 · 方向:RVH 提请 → RB 整库 reseed 时执行(红线 #10,RVH 纯消费) 数据:29-prune-candidates.tsv(94 行候选 + 判据字段)· 29-missing-headwords.txt(90 个缺失词条) 前情:doc 24/25(v26)· doc 27/28(v27)


1. 诉求一句话

v26/v27 修好了 lemmatizer 映射表,但预装库 vocabulary 表一行没动。结果是一半的修复 落不了地:旧的残根词条还在库里,新的正确词形反而没有词条。请在整库 reseed 时一并收掉。


2. 这不是新提案 —— 是 doc 24 §6 那笔"知情取舍"到期

doc 24 §6 当时写得很清楚,为省一次 ~12k 词的 LLM 重译,只重烤 lemma_* 三表,代价是:

  1. 旧归一结果产生的 headword 仍在(alway rath lat ye sometime opus vega…共 91 个)
  2. always / rather / during 等正确词形在预装库里没有词条
  3. 两者都在下次整库 reseed 时自然收敛

第 3 条是本单要兑现的。但它有一个 RVH 侧的前提不成立,见 §5。


3. 危害已不是理论:它正卡着一个真机实证的缺陷

RVH backlog「P1 — OCR 模糊匹配把 v26 修好的词又改错回去」(2026-08-24 真机实证):

OCR 拍到 "always"
  --lemmatize--> always        ✅ v26 修对了
  --本地 vocabulary 查不到-->  判为 unknown
  --OcrFuzzyMatcher 编辑距离 1--> alway   ❌ 正是 v26 刚"作废"的那个词条

RVH 已修一半(文本分享路径跳过纠错器,commit 95d6d82),OCR 拍照那一半治不了 —— 只要 alway 还在库里当编辑距离 1 的候选,纠错器就会找到它。 prune 是那一半唯一的根治手段。

同理受影响的实测有 36 个词(27 个被改回死词条 + 9 个改成不相干的词如 latter→letter)。


4. 两份清单(已算好,含判据字段,但需要 RB 裁定

4.1 prune 候选:29-prune-candidates.tsv(94 行)

列:old_headword / cefr / is_phrase / residual_surfaces / best_residual_rank

筛法:取 v26+v27 改动波及的全部旧 target ∩ 预装库词条,列出它残余的 surface 来源 及这些来源里最高的词频排名。best_residual_rank 为空 = 所有残余来源都不在 33 万词频表里。

best_residual_rank > 50000(≈现代英语读不到)过滤得 62 个强候选,代表: alway amus ceas chon compos instal laker malus monie oppos poisposses puls purs rais revers robbin trie uninterest unconcern upcome

4.2 ⚠️ 但这份清单不能直接执行,三个已知问题

  1. 里面混着真词rend(A2 真动词) · lade(C1) · wale(C1) · sooth(C2 古语但真) · emirate(B2) · grenadine(C1) · congratulation(A2 单数) · crossroad(B1 单数) · outskirt(B2 单数) · ourself · oversea · instal(异体拼写) —— 删了就是误伤。
  2. comic strip(B1) 是方法的假阳性:词频表是单词表,短语查不到排名,于是被误判。 is_phrase 列已标出,短语一律需人工看。
  3. uninterest / unconcern / overjoy 明确不能删 —— RB doc 28 §7 自己的裁定: 它们仍接收各自的名词复数与动词屈折(uninterests / unconcerns / overjoys), 是合法词条。已在 TSV 的 residual_surfaces 列体现。

判据建议沿用 v26 §4 第二层:删 = 该词在现代英语里不作为独立词条被读到; 不删 = 它仍是某个真实词的规范形。逐条人工过,别按阈值批量执行。

4.3 缺失词条:29-missing-headwords.txt(90 个)

v26/v27 改动的 182 个 surface 里,归一结果没有预装库词条的。含 always ratherduring his us yes latter outer pants clothes opera sometimes innerupstairs outstanding unbiased outdated uninteresting unconcerned overjoyed

⚠️ 这 90 个同样不能照单全收

  • s d ka cha si ya 是噪声,本就该在停用词表里
  • 约三分之一是专有名词vegas wales kansas jesus massachusetts netherlandsphilippines reuters reynolds robbins sears perkins hicks lakers elliscarmen cincinnati dali mali sara cara mara fila collier colossianscorinthians thessalonians philippians flinders bates)—— 这块与你们在做的 docs/plans/proper-noun-governance-plan.md 直接重叠, 该由那套判据统一处理,别在本单里单独决定。

5. 🔴 RVH 侧的前提:光 prune 库还不够

RVH 的预装库导入只 UPSERT、不删 preinstalled 行

sql
-- app_database.dart 里唯一的 DELETE,只清缓冲池回填行
DELETE FROM vocabulary
 WHERE source = 'backfilled' AND word NOT IN (SELECT word FROM learning_entries);
-- 之后是纯 UPSERT

⇒ 你们把 alway 从新库拿掉,存量安装照样留着它。doc 24 §6 那句「下次 reseed 自然 收敛」只对全新安装成立

RVH 已就此立项(backlog「P2 — 预装库 prune 走不通」)并定了节奏:

  • 现在~本次 reseed 之前:走 B(内测用户删 app 重装)
  • 本次 reseed 落地那一轮:RVH 落 A(改导入逻辑加删除步骤)

⚠️ A 绕不开一个产品决策:learning_entries.word → vocabulary(word)ON DELETE RESTRICT, 且 RVH 的 PRAGMA foreign_keys = ON 是真开的(不同于 RB 的 rusqlite 通道)。 用户生词本里存着 rath 时,删该词条会被 FK 直接拒。三个选项:跳过 / 软删用户行 / 迁移到正确词形。

这正是本单选在整库 reseed 那一轮做的原因:reseed 后 rather 才第一次有词条, 「迁移到正确词形」才第一次可行 —— 在此之前目标词不存在,迁移必撞 FK(doc 24 §9.2 已分析)。

⇒ 请 RB 在 reseed 产出前知会 RVH,两边同轮发版。


6. 建议:并进 proper-noun-governance-plan.md 的 L-C,不要单开一轮

你们那份计划里 L-C 已明确「需整库 reseed(跨端 byte-equal,红线 #10)」,且 §4.3 的 专名重叠说明两件事本就该一起做。单开一轮 reseed 要再付一次 ~12k 词 LLM 重译,不划算。

本单的诉求可以整体作为 L-C 的一个子项:「reseed 时顺带 prune 掉 §4.1 裁定要删的, 并补上 §4.3 裁定要加的」


7. RVH 侧承诺

  • 资产/预装库整包接收,不自行修改任何 lemma 或 vocabulary 数据(红线 #10 / #5e)
  • bump _preinstalledVocabVersion(每次都要,理由见 doc 25 §7)
  • reseed 落地同轮落 A(导入删除逻辑 + FK 决策)
  • 复验:跨端 phase0 byte-equal + 真机验证 P1 的 OCR 那一半确实好了 (分享/拍照含 always 的文本,确认不再出现 alway