BLOG

handwired:把 JS 代码硬写成神经网络

Yongliang
AItech
广告 · Advertisement

10 月 15 日,React 团队成员 chenglou 在 GitHub 发布 handwired,README 第一句就是「Turn your regular JavaScript code into a neural net; no training, exact, yet also fully differentiable」:把普通 JavaScript 代码变成神经网络,不用训练,结果精确,还全程可微。到 10 月 20 日,仓库已收获 1804★,热度主要来自 GitHub trending 和社交媒体,HN 上也曾多次登上首页。项目用 TypeScript 写成,MIT 协议,构建工具是 bun,在线 demo 挂在 chenglou.me/handwired,本地只要 bun install && bun start 就能跑起来。本文按六段式拆解。

这个项目的特别之处在于,它没有走「训练网络模拟程序」的老路,而是反过来:先写程序,再把它编译成神经网络可以运行的形式。这种反向操作,让神经网络从「学习器」变成了「执行器」。

一、它是谁

作者 chenglou,GitHub 知名开发者,React 团队成员。这次他以个人项目形式发布 handwired,从 lab 目录的实验记录看,9 月初已有逐日更新的实验日志,还提到 6、7 月的设计讨论,说明公开前已经历较长准备期;公开仓库后短时间内的密集提交,应理解为「长期准备后一次性公开加持续整理」,而非全部工期。这个发布节奏在开源社区并不罕见:先私下打磨,再一次性公开,利用社交媒体放大初始关注度。

项目规模上,核心 src/ 目录下包含 runtime、handwiredos、json-search 等子模块。关键文件规模如下:src/runtime/numeric-ui-core.ts 约 152 KB,src/runtime/cells.ts 约 22 KB,src/runtime/host-timing.ts 约 21 KB。仓库整体 TypeScript 占比 90.5%,是一个带文档、带测试、带在线 demo 的完整工程,不是 gist 级别的概念演示。它的目标不是成为又一个前端框架,而是为「程序即网络」这个命题提供一套可执行的参考实现。对于希望快速了解 differentiable programming 的开发者,这个仓库提供了一个可以直接 clone、运行、修改的起点。

二、机制拆解

handwired 的出发点:任何程序无非是 if-else、循环和状态,而它要把这三样东西变换成「矩阵乘法 + ReLU」在浮点数上执行。

README 给的例子最直观。(a > 4) ? 10 : 12 这样的分支,可以改写成纯算术:

above4 = max(0, a - 4) - max(0, a - 5)   // a > 4 时为 1,否则为 0
result = above4 * 10 + (1 - above4) * 12 // 两个分支都计算,再用 above4 选择

其中 max(0, x) 就是 ReLU。比较、选择这些控制流原语,于是被编码成加减乘和 ReLU。循环和状态同理:状态放进一张 Float32Array 源表,每轮求值读表、计算、写回。

为了把整套编译流程串起来,handwired 在构建期运行一次普通 JavaScript,把 emitMultiply、emitCompare 等宏展开成定长指令;运行期没有任何分支和循环,只有对这张浮点表的顺序求值。这也意味着,一旦程序被编译完成,它的执行路径就是确定的,GPU 可以一次性调度大量同构线程,而不必在运行时处理动态分支。

下一步是收集:把程序里所有的加法、乘法和 ReLU 收进一个巨大的 matmul,在 JS 或 WebGPU 上运行。因为基本只用这两个原语,README 给出三条性质:整个程序保持可微;权重是手写的,不需要训练;GPU 的成熟优化技术对这种极简原语特别好使。

项目的核心创新在于:它不是训练一个网络去逼近程序,而是把手写程序精确地编译成神经网络形态。权重不是训练的产物,权重就是程序本身。这种「免训练、精确、可微」的三重目标同时成立,靠的是编译方向的选择。换句话说,神经网络在这里更像一种程序的执行格式,而不是从数据中学出来的近似函数。

这种思路的可贵之处在于,它把「可微」从训练环节挪到了编译环节。传统神经网络需要大量数据和反向传播来调权重;handwired 则先让你用熟悉的程序逻辑写出确定性行为,再保留其梯度结构,以便在需要时接入优化器。它并不是要取代训练,而是把「训练」与「程序」之间的边界往后推了一步。

三、工程成色

从目录结构看,src/ 是核心 runtime,lab/ 是实验项目,template/ 是模板,docs/ 是文档。runtime 部分又以 cells、host-timing、numeric-ui-core 等文件为主,其中 numeric-ui-core.ts 单文件约 152 KB,是数值/UI 运行时的主干。

仓库的 TypeScript 占比达到 90.5%,说明它不是一个轻量包装,而是把数值运算、动画调度、宿主交互都内建其中的工程。docs/ 里的文档则把执行模型、教程、模式、行为选择都覆盖到了,对想理解可微编程的人比较友好。这种工程密度也说明,handwired 不是一两天的灵感产物,而是经过多次迭代才成型的系统。

从依赖关系看,handwired 没有引入重量级运行时。package.json 里只有 TypeScript、测试和 lint 工具,核心逻辑完全自包含。这个选择让仓库保持轻量,但也意味着它目前只能覆盖可以用 builder API 表达的程序片段。对于已有的大型业务系统,直接迁移并不现实,更现实的路径是把局部计算密集型片段抽出来重写。从源码组织上,tests/ 目录与 template/ 目录并列,说明作者希望用户从模板出发,逐步把普通 JS 改写成 handwired 风格。

在线 demo 和 template/ 目录里的示例构成最直观的入口:一个普通 JS 写法的 UI 组件,经过 handwired 的 builder 代码转换后,变成一张可在 GPU 上跑的数值表。构建期运行一次普通 JavaScript,把 emitMultiply、emitCompare 等宏展开成定长指令;运行期没有任何分支和循环。

这种写法对前端工程师有天然的亲近感:你不用写 CUDA,也不用写 WGSL,只需要用 JavaScript 的 builder API 描述数值计算,剩下的展开、收集、执行都由 handwired 完成。对于习惯了 React 声明式组件的人来说,这相当于把「组件树」替换成了「数值程序图」,但书写界面仍然是 JavaScript。这也意味着,前端工程师可以用自己最熟悉的语言去探索 GPU 并行和可微程序,入门门槛比学习一门新语言要低得多。

不过,builder API 的友好性也带来了限制:所有计算必须能用项目提供的原语表达,任何超出范围的操作都需要回到普通 JavaScript 中处理。handwired 更像一种嵌入在 JS 里的领域特定语言,而不是对 JS 语法的无差别翻译。

四、效果与验证

仓库自述的效果分三层。第一层是概念验证:把 if-else、循环、状态映射成矩阵乘法和 ReLU,程序仍然精确且可微。第二层是演示:在线 demo 展示了完整 UI 桌面系统 HandwiredOS,窗口拖拽、最大化、点击选中、文本换行、虚拟滚动列表等交互都编译进数值程序,宿主只负责把浏览器事件写进源表、跑一次求值、把输出写回 DOM。第三层是性能宣示:JSON 搜索 demo 号称能在 10 万文档上毫秒级完成,其收益来自同构并行,即每份文档跑同样的操作、互不干扰。换句话说,handwired 的演示价值在于证明「程序可以跑在一张浮点表上」这件事是可行的,而不只是理论可行。它把抽象概念做成了浏览器里可点的 demo,这是它获得高星数的重要原因。

不过作者自己把这些定位为实验。README 里「what does that even do? Let’s find out!」的风格,以及「把冻结的特定程序接上通用神经网络端到端训练,nanoGPT 能同时学莎士比亚和你的 UI?」这类问句,都说明它更像一个探索性项目,而不是成熟工具。

五、边界与争议

首先要说的是表述边界。README 的「Turn your regular JavaScript code into a neural net」容易让人误以为可以把任意 JS 自动编译成网络;但技术现实是,它要求用项目提供的 builder 原语和数值契约手动重写程序,不是通用 JS 编译器。

其次是数值边界。用 ReLU 编码整数比较依赖操作数落在声明的网格和范围内,浮点世界里超出范围的输入没有魔法;索引读取也有限制范围。写程序的人需要主动维护这些数值契约。

第三是规模边界。分支两边都计算,操作数会随程序复杂度增长。handwired 适合用来验证「程序即网络」这个方向,但一个真实业务系统的控制流如果全部展开成矩阵操作,规模和调试成本都会迅速膨胀。这也意味着,handwired 目前更适用于控件、搜索、动画等局部计算密集场景,而不是整套业务逻辑。

最后是生态边界。作为刚发布的实验项目,handwired 还没有形成稳定的社区和工具链。第三方库、编辑器插件、调试工具都未成熟,企业若要考虑引入,必须同时承担维护成本和认知成本。

最后是传播与热度之间的温差。GitHub 上 1804★ 很高,HN 也多次登上首页;但高星数更多度量话题性,不是生产采用度。接口随时可能变化,open issues 也在增长,现在找生产工具的人不宜直接采用。

六、结语

handwired 的价值在于用一个具体可跑的工程,把「普通程序可以编译成可微分神经网络」这件事从口号落到了 demo 层面。它挑战了「神经网络必须训练」的默认认知,也说明可微性可以从编译结构里长出来,而不是必须靠反向传播从外面灌进去。这个思路对当前大量依赖训练数据的 AI 工程实践形成一种补充:在某些场景下,程序本身的结构就可以带来可微性,而不需要把问题全部建模成优化问题。

4 天冲上 1804★ 说明这个话题击中了社区的好奇点;但判断它是研究玩具还是范式信号,还需要看后续有没有人用它做出真实应用、有没有人能把这套方法扩展到更复杂的控制流上。目前阶段,它更适合作为理解可微编程和数值编译的教材级入口,而不是拿来就用的新一代前端框架。对于前端和编译器领域的开发者,handwired 提供了一种值得关注的程序表示方式;对于希望直接应用的团队,它还需要更多验证和生态建设。

一个有意思的比较对象是传统神经网络。传统网络用训练来寻找权重,好处是通用性强,缺点是行为不可解释、需要大量数据;handwired 用程序直接指定权重,好处是行为确定、可解释,缺点是表达能力受限于程序员能写出来的程序。两者并不是替代关系,而是互补关系。在一些对可解释性和确定性要求高的场景,比如 UI 动画、金融计算、物理模拟,handwired 的思路可能比训练网络更可靠。

它不一定改变你明天的写法,但它确实把「程序和网络之间的墙」又凿开了一道缝。未来值得关注的问题包括:它能否支持更动态的控制流?能否在保持可微的同时降低规模膨胀?能否与现有前端框架形成互补而非替代?这些问题没有现成答案,但正是它们让 handwired 保持讨论价值。

信息来源

  • GitHub 仓库:chenglou/handwired(README、docs/、src/、lab/)
  • 事实包:/Users/kael/xhs-content/drafts/2026-10-20-facts-packages.json(仓库规模、作者、核心机制、Demo 地址、传播力)
  • 在线 Demo:https://chenglou.me/handwired/
广告 · Advertisement

常见问题

handwired 是什么?

handwired 是一种技术,可以将普通 JavaScript 代码编译成可微分的神经网络,无需训练即可执行。

handwired 的作者是谁?

handwired 的作者是 React 团队成员 chenglou。

handwired 的核心创新点是什么?

handwired 的核心创新点在于它不是训练一个网络去逼近程序,而是把手写程序精确地编译成神经网络形态,权重就是程序本身。