词光 Word Atlas:7,298 个词的星图,和 679 MB 的代价
词光 Word Atlas:7,298 个词的星图,和 679 MB 的代价
它最不像开源项目的地方,是它几乎没有开发史:37,725 个文件,14 个 commit,1 个贡献者。
2026 年 10 月 25 日 08:27(UTC),开发者 designfuchen 把「词光 · Word Atlas」推上 GitHub:7,298 个雅思词条,每个词配一幅原创插画、英音与美音、两条原创例句,再加一套按作答情况排期的 FSRS 复习。到 11 月 8 日,13.8 天里它拿到 4,409 星、932 个 fork,在线版(0xlei.tech/words)免费、无需注册,代码 MIT、词库与插画录音 CC BY 4.0。
这个数字最容易被读错的地方,是把它当成「代码质量认证」。GitHub API 同时给出另外三个数字:commit 总数 14,贡献者 1 人,watcher 11 人。4,409 星对 11 个关注者,比例是 401 : 1——star 是「我记住了它」,watch 才是「我要跟进它」。这里真正被人认可的不是工程,是语料。
所以我把三样东西都读了一遍:仓库的 PUBLIC_MANIFEST.json(37,725 条文件清单,含每个文件的字节数与 sha256)、8 MB 的 data/word-atlas.json(逐字段统计)、以及全部 50 条 open issue/PR。另外下载了 abandon 的图和音,用 PIL 验了实际像素尺寸。下面这些数字,除特别注明外都是我自己算出来的,不是抄 README。
本文提纲
- 先看数字:679 MB 里只有 3% 是文字
- 14 个 commit:它是一份生成物,不是一段开发史
- 一个词条要过七道工序
- 真正的产品是复习计划,不是插画
- 星图不是装饰,19 个话题的分布本身就在说话
- 一支外部团队替你做完了 code review
- 三种人,三种拿法
- 该怀疑的地方
先看数字:679 MB 里只有 3% 是文字
把 manifest 按目录求和,得到一张很说明问题的重量表:
| 资产 | 文件数 | 体积 | 平均单件 |
|---|---|---|---|
| 插画 512px WebP | 7,298 | 184.7 MB | 25.9 KB |
| 缩略图 256px | 7,298 | 69.8 MB | 9.8 KB |
| 例句朗读 | 7,298 | 192.9 MB | 27.1 KB |
| 美音 | 7,298 | 61.4 MB | 8.6 KB |
| 英音 | 7,298 | 58.9 MB | 8.3 KB |
| 第二条例句朗读 | 1,011 | 52.8 MB | 53.4 KB |
| 界面音效与环境声 | 24 | 4.3 MB | 182.1 KB |
| 词库 JSON / CSV | 2 | 12.8 MB | — |
| 分片词条 entries/*.json | 73 | 约 6.8 MB | 约 93 KB |
| 合计 | 37,725 | 679.2 MB | 18.4 KB |
第一件事是算术校验。README 说「全部 7,298 个词都有英音、美音和例句朗读,还有 1,011 个重点词的第二条例句也配了朗读」,那么音频总数应当是 7,298 × 3 + 1,011 = 22,905。manifest 里 audio/uk、audio/us、audio/ex 各 7,298 个,audio/ex2 恰好 1,011 个,加起来 22,905——一个不缺。这种「用三个独立数字互相圆上」的校验,比读一遍宣传语有用得多:它证明这份数据集的完整性是算出来的,不是抽样出来的。
第二件事是比例。音频合计 366 MB(占 53.9%),图片合计 254.5 MB(占 37.5%),而所有文本(词库 JSON + CSV + 73 个分片 + 索引)加起来约 20 MB,只占 2.9%。语言比较 API 那边,TypeScript 219 KB、CSS 80 KB、Python 48 KB、JS 18 KB,源码合计约 371 KB。资产与源码的体积比是 1 : 1,875。
这个比值就是全文的第一个判断:它不是一个应用仓库,是一个语料仓库,前端只是这份语料的播放器。 所以 git 的 delta 压缩对它几乎无效——GitHub 报的 size 是 669,578 KB(约 654 MiB),压完仍然相当于一部 1080p 电影。作者在 README 里很诚实地写「仓库含完整图片与录音,首次下载可能较久」,并给了 git clone --depth 1;部署文档也建议「在 CDN 后部署,或按需只发布 thumb/ 和部分音频」——只发缩略图能把图片成本从 254.5 MB 砍到 69.8 MB,代价是词卡上的插画变成马赛克。
顺带一个容易读错的点:cover-v2.jpg、atlas-desktop.jpg、launch.mp4 这些是 docs/assets/ 里的宣传素材,13 个文件 32 MB,不属于产品运行时资产。真正在浏览器里跑的是 public/atlas/ 和 public/sfx/。
14 个 commit:它是一份生成物,不是一段开发史
把 git 历史拉出来,结论有点刺眼:仓库总共 14 个 commit,最近一次是 10 月 31 日 11:37(UTC),我看到的最近 10 条全是 README 修订。也就是说,7,298 个词条、22,905 段录音、7,298 幅插画,是在极少的几次提交里一次性灌进去的。
这解释了为什么它的代码量小得反常,也解释了另一件事:它是被「生成」出来的,不是被「开发」出来的。 证据在 scripts/atlas/——11 个脚本,合计 44.8 KB:
gen_text.py(5.2 KB):每批 10 个词,按脚本里的编写规范生成词条 JSON(准确优先、原创、两类例句、不编造词源、安全中立)gen_images.py(4.7 KB):读每个词条自带的scene场景描述,拼上统一画风提示词,生成 1024px 图片,压成 768px WebP 母版gen_word_audio.py(3.1 KB):调 ElevenLabs,英音 Alice、美音 Sarahgen_sentence_audio.py(3.5 KB):只为ex[0]合成朗读build_atlas.py(7.4 KB):清洗字段、排序、切块,产出public/atlas/与data/gen_brand.py/gen_sfx.py/build_sfx.py:品牌图、界面音效、环境声的母带链fix_blocked.py:被内容审查挡下的词条返工
流程写得很清楚:.local/forge/headwords.json 是词头,中间产物全部写进被 git 忽略的 .local/forge/,可断点续跑;凭据只从环境变量读(SUB2_BASE_URL / SUB2_API_KEY / ELEVENLABS_API_KEY),SUB2_BASE_URL 指向任意 OpenAI 兼容接口;最后 npm run check:atlas 校验。
这套设计真正的含义是:你拿到的不只是 7,298 条数据,而是再生成一遍的能力——换一批词、换一种画风、换一个语言,脚本层面都成立,甚至已经有人把它 fork 成了俄语版(后面第 6 节的 31 个 bug 就是那支团队发现的)。
但这份能力有成本,而这个成本 README 里只轻描淡写了一句「我自己投了很多钱和时间」。你自己重跑一遍要付的是:7,298 次文本生成、7,298 张 1024px 图生成、7,298 + 7,298 段语音合成(英音 + 美音)、再加 8,309 段例句朗读。按公开市价,这是一笔四位数的美元开销,不是「改个 prompt 重跑」的量级。作者也在页首挂了微信和支付宝的赞助码——这不是卖惨,是这类项目的真实财务结构。
反过来说,14 个 commit、1 个贡献者意味着这份工程从来没有过 review 环节。第 6 节会看到它的代价具体长什么样。整条链的形状是这样的:
MERMAID_BLOCK_0
一个词条要过七道工序
单看「一词一画」是句营销话,把它拆成工序才有信息量。词条从词头到能在浏览器里点开,中间有四层规格:
- 生成:1024px 场景插画,一个词一个场景描述,与统一画风提示词组合;
- 母版:压成 768px WebP,留在构建链里;
- 站点:512px WebP 主图,7,298 张 184.7 MB;
- 缩略:256px WebP,7,298 张 69.8 MB。
我下载了 abandon 的两张图实测:主图 512 × 512、28,220 字节;缩略图 256 × 256、10,508 字节。与 manifest 平均值(25.9 KB / 9.8 KB)对得上——所以这张表不是我推的,是逐个文件称出来的。
为什么是正方形?因为词卡和星图里的「星」都是方形/圆形的构图单元,非方图在 WebGL 星图上会被二次裁切。这是一个很朴素但很关键的选择:排版先决定了素材的宽高比,而不是反过来。
比插画更值得抄的是切块方式。7,298 个词不是一个大 JSON,而是切成 entries/ 下 73 个分片(73 × 100 = 7,300,最后一片不满),每片约 93 KB;另有一个 498 KB 的 index.json 负责索引。首屏只取需要的那一片,所以「7,298 个词」在第一次打开时不会变成一次 8 MB 的下载。这是内容型项目的通用解法:数据量再大,只要按访问路径切块,首屏成本就和总量无关。
声音的分层更讲究。单词音平均只有 8.3 KB(英音)/ 8.6 KB(美音),例句朗读却平均 27.1 KB,第二条例句 53.4 KB。体积差背后是信息量差:单词音是「建立词—音关联」,例句音才是「提供语境」。24 个 sfx 里除了 9 个操作提示音,还有 6 段环境声(雨天图书馆、清晨海岸、林间早晨、夜晚壁炉、远航船舱、安静咖啡馆)、一段可无缝循环的星空配乐、两段配音(开屏一句「欢迎打开雅思大门」、星图一句「每学会一个词,就点亮一颗星」)。
作者还做了一个常被忽略的细节:读单词的时候背景音会自动压低(duck)。这不是音效师的讲究,是学习场景的必需——环境声盖住发音,整个「听音辨词」题型就废了。可惜这件事在第 6 节会翻车:9 个界面音效被母带链的淡出参数截成了 10 毫秒。
真正的产品是复习计划,不是插画
插画是钩子,留人的是排期。docs/learning-model.md 写得比 README 细得多:
- 每日旅程:先把所有到期词复习完,再学新词。新词上限可设,默认 10 个/天,从学习路线上你的起点难度开始取未学过的词。新词以 5 个为一组:先「初见」认识这 5 个,再打乱顺序回忆这 5 个。
- 四种题型:选义(看英文选中文,干扰项词性相同)、看图补句(插画 + 挖空例句选英文词,干扰项拼写相近)、听音辨词(只听发音选词)、拼写(看图和释义拼写,可逐字母提示)。
- 评分:每个词在一轮里只有第一次作答更新记忆状态(ts-fsrs,FSRS-6,默认目标记忆率 90%)。答错 → Again;答对但慢、或者用了提示 → Hard;答对 → Good;拼写又快又对 → Easy。
- 重试不算分:答错的词会在几题之后换一种题型再练一次,最多两次,重试既不评分也不计入正确率。
- 已掌握 = FSRS 复习状态且记忆稳定度 ≥ 21 天。
我更愿意把这三条(提示后最多计 Hard、重试不计分、只记首次作答)叫防自欺设计。背单词软件最容易烂的地方就是指标:提示越多、重试越多,「正确率」越好看,而记忆并没有真的变牢。词光把这三条全部堵死了,代价是用户会看到比其它软件更低的正确率——这是好事,但也是它不好卖的地方。
排期还有一个很硬的算术:7,298 个词按默认 10 个/天,需要 730 天,整整两年。想六个月走完,得开到 40.5 个/天;而在 FSRS 稳态下,每天到期的复习量通常是新词量的数倍,40 个新词会滚成两三百张卡。也就是说:这个项目的默认参数默认你「长期陪跑」,而不是「考前冲刺」。 如果你要两周速成,它给不了。
至于出口,learning-model.md 只定义了 Again/Hard/Good/Easy 与「稳定度 21 天」,没有写顽固词(leech)怎么降级、词条怎么暂停。数据模型也只有一个 uk / us 读音字段——所以那 105 个同形异音词(read / record 这一类)在词卡上只能显示一个读音,社区为此提了 PR #38、#39。
星图不是装饰,19 个话题的分布本身就在说话
19 个话题组成一张词汇星图:拖动旋转、滚动缩放、点击星星打开词卡,掌握程度用亮度表示,WebGL2 渲染,不支持的设备给降级显示。这是整个项目最出圈的部分,宣传片就是星尘汇聚成「词光」两个字、大门打开。
但把词库按 topic 计数,星图的形状其实是数据决定的:
| 话题 | 词条数 | 占比 |
|---|---|---|
| daily(日常) | 1,828 | 25.0% |
| society(社会) | 824 | 11.3% |
| thinking(思维) | 516 | 7.1% |
| nature(自然) | 443 | 6.1% |
| work(工作) | 414 | 5.7% |
| health(健康) | 381 | 5.2% |
| …中段 | — | — |
| history(历史) | 123 | 1.7% |
| sport(运动) | 103 | 1.4% |
| media(媒体) | 100 | 1.4% |
daily 是 media 的 18.3 倍。所以星图上「日常」是一团巨云,而「媒体」只有一百颗星——这不是美术构图,这是词表结构的直接投影。也意味着:这张星图看着很浪漫,实际导航价值有限,你没法靠它判断「我雅思考 6.5 还差哪一块」,因为 25% 的星星挤在同一个话题里。
CEFR 分布同样说明定位:
| CEFR | 词条数 | 占比 |
|---|---|---|
| A1 | 785 | 10.8% |
| A2 | 1,039 | 14.2% |
| B1 | 1,465 | 20.1% |
| B2 | 2,127 | 29.1% |
| C1 | 1,608 | 22.0% |
| C2 | 274 | 3.8% |
B1–C1 合计 71.2%,而 A1 只有 785 个。这个形状是对的——它是「雅思词库」,不是「零基础 3,000 词」;但它也意味着宣传里的「雅思词汇图鉴」对完全新手不友好,第一屏就会撞到 B1/B2 的词。
字段密度我也统计了一遍,这是判断「数据加工到什么程度」最直接的办法:
- 义项平均 1.88 个,最多 3 个;
- 例句恰好 2 条,7,298 × 2 = 14,596,与 README 完全一致,且 0 条重复;
col(搭配)、tip(辨析提示)覆盖率 100%;fam(词族)76.3%,syn(近义)53.5%,ant(反义)31.3%;note只有 37 条(0.5%)——说明这个词库几乎没有标注「例外」;- 英音与美音的 IPA 不同的词:3,103 个(42.5%)。
两个判断。第一,tip 100% 覆盖是最划算的一笔投入:它做的是同形近义辨析(principle 是原则、principal 是校长或主要的),这正是雅思阅读最容易掉进去的坑,成本低、命中率高。第二,syn/ant 只覆盖一半和三成——它不是同义词词典,别拿它做写作替换训练,也别指望它替你解决「这个词能不能用在这篇作文里」。
顺便说清「例句恰好两条」是怎么来的:pipeline 的编写规范要求「两类例句」,所以它是脚本约束的结果,不是编辑判断。这正好是第 6 节的主题——结构可以批量保证,语义不能。
一支外部团队替你做完了 code review
10 月 26 日,也就是开仓第二天,一个正在把词光翻译成俄语的团队(fork ivkiwi/word-atlas,分支 russian-edition)提了 issue #8:31 个可复现的问题,每条带文件位置、复现方式、最小修复建议,并按 P1/P2/P3 分级。他们还说「我们的分支里已经有修复,很乐意按 CONTRIBUTING 提交干净的 PR」。
第二天起 PR 就到了。今天 50 条 open 里 27 条是 PR,来自 9 个不同账号(其中 10 月 26 日当天就提交了 8 个)。挑几条最值得看的:
- [P1] 打包脚本可能删掉整个项目:
scripts/package_public.py:92只拒绝「项目目录本身及其子目录」。如果--out指向上级目录,检查会通过,随后的清理循环会把那个目录里的所有东西删掉——包括项目自己。(PR #18 修) - 所有选择题的正确答案位置有偏:
src/lib/text.ts:48用x % (i + 1),取的是线性同余发生器的低位,而低位只是交替变化。20 万个随机种子实测,四个选项时正确答案落在按键 1 的概率 33.3%、落在按键 2 只有 16.7%、按键 3 和 4 各 25%。盲按「1」就能高于随机水平,FSRS 评分被系统性抬高。(PR #9 修) - 干扰项可能和正确答案同义:比较只用子串方式比第一个义项,所以
dorm和dormitory会同时出现,答对判错。(PR #12 修) - 离线外壳从来没缓存成功:
public/sw.js的网络优先分支直到caches.open().then()里才调res.clone(),那时页面已经把响应体读走了,put必然失败——index.json和页面导航都没进缓存,断网重开直接白屏。(PR #54 修) - 练习只用词池前 60 个词:先截取再打乱,学习路线第 61–400 个词永远抽不到,早期收藏的词也一样。(PR #14 修)
- 9 个界面音效只剩 10 毫秒有声(issue #48,11 月 5 日):
build_sfx.py的母带链写了afade=t=out:st=0:d=0.001,把correct / wrong / flip / page / complete / start / streak / key / tap全部截成 10 ms 静音,再叠加偏低增益,最终峰值 −26 ~ −44 dBFS——在默认环境声下基本听不见。报告者还比对了线上 17 个 sfx 与仓库 blob 的 SHA,一致,说明线上跑的就是这份坏音频,不是部署走样。
把这 6 条放在一起看,共性很清楚:它们没有一条会在「演示一次」时暴露。 位置偏差要 20 万次采样才看得见;前 60 个词要真学到第 61 个才撞上;10 毫秒音效要放大波形才看得见;离线缓存要断网才暴露。这就是生成式生产的典型形态——「不缺项」可以靠脚本保证,「分布正确」不能。
而项目自带的 npm run check:atlas 校验的是「结构、顺序、引用与媒体文件存在性」,README 自己在「质量边界」里承认不覆盖语义正确性。31 个问题里没有一条能被它抓到。
还有一个必须纠正的读法:50 个 open 不能当 50 个缺陷。 23 条 issue 里只有 9 条是缺陷报告,其余是「收录到某工具榜」的通知(2 条)、内容合作询问、iOS 内测名额申请、「能不能做托福版」「能不能加可选词库」「希望支持古诗词」这类需求,还有一条纯粹的感谢(#16)。真正的健康度信号在另一处:27 个 PR 至今一个都没合并,GitHub 的 contributors 仍然只有 1 人。 社区把活干完了,维护者没接。
三种人,三种拿法
它把「拿走」写得很顺,三步就能自建,所以先说清楚三种拿法的边界。
第一种,自建站。 npm run build 出纯静态 dist/,丢给任何静态托管;子路径部署一行 ATLAS_BASE=/words/ npm run build;nginx 三行(alias + try_files $uri $uri/ /words/index.html + expires 7d);仓库还自带 .github/workflows/pages.yml,在 Settings → Pages 选 GitHub Actions 手动跑一次就行。唯一要认真对待的是 679 MB 资产:要么走 CDN,要么改成只发 thumb/ 和部分音频。忽略这一条,第一个月就会被流量账单教育。
第二种,只要数据。 data/word-atlas.json(7.7 MB)和 data/word-atlas.csv(5.1 MB),字段是 id / w / uk / us / senses[] / ex[] / col[] / fam[] / tip / cefr / topic,一条词条的完整形状 README 里有样例。适合做 Anki 牌组、自己的 App、或者语料研究。许可 CC BY 4.0,署名要求写的是「Word Atlas contributors(词光)」——商用可以,署名不能省。
第三种,只要代码。 MIT。技术栈是 React 19 + TypeScript + Vite + ts-fsrs + WebGL2。源码里 CSS 有 80 KB、TypeScript 219 KB——CSS 那个量级说明样式大量堆在 src/styles/app.css 里(issue #8 引用的行号已经到 2,983 行),想二次开发的人要有心理准备。
一个反常的数字:fork/star = 21.1%(932 / 4,409)。这类工具仓的 fork 通常只是 star 数的零头,五个 star 换一个 fork 已经偏高;这里是四点七个星就有一个 fork。原因不是「大家特别爱收藏」,而是部署文档把「拿走」写得太顺——子路径、nginx、Pages 三件套齐全,fork 下来改个 base path 就是自己的站。所以那 932 个 fork 里,绝大多数是自建站的人,不是贡献代码的人;证据就是贡献者数 1、PR 27 个。
还要提醒一句版本关系。README 里明写:「这个仓库提供词光的开源基础版及配套数据集。在线网站独立迭代,功能与仓库可能不同。」iOS 版是闭源测试版,下载挂在 api.billswise.cn/app,和开源站不是同一个域名、也不保证同一套功能。你 star 的那个、你部署的那个、你好朋友在用的那个,可能是三个不同的东西。
该怀疑的地方
1. 热度在跑,维护暂停了。 4,409 星、932 fork,但 watcher 只有 11(401 : 1),最后一次 commit 停在 10 月 31 日,27 个外部 PR 零合并,contributors 还是 1。发布两周、社区已经修完 31 个问题里的绝大部分,代码还在原样躺着。这不是「项目不行」,是「它现在还不是一个可持续协作的项目」——想长期用,得接受它随时停更。
2. AI 生成这件事,作者自己说得很清楚。 README 的原话:文字与插画使用生成式 AI,语音使用 ElevenLabs,内容「经过自动结构与一致性校验,尚未逐条人工审校」,「可能出现释义、例句、插画或发音错误」,「它不是官方雅思词表,也不承诺提分」。这段话值得尊重,但也意味着:错误是系统性的可能,不是偶发的意外。 issue #47(reportage 发音错误)、#31(练习配图与例句场景不符)、#35/#36(例句里不规则变形没高亮)都是这个机制长出来的。
3. 「一词一画」是它最大的卖点,也是最大的教学风险。 图和词绑定得越牢,记起来越快;但图错了会带着错记牢——双编码(图像 + 文字)让错误也变成双份。纯文本词库错了你换个词典就纠正,配图错了你脑子里那张画不会自己消失。用之前值得抽查二十个你熟的词,看画和义对不对得上。
4. 学习进度只在本机。 无需注册是优点,代价是全靠浏览器 localStorage。issue 里已经出现过「另一个标签页覆盖未保存的修改」「写入失败后不重试」「配额超限后不再保存」三条,作者还没合并修复。这意味着清一次缓存、换一台设备,进度就没了——README 的忠告是「换设备前请先导出进度备份」。这不是加密备份,是纯文本导出,你最好真的去点一下。
5. 版本分裂 + 单点域名。 开源基础版、独立迭代的在线版、闭源 iOS 测试版,三者功能可能不同;线上站挂在 0xlei.tech 这个个人域名上,issue #27 还在提「建议启用 IPv6」。想长期用,自建一份是更稳的选择——反正资产都在。
6. 我自己的口径。 音频 22,905 段这个总数是我用 7,298 × 3 + 1,011 反算并和 manifest 对上的,可信;679.2 MB 是 manifest 里 37,725 个文件的字节和,GitHub 报的 669,578 KB 是打包压缩后的体积,两个数不矛盾,别当成打架;星数、fork 数、PR 数是 11 月 8 日的 API 快照,明天就会变。至于「哪个词条错了」,我没法给——7,298 条我一个都没逐条读,本文所有内容层面的判断都建立在字段统计和社区 issue 上,不是我自己校对的结果。
参考文档与链接
- designfuchen/word-atlas — 仓库主体,代码 MIT、词库与插画录音 CC BY 4.0
- 在线体验 0xlei.tech/words — 免费、无需注册,独立迭代版
- 部署文档 deployment.md — 子路径构建、nginx 示例、GitHub Pages、体积建议
- 生成流程 pipeline.md — 七步流程、密钥边界、断点续跑与「质量边界」自述
- 记忆模型 learning-model.md — 每日旅程、四种题型、FSRS 评分规则
- issue #8:31 个可复现的问题 — 带行号与修复建议,全文最值得读的一份材料
- issue #48:9 个界面音效只剩 10 ms — 一次标准的音频母带事故复盘
- scripts/atlas — 11 个生成与校验脚本,44.8 KB
- CONTENT_LICENSE.md — CC BY 4.0 的署名要求
- ts-fsrs — 它使用的 FSRS 实现
你如果已经 fork 它自建过站,或者拿
word-atlas.json做过别的东西(Anki 牌组、小程序、自己的 App),欢迎在评论区说一下你卡在哪一步——尤其是那 679 MB 资产你怎么分发。这类项目的坑几乎不在代码里,全在带宽和存储上。
作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top
关注公众号,获取更多 AI 技术干货!

浙公网安备 33010602011771号