Skip to content

预装短语库 reseed 交接(RVH → RB)

RVH Phase 1 完成,交 RB 启动 Phase 2。 对应 RB 简报:~/reading-browser/docs/cross-end/06-rvh-phrase-library-brief.md RVH 计划:rvh/docs/plans/phrase-library-rvh-phase1-plan.md 日期:2026-06-07


1. 发布物

DB 文件assets/databases/reading_vocab.db
SHA25622ee5f1f0a9ebd850c68a3d0e29d51847e0db5f55b51edfbe1bb9ed448c070fd
_preinstalledVocabVersion16 → 17
schema不变(短语复用现有列,无 schema 变更)
词库总量12291 → 18899(+6611 短语,3 条合并入既有行)

⚠️ DB 文件 sha 每 build 变(created_at 时间戳);RB reseed 比 pos_definitions 内容,文件 sha 仅供完整性校验。


2. 交接回填表(对应简报 §4.1)

目标RVH 实际值
phrasal_verb 条数~1,000–2,0001861
idiom 条数~500–1,0005336(见下注)⚠️
含 gloss + 中文 translation 占比100%100%
primary_cefr_level 占比尽量高0%(有意不产,见 §4)ℹ️
frequency_rank 占比尽量高99%
word 经 lemmatizer 归一100%100%(normalizePhrase,逐 token)
仅存连续基础形(无屈折 / 无可分离)
byte-equal 整包覆盖(确定性双跑校验通过)
_preinstalledVocabVersion bump17
basic(默认排除)条数(新增项,见 §3)400

idiom 超目标说明:LLM 按 commonness 评分后,库纳入阈值取 commonness ≤ 3(丢 c4-5 生僻尾巴 2607 条)。idiom 的 c2-3「真常用」比简报预估多,故 5336。降噪由 RB 在高亮层用 frequency_rank 阈值控制(见 §3),库大小与高亮密度解耦——这正是简报「frequency_rank 做降噪阈值」的设计。RB 可只高亮 frequency_rank ≤ 4000(commonness ≤ 2)起步,按体验调。


3. 字段约定(RB 消费要点)

每条短语 = 一行 vocabulary

  • word:归一后基础形短语(逐 token lemmatize + 单空格 + NFC)。
  • word_tags:JSON 数组,含 phrasal_verbidiom互不互斥,可并存)。
  • basic tag(超出原简报的新增契约):标记「太简单=系统默认排除」的短语(如 go on/give up/find out)。共 400 条。语义见 §3.1。
  • pos_definitions:单 POS key "phrase"definitions[],每条 {gloss, translations:{zh}}覆盖度驱动义项:idiom 多为 1 条,常用 PV 1–5 条(如 get up 5 义:起床/站起/攀登/增强/组织)。
  • frequency_rank:commonness×2000 代理(commonness 1→2000 … 3→6000)。越小越常用,与单词 rank 同向。RB 据此降噪。
  • primary_cefr_level:NULL(短语不产 CEFR)。
  • emoji / ipa / etymology / word_forms:NULL。

3.1 basic = 系统默认排除短语(决定 A,需 RB 协调)

「太简单」短语保留入库但标 basic,作为系统默认排除集。落地复用 RVH/RB 已有的 v42 recommended_excluded_words 机制(Supabase 公共表 → 确定性 id merge 进 per-user excluded_words → 同步 + 统一 UI):

  • RVH 已产 artifacttools/vocabulary_builder_v3/output/recommended_excluded_phrases.jsonl(400 条,{word(归一), sort_order, tags})。
  • 需 RB/Supabase 协调动作:把这 400 条短语加进 Supabase 公共表 recommended_excluded_wordsword 用 artifact 里的归一形,保证与 vocabulary.word 同归一 → merge 命中)。
  • ⚠️ 这是对简报 §5「无 Supabase 动作」的有意偏离——经双方确认采用(复用现成排除机制,零新增逻辑,UX 与排除词统一)。recommended_excluded_words 是全端共享表,策展归属/时机请 RB 确认
  • RB 运行时:有效排除 = (在用户 excluded_words) OR (该短语 basic 且未被用户捞回);basic 短语默认不高亮。

4. 归一一致性(红线 #9)—— 20 条样例(对应简报 §4.2)

RB Phase 2 须实现逐字符等价的 normalize_phrasesplit_whitespace → lemmatize 每 token → join " " → NFC),用同输入复算确认 diff 为空。完整回归集:test/data/phrase-normalize-regression.txt(35 条)+ RVH 输出 tools/vocabulary_builder_v3/output/rvh-phrase-normalize.csv

#原始短语入库 word(归一后)说明
1Looking Intolook into大小写 + 屈折
2LOOKS INTOlook into全大写
3looked intolook into屈折
4gives upgive up屈折
5gave upgive up不规则过去式
6giving upgive up-ing
7took offtake off不规则
8taking offtake off-ing
9running outrun out双写 -ing
10look forward tolook forward to3-token
11looking forward tolook forward to3-token 屈折
12put up withput up with3-token
13came up withcome up with3-token 不规则
14runs out ofrun out of3-token 屈折
15break the icebreak the iceidiom
16breaks the icebreak the iceidiom 屈折
17piece of cakepiece of cakeidiom(注:Kaikki 词条无冠词 a)
18a dime a dozena dime a dozenidiom
19raining cats and dogsrain cat and dog⚠️ 逐 token lemmatize 致字面变形,跨端一致即可
20déjà vudéjà vuUnicode NFC byte-equal

⚠️ 已知 lemmatizer 资产瑕疵surface_to_base.json(双端共享)有 3 处错误映射 picked→pic / passed→pas / trying→trietried→try 却对)。表现:picked up → pic up(不等于库里 pick up)。跨端一致性不破(双端同资产同输出,diff 仍空),仅影响 pick/pass/try 系短语的屈折匹配召回。属红线 #5e(资产双端原子提交)独立修,不在本次。详见 RVH memory reference_lemmatizer_asset_bugs


5. RB 待办(Phase 2 协调清单)

  1. /vocab-reseed:整包覆盖 src-tauri/assets/reading_vocab.db + bump VOCABULARY_SEED_VERSION + 校验。
  2. 实现逐字符等价 normalize_phrase,跑 test/data/phrase-normalize-regression.txt diff RVH 的 rvh-phrase-normalize.csv,确认为空。
  3. get_phrases_for_matching:查 word_tags 含 phrasal_verb/idiom 的短语 + frequency_rank(降噪)+ basic(默认排除)。
  4. 决定 A:把 recommended_excluded_phrases.jsonl(400 条)填入 Supabase recommended_excluded_words 公共表(协调策展归属;这是对简报 §5 的有意偏离)。
  5. 高亮降噪起步阈值建议:只高亮 frequency_rank ≤ 4000(commonness ≤ 2)且非 basic。

6. 验收 SQL(RB reseed 后)

sql
-- 短语条数(注意 NULL word_tags 行会让 json_each 报错,加 IS NOT NULL guard)
SELECT value AS tag, COUNT(*) FROM vocabulary, json_each(vocabulary.word_tags)
WHERE vocabulary.word_tags IS NOT NULL AND value IN ('phrasal_verb','idiom','basic')
GROUP BY value;
-- 期望:basic 400 / idiom 5336 / phrasal_verb 1861

SELECT word, word_tags, frequency_rank,
       json_extract(pos_definitions,'$') IS NOT NULL AS has_def
FROM vocabulary WHERE word IN ('look into','give up','get up','piece of cake','break the ice');