一款能读懂你写了什么的字体

查看原文 HN 讨论

文章摘要

Rohan Adwankar 在个人博客上介绍了他做的一个小型 JavaScript 库 semfont。它的目标是自动排版:根据文本的语义,自动给词语上色、加粗、加斜体、加高亮,让一段文字”更容易读”。页面顶部有一个交互式演示框,用户随手输入一段话,就能实时看到它被重新着色,还能在 editorial(编辑风)、loud(喧闹)、monochrome(单色)、technical(技术风)四种主题之间切换。需要说明的是,尽管标题叫”字体”,它其实并不是字体文件,而是一个在字体之上做语义标注的排版库——这一点后来成了 HN 上被吐槽最多的地方。

核心原理:每个词打四个分。 每个分数都先查词典,再根据周围几个词用少量规则修正:

最后由主题把每个分数映射到一个排版维度:情感→颜色,显著性→字重,转折→高亮,确定性→斜体。每个维度都有阈值,所以大多数词保持原样。

第二遍扫描:修补窗口规则的盲区。 上面这些规则只看左右几个词,存在明显的盲点。比如 “I would not go so far as to call the new editor great”,great 仍然是绿色,因为抵消它的 not 远在九个词之前;又比如 “We fixed the crash”,结果是一个绿词加一个红词,因为没有东西把 fixed 和它修好的对象关联起来。于是作者加了第二遍,按整个从句来读:否定词的作用范围延伸到从句末尾并随距离衰减,great 因此变红;fixed、recovered、avoided 之类的动词会把后面的对象标记为”变好了的东西”,crash 因此变绿。这一遍还能识别 less broken、fewer complaints 是改善,too simple 是抱怨,以及坏消息前单独一个 “Great,” 是讽刺。每一处修改都记录在词上,调用 analyze() 可以查到某个词为什么是这个颜色(例如 crash 的 notes 写着 resolved by "fixed")。第二遍的开销与第一遍相当,仍在性能预算内,所以没有做成开关。文中列出了促成这一改进的十个例句,左右对比新旧效果。

使用方式。 在 React 里用 <SemanticText> 组件包住文本即可,可以选主题、只开部分通道(比如只要情感上色),也可以传入自定义词典,例如把 flaky 设成 -0.7、oncall 设成 -0.4、rollback 的显著性设成 0.8。作者坦言做这个库的初衷是 AI:AI 系统会流式吐出大量文字,很难全部读完,他希望有一个能直接塞进大多数流式组件的库,让文字更好读——文中就给了一个接 Vercel AI SDK useChat 的示例,只给 assistant 的消息套上 semfont。不用 React 的话,也可以直接调用 semfont/analyze 拿到每个词的四个数字,再用 semfont/theme 生成 CSS。博客页面本身就没有打包器,靠一个 import map 从 jsDelivr 加载 npm 上的 0.2.0 版本。

下一步。 作者承认,以这种实现方式,不可能在足够快、不拖慢流式输出的同时做到完美分类;但为了”让文字更好读”,也不必完美,一些简单的启发式规则也许就能走得够远。讽刺、带嵌套从句的否定等情况值得继续用启发式去攻克;面向流式编程 Agent 的场景,还可以把技术词汇加进词典。代码与演示在 GitHub 的 RohanAdwankar/semfont 仓库。

HN 评论精华

约 44 条评论,97 分。讨论主要围绕三点:标题把 JS 库叫”字体”名不副实;Firefox 上直接不能用;以及这种”给散文做语法高亮”到底是帮助阅读还是破坏阅读——后者的反对声明显占多数。

作者自述。 作者 RohanAdwankar 在帖子里说明:它没有用 LLM,只是一组朴素的启发式规则,因此快到可以在文本流式输出或编辑时实时排版,目标是看看能否让正在流进来的文字更好读。

Firefox 上跑不起来。 frereubu 贴出报错:浏览器提示 semfont/analyze 是一个”裸说明符”但没有被映射,Chrome 下则正常。jstanley 说”我还以为它就是什么都不做”。brk 也说在 Firefox 里只是一个文本框,一开始都没明白它要干嘛。LoganDark 补充 Safari 下工作正常,bensyverson 则挖苦道”我猜它在 Chrome 这个世界上唯一的浏览器里完美运行”。作者随后回复,已经有 HN 读者 Jakub 提交 PR 修好了这个问题。

“这根本不是字体”。 skrebbel 说这只是一个根据语义分析给文字上色的 JS 库,标题严重夸大。ShinyLeftPad 的 TLDR 是”不是字体,只是 JS 库”。TheRealPomax 措辞最重:”这在任何意义上都不是字体,这是一个排版器(typesetter)……现在的标题不只是标题党,是彻头彻尾的撒谎。”他还顺带提醒网站上那个没有任何标识的明暗切换按钮让人摸不着头脑。作者道歉说自己当时想不出能直观描述它的名字,并非有意标题党。tensegrist 本以为计算是在字体内部完成的,并贴出几个真正把逻辑做进字体里的例子:SansBullshitSans(用 OpenType 连字把 buzzword 涂黑)、Chartwell(输入数字就变成图表的字体)、numderline(用下划线给长数字分组的字体),以及更极端的 fontemon——一个完全在字体里实现的游戏。作者回复说完全不知道还有这种东西。

阅读体验:多数人觉得更难读了。 AnthonBerg 的评论最细腻,作者也称赞它”非常有思考”:这个想法很棒,但结果读起来”像糟糕的 AI 写作一样难受”;有一种强行侵入的感觉,文字”没法呼吸”;读者本来就会在阅读中自己筛出语义权重,高亮反而加进了一种古怪、别扭的情绪处理噪音。他反复强调自己其实很喜欢这个项目揭示出的东西——关于文本理解、显著性感知和书面节奏。great_tankard 附和:”很酷的点子,也希望没人真把它用在写作里。”作者回应说项目主要是为了探索,不确定这就是答案;他关注的是像 Agent 那样文字飞速滚过时能否帮上忙,并举了辩论选手的例子——需要极速朗读的辩手会给资料做高亮和格式标注,所以在高速场景里或许有用;但他也同意如果一本书被这样排版会很烦人。

pxx 给出了最有说服力的原理性反驳:给无格式文本加强调,会以文本本身并未暗示的方式牵引读者注意力。”I didn’t say he stole the money”这句话,重音放在哪个词上语义完全不同,但原始文本里根本无从判断该强调哪个。”你脑中本来就有转折的心智模型,加上视觉噪音只会破坏阅读中已有的东西。语法高亮之所以成功,是因为代码的语义是刚性的,而自然语言恰恰不是。”applfanboysbgon 更尖刻:他平时批评代码里”彩虹糖式高亮”泛滥时,常用的论据就是”没人会蠢到给散文上彩虹糖,因为从单色文字中识别句法和语义是我们终身训练的技能”,”很高兴看到一个活生生的例子证明这会让一切难读十倍”。codingdave 认为前提就有问题:它不会帮人阅读,只会帮人决定跳过哪些词,而且大概搞不定讽刺。brk 觉得它有种小学语法课给句子里的词划线标色的味道。prodmod 被激怒到忍不住发言:”我聪明到能在脑子里自己标重点,这就是我有大脑的原因。”

也有人看好。 mkrecny 认为”这是个大想法,具体实现好不好并不重要”。smugglerFlynn 顺着可调词典想到一个实际用途:给公司内部黑话、内部组件和团队名设置显著性分数,用来增强 wiki、聊天、工单和日志,让人更快更准地略读。alexkkoo93 觉得它最适合用在 Agent 帮自己记的笔记或自己的录音转写上,但不希望用在对外发布的文字上,以免无意中加进不想表达的意思。yigalirani 的概括是”给自然语言做语法高亮”。WillAdams 说他早就想过给 (La)TeX 排版的 PDF 加这种高亮。

其他有趣的联想。 rob74 担心一旦流行,经理就会抱怨员工的邮件和 Slack 消息里红词太多、绿词太少。amelius 调侃”至少我们还没走到’会向厂商汇报你读了什么的字体’“。philipwhiuk 说这是一种应对 AI 生成文本冗长啰嗦的奇怪方式。velcrovan 联想到漫画作者选择加粗哪些词的逻辑一直让他困惑,大声读出来常常很滑稽;_grilled_cheese 则想起了用花哨彩色字体排版的儿童读物《老鼠记者》(Geronimo Stilton)。busssard 遗憾它目前只支持英文。