给词汇量有限的读者读外语原版书的网页阅读器生成器。一本书产出一个纯静态阅读器:默认每个词都不认识(高亮),逐个认领;查词走预构建词典(即时),整句翻译实时调 任意 OpenAI 兼容 LLM API。任意语言(法 / 英 / 德 / 俄 / 西 / 日 / 中…)、任意一本书都适用。
在线示例:凡尔纳《从地球到月球》(公有领域) → https://felix021.github.io/terre-a-la-lune/ (仓库;部署见 design.md §9)
- 学习模型:每个词原形(lemma)一个整数
k。某次出现是否高亮 = 抽签draw(lemma,位置) < 0.5^k。k=0恒亮(生词),k≥1按概率复查(已认领)。点「标记为认识」k+1,点「标记为生词」k=0。多次确认后趋于稳定——避免"标一次就当会了"的假掌握。 - 词典预构建:把全书 lemma 切成 ~12 片 → 派 N 个 Claude subagent 并行,各直接凭模型自身语言知识给分片出词典条目(注音/词性/释义/变位/例句)→ 合并成
dict.json。查词零延迟,不依赖运行时 LLM。 - 运行时翻译:划选词组/整句 → 实时调你配置的 OpenAI 兼容 LLM。
# 1) 装依赖 + 语言模型(法语为例)
pip install -r build/requirements.txt
python -m spacy download fr_core_news_sm
# 2) 原文 -> 结构化 JSON(每书写个抽取器;build/extractors/ 下有个《小王子》示例)
python build/extractors/extract_le_petit_prince.py book.html structured.json
# 3) 结构化 JSON -> book.json(分词 + 词形还原 + seed)
python build/build_book_json.py structured.json book.json fr_core_news_sm
# 4) 预构建词典:切分 -> 派 Claude subagent 并行 -> 合并
python build/split_chunks.py book.json 12 # 产出 chunk_0..11.json
# (在你的 agent 客户端里派 12 个 subagent,各读 chunk_i.json 生成 dict_part_i.json;
# subagent 任务模板见 design.md §5)
python build/merge_dict.py book.json # 合并 dict_part_*.json -> dict.json,校验覆盖率
# 5) 部署阅读器:把 reader/ 的三件 + book.json + dict.json 放到任意静态服务器
cp reader/{index.html,style.css,app.js} /your/static/<book>/
cp reader/config.example.js /your/static/<book>/config.js # 改里面的配置
cp book.json dict.json /your/static/<book>/不想用 subagent?
build/build_dict.py可用任意 OpenAI 兼容 API 串行建词典(慢,断点续传):LLM_BASE_URL=... LLM_KEY=... python build/build_dict.py book.json。
复制 config.example.js 为 config.js,改:
| 字段 | 说明 |
|---|---|
title |
顶栏 / 标签页标题 |
ttsLang / ttsRegex |
朗读语言 / 选语音的前缀(如 fr-FR / fr) |
llmBase |
默认 LLM 接口地址(OpenAI 兼容);留空则用户在 ⚙ 设置里填 |
idb |
IndexedDB 库名,每本书必须唯一(同源多本书共享存储,重名会串数据) |
cfgKey |
localStorage 键前缀,每本书唯一 |
朗读按钮只在设备装了 ttsLang 对应语音时才显示(没有就不显示,避免用错语言语音硬读)。
| 语言 | spaCy 模型 | TTS | 注音 |
|---|---|---|---|
| 法语 | fr_core_news_sm |
fr-FR |
国际音标 |
| 英语 | en_core_web_sm |
en-US |
国际音标 |
| 德语 | de_core_news_sm |
de-DE |
国际音标 |
| 俄语 | ru_core_news_sm |
ru-RU |
国际音标 + 重音 |
| 西语 | es_core_news_sm |
es-ES |
国际音标 |
| 日语 | ja_core_news_sm |
ja-JP |
假名/罗马音 + 声调 |
| 中文 | zh_core_web_sm |
zh-CN |
拼音 |
日 / 中无空格,分词质量依赖 spaCy 模型,先验证分词效果再建词典。
reader-builder/
├── reader/ # 阅读器前端(模板,各书共用)
│ ├── index.html style.css app.js
│ └── config.example.js # 复制为 config.js 改配置
├── build/
│ ├── build_book_json.py # 结构化 JSON -> book.json(通用分词)
│ ├── split_chunks.py # book.json -> 分片(通用)
│ ├── merge_dict.py # dict_part_*.json -> dict.json(通用)
│ ├── build_dict.py # 可选:用任意 OpenAI 兼容 API 串行建词典
│ ├── requirements.txt
│ └── extractors/
│ └── extract_le_petit_prince.py # 示例抽取器(不含原文)
├── design.md # 设计 + 避坑规则
└── AGENTS.md # agent 工作指南
MIT。各书原文的版权各自负责(示例抽取器针对的是公有领域文本)。