Qwenputer 将确定性 RISC-V CPU 编译进 Qwen3.5 4B 权重
Qwenputer: A functioning, deterministic RISC-V CPU inside Qwen3.5
Qwenputer 为 Qwen 3.5 4B 加入 32-bit RISC-V CPU,以 Gated DeltaNet 层作 RAM,并在模型前向过程中运行,无需外部工具或运行时。
文章拆解了以 Gated DeltaNet 状态作 RAM、在模型权重中编译 RISC-V CPU 的方法,并提供算术准确率、指令一致性和运行开销等实测数据。
已编译权重
一个原版 Qwen 3.5 4B,其权重中编译进了 RISC-V CPU,并以自身的 Gated DeltaNet 层作为 RAM 运行。
真不敢相信它居然不是硅做的
Qwenputer 是一个相当有趣的实验模型。它就是原版 Qwen 3.5 4B,只增加了一项设计:在权重中嵌入一个 RISC-V CPU,并将模型自身的 Gated DeltaNet 注意力层用作 RAM。(想了解 GDN 的工作原理,这里有一份实用指南。)这个“CPU”完全运行于模型的前向传播过程中,无需任何外部运行时或工具,即可执行算术运算以及 C 和 MicroPython 代码。
明确说一下,它不是插件、工具或沙箱。本文将准确说明这个模型的工作原理、它如何利用 GDN 层作为 RAM,以及我如何还加入了一套实验性的模型内文件存储。
我还写了两篇基于 Qwenputer 的后续文章:一篇介绍混合模型如何学会将推理过程隐藏在 RNN 状态中并规避 CoT 监控,另一篇介绍这类编译权重如何成为模型自身无法篡改的内置监控工具。

你可以从 Hugging Face 或 ModelScope 获取 Qwenputer,代码位于 GitHub。
Qwen3.5 内部的 RNN 可以充当精确 RAM
Qwen3-Next 和 Qwen 3.5(Qwenputer 所基于的模型)都采用了一个相当巧妙的技巧。模型中 4 个注意力层有 3 个使用 Gated DeltaNet(一种线性 RNN)作为注意力机制(这里有更多相关介绍)。每个头都会维护一个状态矩阵,delta 规则则让该矩阵持续更新。
现在,有趣的实验就从这里开始。我发现,将门控设为 1,11 每个 Gated DeltaNet 头都维护着一个状态矩阵,也就是它的记忆。在处理每个 token 时,在写入任何新内容之前,它会用门控值(一个介于 0 和 1 之间的数)乘以整个状态。这就是 RNN 遗忘的方式:门控为 0.9 时,存储的所有内容在每个 token 都会略微淡去;门控为 1 则意味着任何内容都不会淡去。将写入强度(beta)设为 1,22 门控处理之后,该头会将状态的一个方向朝新值轻推,而写入强度 beta 决定移动幅度。beta 为 1 时,沿该方向的旧值会被完全替换,而不是与之混合。并使用独热键编码,33 独热键是一个仅含一个 1、其余均为 0 的向量,因此它会准确指向状态中的一行,就像内存地址指向一个存储单元一样。我们执行的每次写入都会恰好覆盖一行,而每次独热查询都能取回一个精确值。这意味着,GDN 层本身完全可以充当 RAM,而且成本远低于把普通注意力用作 RAM,因为无论对话持续多久,GDN 头的状态大小都保持不变,而注意力机制的 KV 缓存并非如此。

认为 delta rule 充当记忆的观点并不新鲜:Schlag 等人(2021)证明,采用 delta rule 的线性注意力可以作为一种联想记忆,或称“快速权重”。44 Imanol Schlag、Kazuki Irie 和 Jürgen Schmidhuber,“线性 Transformer 其实是隐秘的快速权重程序员”,ICML 2021。 这里的创新之处,是将其精确化并使其可寻址,在实际使用的模型内部以足够高的可靠性在其上运行一整颗 CPU。
整个模型都建立在这个基础上。目前,默认版 Qwen 3.5 不会在 GDN 中保留精确值。通过这一修改,我们就能解锁实验的下一部分。
将计算机编译成层
既然我们现在已经有了一个功能完整、廉价且快速的 RAM,就可以着手把一个可正常工作的 CPU 编译进模型权重中。幸运的是,这不需要训练:编译器会直接设置每一个权重。你会将 CPU 描述为一条电路,也就是一长串小步骤,例如“读取这个寄存器”“将这两个数相加”或“如果为零则跳转”,编译器则会把每个步骤转换为 Transformer 层的一部分:负责查找内容的注意力头、执行算术运算的前馈单元,以及保存 RAM 的 DeltaNet 头。随后,在模型解码时,CPU 就会随之运行。
每条指令都会变成若干个生成的 token:一个 token 标明要写入的内存行(ADDR),下一个 token 携带相应数值(VAL),而 STEP token 则表示指令结束。这些 token 构成了 CPU 的执行轨迹,因此,当 Qwen 生成它们时,CPU 实际上正在运行。
CPU
该 CPU 是一个 32-bit RISC-V 核心(RV32IM,另加 Zba 扩展和一个用于大数运算的小型大数单元),置于 Qwen 的 32 层之前,占据 11 层。目前,它能够通过官方 riscv-tests,其程序运行结果与 qemu 一致,并且已经以自主运行方式执行了 18 million 条指令,没有出现任何错误。55 自主运行是指,在整个运行过程中,CPU 会持续依据自身的输出向前运行,步骤之间没有参考机器进行纠正。
这个 CPU 还可以在前向计算中相当好地运行 C 和 MicroPython 代码(尽管速度稍慢)。它目前还不是 Linux 级别的芯片,但已经实现了完整的 RV32IM 指令集。
Qwen 如何使用它
Qwen 3.5 4B 无需任何后训练,就能相当好地使用这个 CPU。CPU 完全在内部使用,不会通过任何外部工具调用来调用。
为了让模型能够可靠地使用它,我决定采用省事的办法:借助模型已经得到充分训练的工具调用格式,让 Qwen 将指令发送给 CPU,再读回结果。不使用任何外部工具调用或运行时。 一旦我们的 CPU 收到指令,计算层就会运行,然后写入工具响应。我们使用一个名为 RvChat 的小型驱动程序,将固件加载到 GDN 状态中,从而避免执行轨迹 token 进入 Qwen 的各层。
Qwen 原有权重保持完全不变。计算机权重叠加于其上,使用额外的维度和层。
它能用吗?
我想,读完我这些喋喋不休的牢骚后,你脑海中最主要的问题一定是:这真的能用吗?

在 DeepMind 数据集上:
- div_big:Qwenputer 的得分为 97.5%,给 Qwen 3.5 4B 配备 Python 工具后得分为 95%,而基础 Qwen 为 72.5%。
- mul_big: Qwenputer 得分 97.5%,配备 Python 工具时为 100%,基础版 Qwen 为 55%。
- mul_div_multiple_longer: Qwenputer 得分 100%,配备 Python 工具时为 97.5%,基础版 Qwen 为 90%。
- add_or_sub_big: Qwenputer 得分 97.5%,与配备 Python 工具时相同,基础版 Qwen 为 87.5%。
在 NUPA 的长整数算术测试中,Qwenputer 从 48.6% 提升到 100%,与给 Qwen 配备 Python 工具相当。
CPU 输出的数字也完全准确:我将其输出中约 230,000 个位置的结果与参考机器逐一比对,未发现任何不匹配。而且,给 Qwen 装上一台计算机并不会改变它的表达方式:其常规文本与基础版 Qwen 的差异仍处于噪声范围内(KL 6e-4,噪声底为 5e-4)。
硬盘?都这经济状况了?
既然语言模型内部的 CPU 显然还没受够诅咒,我决定稳妥起见,也给它加一个文件系统。
既然我们已经有了一个可用的 RAM,这基本上不成问题。在模型侧,它通过内部的 put / append / get / list / delete 操作提供接口。 再次强调,没有实际工具调用。 当 Qwen“保存”文件时,编译后的各个层会把文件名哈希到保存在 DeltaNet 状态中的某个目录的 1,024 个槽位之一,并把文本本身存在其他 head 中,每行存放八个 token,并串联在一起。在两个名称落到同一槽位的情况下,它只需检查下一个槽位。再次查找文件大约只需两三个步骤,而不必进行扫描,并且最多可容纳 512 个文件,约合 53,000 个文本 token。
有意思的是,这东西还挺持久。你可以在对话结束时保存状态,再把它加载到下一次对话中,文件仍然存在。利用这个文件系统,Qwen 对聊天之间发生变化的事实有 90% 的时候能回答正确,而把旧对话粘贴回去时正确率只有 30%;其表现也与给 Qwen 配备由 Python 运行的记忆工具相当(83.3% 对 78.9%)。这个功能仍处于实验阶段,代码位于 rv-store 分支,模型则可在 Hugging Face 和 ModelScope 上获取。
限制与下一步
Qwenputer 在很大程度上仍是一项实验,因此也存在一些限制。额外的层和更宽的隐藏层尺寸使模型检查点达到 18.8 GB,约为基础版 Qwen 的两倍,尽管其中大部分是零填充。它还需要一个小型驱动程序(RvChat)来启动固件,并将 trace token 隔离在 Qwen 的各层之外,因此目前还不能通过普通的 generate() 调用运行。而且它的速度也有点慢,每条 CPU 指令都要消耗几个解码 token,因此大型计算需要数秒而不是数毫秒。我在基准测试中使用的批处理执行器,在 L4 上每秒可运行约 3,200 个 CPU token。
接下来,我想让 Qwen 编写 Python,并让它运行在自身权重内的 MicroPython 上,通过一个 python() 工具来执行,该工具的工作方式与 calc 相同。让 CPU 更快是另一项重点。
算术之外
对 RNN 层的精确控制,用途远不止算术,还可用于大量其他领域。它也让 Qwenputer 成为 AI 安全研究的绝佳试验场。我还写了两篇后续文章:一篇讲像 Qwen 3.5 这样的混合模型如何学会将推理过程隐藏在 RNN 状态中并规避 CoT 监控,另一篇讲编译后的权重如何作为可监控性工具发挥作用,比如模型无法关闭的权重内监控器,或用于可解释性的答案密钥。
试一试
如果你想亲自上手试用,该模型可在一块 24 GB GPU 上运行。你需要 uv 和 Hugging Face CLI。计算时,你不需要工具服务器或 Python 沙箱:这些计算由 CPU 在模型内部运行。
git clone https://github.com/divagr18/qwenputer && cd qwenputer/experimental/riscv && uv sync --extra hf
hf download divagr1925/Qwen3.5-4B-Qwenputer --local-dir qwenputer-rv
uv run python -m chipformer.rv.chat qwenputer-rv --firmware tests/data/rv/calc-bridge.elf \
--ask "Use calc: what is 123456789 * 987654321?"所有内容均已开放:GitHub 上的代码,以及 Hugging Face(Qwenputer、Filesystem)和 ModelScope(Qwenputer、Filesystem)上的两个模型。
如果你在工作中使用它,可以按以下方式引用:
@software{agrawal2026qwenputer,
author = {Agrawal, Divyansh},
title = {{Qwenputer}: a computer compiled into the weights of a pretrained language model},
year = {2026},
url = {https://github.com/divagr18/qwenputer}
}注释
- 每个 Gated DeltaNet 头都会保留一个状态矩阵,也就是它的记忆。在每个 token 处,在写入任何新内容之前,它会用门控值乘以整个状态,门控值是一个介于 0 和 1 之间的数字。RNN 正是这样实现遗忘的:门控值为 0.9 时,每个 token 都会让存储的所有内容略微淡化;门控值为 1 则意味着任何内容都不会淡化。↩
- 经过门控后,该头会将状态的某个方向朝新值微调,而写入强度 beta 决定调整幅度。beta 为 1 时,沿该方向的旧值会被完全替换,而不是进行混合。↩
- 独热键是一个只有单个 1、其余均为 0 的向量,因此它会恰好指向状态中的一行,就像内存地址指向单个存储单元一样。↩
- Imanol Schlag、Kazuki Irie 和 Jürgen Schmidhuber,“线性 Transformer 其实是快速权重程序员”,ICML 2021。↩
- 自由运行是指,在整个运行过程中,CPU 都依据自身输出持续运行,步骤之间没有参考机器对其进行纠正。↩
来源:Hacker News · divagr.com