词光 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。

本文提纲

  1. 先看数字:679 MB 里只有 3% 是文字
  2. 14 个 commit:它是一份生成物,不是一段开发史
  3. 一个词条要过七道工序
  4. 真正的产品是复习计划,不是插画
  5. 星图不是装饰,19 个话题的分布本身就在说话
  6. 一支外部团队替你做完了 code review
  7. 三种人,三种拿法
  8. 该怀疑的地方

先看数字: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、美音 Sarah
  • gen_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

一个词条要过七道工序

单看「一词一画」是句营销话,把它拆成工序才有信息量。词条从词头到能在浏览器里点开,中间有四层规格:

  1. 生成:1024px 场景插画,一个词一个场景描述,与统一画风提示词组合;
  2. 母版:压成 768px WebP,留在构建链里;
  3. 站点:512px WebP 主图,7,298 张 184.7 MB;
  4. 缩略: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 上,不是我自己校对的结果。

参考文档与链接

你如果已经 fork 它自建过站,或者拿 word-atlas.json 做过别的东西(Anki 牌组、小程序、自己的 App),欢迎在评论区说一下你卡在哪一步——尤其是那 679 MB 资产你怎么分发。这类项目的坑几乎不在代码里,全在带宽和存储上。


作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top

关注公众号,获取更多 AI 技术干货!

posted @ 2026-11-08 12:43  iTech  阅读(3)  评论(0)    收藏  举报