Janas-LLM 发布:从 SSD 流式加载专家,32GB 笔记本跑 80B MoE 模型
Janas: Run LLMs larger than RAM by streaming experts from SSD
Janas-LLM 是一个用 C 编写、除 C 库外无依赖的推理工具,把权重留在磁盘上,按 token 需要的专家从 NVMe SSD 流式读取,让 80B 参数的 MoE 模型在 32 GB 内存的笔记本上运行。
在 32 GB 内存的笔记本上,Qwen3-Next-80B(一个 48 GB 的模型)达到 37 tok/s,无草稿时 24 tok/s,而 llama.cpp 只有 2.8;读取提示词时,62 tok/s 对 16。 在同一台笔记本上比较的每个模型中,Janas-LLM 都比 llama.cpp 更快(Debian 13 Linux、Intel Core Ultra 9 185H、其集成 Arc GPU、32 GB、一块 NVMe SSD;2026 年 10 月 9-11 日;整台机器见下方):
| 模型 | 读取 1,024 个 token:Janas-LLM | llama.cpp | 写入:Janas-LLM | llama.cpp |
|---|---|---|---|---|
| Qwen3-Next-80B-A3B(48.4 GB,超过内存) | 62 tok/s | 16 tok/s | 24 tok/s | 2.8 tok/s |
| Qwen3-Coder-Next(48.4 GB,超过内存) | 66 tok/s | 14 tok/s | 22 tok/s | 2.2 tok/s |
| Qwen3.6-35B-A3B | 104 tok/s | 79 tok/s | 19 tok/s | 12 tok/s |
| Qwen3-30B-A3B | 135 tok/s | 122 tok/s | 32 tok/s | 15 tok/s |
| Gemma-4-26B-A4B-it | 84 tok/s | 76 tok/s | 18 tok/s | 12 tok/s |
| Gemma-4-12B-it | 65 tok/s | 46 tok/s | 9.9 tok/s | 7.1 tok/s |
| Qwen3.5-9B | 111 tok/s | 78 tok/s | 14 tok/s | 8.7 tok/s |
| Gemma-4-E4B-it | 122 tok/s | 109 tok/s | 20 tok/s | 15 tok/s |
| Qwen3-4B | 193 tok/s | 164 tok/s | 27 tok/s | 18 tok/s |
| Gemma-4-E2B-it | 191 tok/s | 150 tok/s | 38 tok/s | 19 tok/s |
| Qwen3.5-2B | 441 tok/s | 323 tok/s | 52 tok/s | 28 tok/s |
| Qwen3.5-0.8B | 799 tok/s | 519 tok/s | 109 tok/s | 32 tok/s |
| Qwen3-0.6B | 939 tok/s | 670 tok/s | 130 tok/s | 45 tok/s |
来自其他来源的相同模型,就在它们旁边的目录中:
| 模型 | 读取 1,024 个 token:Janas-LLM | llama.cpp | 写入:Janas-LLM | llama.cpp |
|---|---|---|---|---|
| Qwen3-30B-A3B,bartowski 的 Q4_K_M(重要性矩阵) | 131 tok/s | 122 tok/s | 32 tok/s | 16 tok/s |
| Qwen3-30B-A3B,unsloth 的 UD-Q3_K_XL(3 位) | 100 tok/s | 112 tok/s | 36 tok/s | 11 tok/s |
| Qwen3-4B,bartowski 的 Q4_K_M(重要性矩阵) | 191 tok/s | 160 tok/s | 26 tok/s | 18 tok/s |
一个例外:3 位的 Qwen3-30B 读取提示词比 llama.cpp 慢,因为它的 Q3_K 权重尚未进入 GPU 的快速提示词路径;它的写入速度是后者的三倍。
它们是如何测量的,以及带草稿时的速度:现在可用的功能。在另一台机器上数字会不同:janas-bench 可以测量你的机器。
试试看 在 Linux x86-64(Ubuntu 22.04、Debian 12 及更高版本)上:
curl -LO https://github.com/prabanta-dev/janas/releases/latest/download/janas-linux-x86_64.tar.gz tar xf janas-linux-x86_64.tar.gz && cd janas ./janas-chat # the models it knows: pick one, it is downloaded and checked
或在 Windows 10(1903 或更高版本)和 11、x86-64 上:下载 janas-windows-x86_64.zip,解压,然后在其 janas 文件夹中的终端里运行 .\janas-chat。在同一台笔记本上,Windows 11 下(2026 年 10 月 12 日),Janas-LLM 的写入速度与 Linux 上一样快(Qwen3-4B 25.6 tok/s,Qwen3-30B-A3B 34.2),读取提示词时混合模型一样快(Qwen3-30B-A3B 132 tok/s),而稠密模型快 1.8 倍(Qwen3-4B 346 tok/s 对 193),因为其整个块都通过 Intel 自己的 Windows 驱动进入 GPU。
这些模型已从 Hugging Face 转换好;从源码构建:入门指南。
▄███████████▄
▄███████████████▄
███ ▄ █████ ▄ ███ ▄ J A N A S
███▄▄▄█████▄▄▄████
▀█████▄▀▀▀▄█████▀ ▀ a family of tools for artificial intelligence, in C
█████████████
█ █ █ █ █ █ █ █
▀ ▀ ▀ ▀ ▀ ▀ ▀ ▀
Janas 是一套用 C 编写、除 C 库外无任何依赖的人工智能工具家族。它的第一个组件 Janas-LLM 可在普通计算机上运行大型混合专家语言模型,无论有无 GPU:权重留在磁盘上,每个 token 所需的专家从 NVMe SSD 流式读取,反复出现的专家则留在内存中。一个 800 亿参数的模型可以在 32 GB 内存的笔记本上运行并作答。
由 Maurizio "camauri" Cammalleri 设计并编写。
⚠️ 请先阅读
这是一个实验,不是产品。
| 阶段 | 早期开发。公共 API 和命令行会随时更改,而且一周内已更改多次。模型文件是例外:发布在 Hugging Face 上的 .jns 文件(格式版本 2)将被之后每个版本的 Janas-LLM 读取。 |
| 稳定性 | 未经验证。该引擎有意对机器要求苛刻:它用专家缓存填满空闲内存,并以全速用 O_DIRECT 读取磁盘。在余量比它预估更少的机器上,桌面可能被推入交换分区,变得缓慢或无响应。使用 GPU 曾有一次导致驱动重置,并连带拖垮了桌面。 |
| 数据 | 它只写入 ~/.cache/janas(它了解到的关于你机器的信息,以及它已读取过的系统消息,以免再次读取)以及你指定放置转换后模型的位置。它不会改动所读取的模型文件。 |
| 硬件 | 在一台机器(见下文)上开发和运行。在其他任何机器上都未经测试:可能更慢,可能拒绝该模型,也可能行为异常。 |
如果出现问题,Ctrl-C 会停止回复,Ctrl-D 会退出聊天;--cache <GiB> 对它占用的内存设置硬性上限,JANAS_GPU=0 则让它完全避开 GPU。
它成长所在的机器
本仓库中的所有内容都是在以下环境编写和测量的:
- Linux Debian 13(trixie),x86-64,内核 6.12.107;GPU 驱动 Mesa 26.1.6(Vulkan);使用 GCC 14.2 构建
- Intel Core Ultra 9 185H(6 个性能核、8 个能效核、2 个低功耗核;AVX2、FMA、F16C、AVX-VNNI;集成 Arc GPU)
- 32 GB DDR5 内存
- 1 TB NVMe SSD(读取约 5.7 GB/s)
Windows 构建在同一台笔记本上、Windows 11(build 26300)下运行,使用 Intel 自带的显卡驱动:其测试在那里通过,速度如何见上文的或在 Windows 上。
引擎所做的一切都根据它测量到的结果来选择,因此另一台机器会做出其他选择——这部分本就设计为可迁移。从未尝试过的是其余部分:其他 CPU(尤其是没有 AVX-VNNI 的,或 AMD)、独立 GPU、更慢的磁盘、更多或更少的内存。如果你在其他地方运行它,来自 janas-bench 的报告是你能发回的最有用的东西(见 帮助它在更多硬件上运行)。
目前可用的功能
Janas-LLM 今天能运行的内容,按模型和功能逐项列出:docs/features.md。
在上述机器上,没有运行其他程序时,janas-bench 报告如下(测量于 2026 年 10 月 10 日,使用引擎自那天起默认采用的快速提示):
| 模型 | 读取提示 | 写入回复 | 带草稿,在聊天中 |
|---|---|---|---|
| Qwen3.5-2B(稠密,1.3 GB) | 395 tok/s | 50 tok/s | 67 tok/s |
| Qwen3-4B(稠密,2.5 GB) | 220 tok/s | 28 tok/s | 见下文 --draft |
| Qwen3.5-9B(稠密,5.7 GB) | 103 tok/s | 14 tok/s | 24 tok/s |
| Qwen3-30B-A3B(18.6 GB) | 133 tok/s | 34 tok/s | — |
| Qwen3.6-35B-A3B(22.3 GB) | 86 tok/s | 25 tok/s | 34 tok/s |
| Qwen3-Next-80B-A3B(48.4 GB) | 64 tok/s | 22 tok/s | 37 tok/s |
| Gemma-4-E2B-it(3.1 GB) | 211 tok/s | 38 tok/s | 52 tok/s |
| Gemma-4-E4B-it(5.0 GB) | 133 tok/s | 20 tok/s | 32 tok/s |
| Gemma-4-12B-it(稠密,7.1 GB) | 71 tok/s | 10 tok/s | 14 tok/s |
| Gemma-4-26B-A4B-it(18.3 GB) | 90 tok/s | 18 tok/s | 26 tok/s |
每个数字都是三轮的平均值,而非最佳一轮,采用的是引擎自身为每种 pass 选定的配置——也就是聊天运行时所用的配置:先输入 256 个 token 的提示,再生成 64 个。此处集成 GPU 读取每个提示(即下方的快速提示),而引擎最终选定的线程数,在几乎所有模型上,提示处理和单 token 生成都使用性能核的 12 个线程;一次处理多个 token 时则使用所有可用核心(性能核与能效核,不含低功耗核)。在另一台机器上,引擎可能会选定其他线程:每种 pass 的首次尝试会遍历所有核心,每个性能核一个线程以及性能核的线程,保留最快的,之后偶尔再试其他线程,因此一台预热后的机器可能改变结论(在 i9-14900HX 上,每个线程的响应速度都不到性能核 16 个线程的一半)。各轮交替运行,使机器预热和缓存填充对每个设置的影响相同。预计各次运行之间会有几个百分点的波动,而首次运行时波动更小,因为此时缓存仍在填充。不使用 GPU(JANAS_GPU=0)时,Qwen3-4B 读取相同提示的速度为 85 tok/s,写入速度为 27。
最后一列是草稿猜测后续 token、模型再对其进行校验,本质上是同一段文本以更高速度生成——其全部原理在 --mtp 下解释:Qwen3.5 和 Qwen3.6 模型以及 Qwen3-Next 自带的预测块,Gemma 4 的 assistant(其自带的小型草稿模型)。它是在一次聊天回复上测量的:一个普通的英文问题(“explain how bread is made at home”),回答 64 个 token,按聊天采样方式采样。草稿的价值取决于文本:在那里,草稿在 Qwen 模型和 Gemma 的两个较大模型上存活率为 74-89%,在 Gemma 的 E2B 和 E4B 上为 63-72%;在意大利语散文上,Qwen3.5-2B 保留了约三分之一,几乎毫无增益。64 个 token 的一轮在这里噪声很大,各次运行之间会有十分之一的波动。Qwen3-30B-A3B 没有这样的块,稠密 Qwen3 也没有;稠密 Qwen3.5 在其原始检查点中有一个,由 hf2jns_mtp 转换(MODELS.md)。
此列在 2026 年 9 月 26 日之前是错误的,而且数值更高:它测量的是该块续写一段自我重复的段落,模型会照抄,而该块几乎每次都能猜中——Qwen3.5-2B 为 107 tok/s,Qwen3.5-9B 为 26。当时的 MoE 数据(29 和 30)恰好低于今天;ChangeLog 中有详细信息。
本页顶部与 llama.cpp 的对比是这样测量的:llama.cpp(2026 年 9 月 18 日的构建 2b18470)及其 Vulkan 后端在同一集成 GPU 上,全部放在其上(llama-bench -p 1024 -n 16 -ngl 99 -t 12;否则为下方最大的模型),与 janas-bench --prompt 1024 --gen 16 在相同文件、相同日期(2026 年 10 月 9-11 日;llama.cpp 的最佳配置,Janas-LLM 自己的选择;10 月 11 日各跑三轮,llama-bench -r 3 和 janas-bench --rounds 3,针对 Qwen3-0.6B、Qwen3.5-0.8B、Qwen3.6-35B-A3B 以及来自其他来源的模型;Qwen3-Coder-Next 作为 Qwen3-Next-80B,见下方)进行对比。
在 Qwen3-Next-80B-A3B 上,其文件比这台笔记本电脑的 30 GB 还大,llama.cpp 用其常规构建在 GPU 一参与时就内存不足,即使把专家留在 CPU 上(-ngl 99 -ncmoe 48):它的 CPU 后端会自行把权重复制到内存中以重新打包,而 Vulkan 后端会把那些留给 CPU 的权重复制到系统无法回收的缓冲区中。它用一个不做重新打包的构建(GGML_CPU_REPACK=OFF)外加两个选项 --no-host 1 -lm mmap 运行,这些选项把专家留在文件中,通过页缓存读取:用 GPU 读取为 16 tok/s,仅用 CPU 写入为 2.8(用 GPU 则为 2.0);这就是它在表中的两个数字。Janas-LLM 用自身无任何选项运行了同一模型,它最常使用的专家放在约 19 GB 的缓存中,其余从磁盘读取。Janas-LLM 的数字各为一轮;写入列两边都未使用草稿。这两个工具的测量方式并不完全相同(llama-bench 写入前没有提示;janas-bench 在 1,024 个 token 之后),而且只有一台机器。llama.cpp 自己的 CPU 后端在这台笔记本电脑上读取表现不如其 Vulkan 后端(Qwen3-4B 在 20 线程上为 70 tok/s),写入表现则相当。
先在空闲机器上试一下。专家缓存会占用模型打开时的空闲内存,模型其余部分在回答时从磁盘读取,因此其他正在运行的程序都会分走一份。它会平缓降级而非崩溃:在打开浏览器和编辑器的情况下测量,同一模型保持了约四分之三的速度,在磁盘上等待的时间长了五倍。但你首先看到的应该是机器的真实速度,任何你要发给别人的测量都必须在机器独占时进行。
文档
- INSTALL.md — 构建需要什么、如何准备模型,以及首次运行
- ChangeLog.md — 变更内容,最新的在前
- MODELS.md — 转换后模型的许可证是什么,以及哪些可以再分发
- CONTRIBUTING.md — 如何提供帮助,以及签署确认
- src/services — Janas 的服务,每个都有自己的页面,在
janas-chat和其他 MCP 客户端中 - docs/features.md — Janas-LLM 目前能运行什么,按模型和功能逐项列出
- docs/models.md — 获取模型:
janas-get,或转换后的 GGUF 文件 - docs/chat.md — 使用
janas-chat、其服务以及来自 MCP 服务器的工具 - docs/library.md — 从程序中以 C 或 FreeBASIC 使用它
- docs/serving.md — 将模型提供给 MCP 客户端(
janas-mcp)以及通过 HTTP(janas-server) - docs/code-completion.md — 在 VSCodium 和 VS Code 中通过
janas-server进行代码补全 - docs/tools.md — 转换器、检查器和基准测试
- docs/hardware.md — 测量你的机器,并帮助它在更多硬件上运行
- AUTHORS — 谁编写了它,以及它归功于谁
- LICENSE — GNU GPL,版本 3 或更高
快速开始
sudo apt install build-essential # Debian/Ubuntu sudo apt install libvulkan-dev glslang-tools vulkan-tools # optional, GPU sudo pacman -S vulkan-headers glslang vulkan-tools # the same, Arch ./build.sh # everything into bin/x86_64-linux/ ./build.sh release test # and run the tests
获取模型
下载已用 janas-get 转换好的模型,或自行转换 GGUF 文件,以及哪些文件经过检查:docs/models.md。
使用聊天
janas-chat:其选项和命令、草稿、Janas 的服务、来自 MCP 服务器的工具、在读取时观察长提示:docs/chat.md。
填写代码
janas-server 在编辑器光标处填充代码,使用诸如 Qwen3-Coder-30B-A3B 这样的代码模型:OpenAI 的 /v1/completions 配合 suffix,以及 llama.cpp 的 /infill,llama.vscode 会请求这些。每次按键时发送的窗口保持不变,因此一次按键只读取它改变的内容:在笔记本电脑上每个建议耗时 1.5-2.2 秒,而滑动一行的窗口需要 17 秒才能重新读取。如何在 VSCodium 和 VS Code 中设置,使用 llama.vscode 或 Continue,以及测量了什么:docs/code-completion.md。
从程序中使用它
从 C 以及从 FreeBASIC 和 BASIC MODERN 使用该库,以及从程序中使用 MCP 服务器:docs/library.md。
Janas 作为 MCP 服务器
janas-mcp:将模型作为工具供 Claude Code、编辑器和其他 MCP 客户端使用:docs/serving.md。
通过 HTTP 使用它
janas-server:一个遵循 OpenAI 的 HTTP API,以及一个可从浏览器试用它的聊天页面:docs/serving.md。
测量你的机器
janas-bench:它测量什么,以及它留下的报告:docs/hardware.md。
工具
与程序一同构建的转换器、检查器和基准测试:docs/tools.md。
帮助它在更多硬件上运行
最需要哪些机器,尝试 Janas 并写出报告的那一条命令,以及要发送什么:docs/hardware.md。
致谢
Janas 由 Maurizio "camauri" Cammalleri 设计和编写(LinkedIn,Substack)。
它立足于他人的工作,并如实说明:
- 它运行的模型属于它们的作者:Qwen3、Qwen3.5、Qwen3.6 和 Qwen3-Next 来自阿里云 Qwen 团队,Gemma 4 来自 Google;GGUF 量化来自 Qwen、bartowski 和 unsloth(MODELS.md 列出了所有来源)。
- llama.cpp 和 ggml 是引擎对照检查的参考(logits、token、速度);它们的代码没有一行在 Janas 中。从 ggml 中取用的唯一东西是定义格式的数据:IQ3_S 网格,位于
src/llm/iq3s_grid.h,依据 ggml 的 MIT 许可证。 - Unicode 字符数据库为分词器提供其表格(
tools/gen_unicode),而OpenAI 的 OpenAPI 规范为janas-server提供其路由表(tools/openapi_routes)。 - GNU libmicrohttpd、yyjson 和 Mbed TLS 被编译进下面列出的程序中。
janas-flights从 adsb.lol(数据依据 Open Database License)和 adsb.fi 读取飞机位置,从 adsbdb.com 读取航线,并使用用户自己的密钥从 AviationStack 读取航班时刻表;其地点表格由 OurAirports(公有领域)、GeoNames(CC BY 4.0)和 Natural Earth(公有领域)构建。janas-quakes从 INGV(Istituto Nazionale di Geofisica e Vulcanologia,CC BY 4.0)读取意大利及其海域的地震,从 USGS(公有领域)读取其他地方的地震,并从 Nominatim(© OpenStreetMap 贡献者,ODbL)读取地点。janas-weather从 Open-Meteo(CC BY 4.0)和 MET Norway(CC BY 4.0)读取预报和海况,从 aviationweather.gov(NOAA)读取站点报告,从 MeteoAlarm(EUMETNET)读取预警,从 Dipartimento della Protezione Civile(CC BY 4.0)读取意大利警报级别。未指定地点时,这些服务会询问 GeoJS 或 ipwho.is 互联网连接所在的位置。janas-maps通过 OpenStreetMap 的数据(© OpenStreetMap 贡献者,ODbL),经由 Nominatim、Photon、Valhalla 和 OSRM 在 FOSSGIS 的服务器上读取,以及 Overpass API(繁忙时使用 Private.coffee 的实例),并通过 Transitous 从运营商的开放时刻表获取公共交通行程。janas-prices读取 European Central Bank(通过 Frankfurter)、CoinGecko(数据由 CoinGecko 提供)和 Coinbase、使用用户密钥的 Alpha Vantage、Eurostat 和 World Bank(CC BY 4.0)、New York Fed、Bank of England 和 Swiss National Bank、energy-charts.info(Fraunhofer ISE;区域数据在 CC BY 4.0 下,来自 Bundesnetzagentur 的 SMARD),以及意大利 MIMIT(IODL 2.0)、法国 prix-carburants、西班牙 ministry 和奥地利 E-Control 的燃料价格;地点通过 Nominatim。janas-github读取 GitHub 的 REST API;janas-git运行 git。janas-wiki通过其 API 读取 Wikipedia;文本来自 Wikipedia,在 CC BY-SA 4.0 下,每个回答都会给出页面的地址。- 在自己的机器上尝试过它的人,并在这个仓库的 issue 中报告了他们看到的情况:他们的报告不止一次改变了引擎(它选择的线程、提示的进度、GPU 的诊断)。
许可证
版权所有 © 2026 Maurizio "camauri" Cammalleri。
Janas 是自由软件,采用 GNU General Public License,版本 3 或更高版本——参见 LICENSE。每个源文件都带有其 SPDX 行。
janas-server,且只有它,编译进了两个他人的库,其源代码在 src/third_party/ 中未作修改,并附有其许可证及来源:GNU libmicrohttpd 1.0.10(LGPL 2.1 或更高版本,或在此构建时无 HTTPS 的 eCos 许可证)和 yyjson 0.13.0(MIT)。libjanas_mcp 以及随附的程序带有 Mbed TLS 4.2.0 和 TF-PSA-Crypto(Apache-2.0 或 GPL-2.0-or-later),用于 https:// MCP 服务器。libjanas_llm 没有。
模型不在其覆盖范围内。 转换后的 .jns 文件是模型的衍生物,而非 Janas 的,并保留其作者赋予的许可证;MODELS.md 说明了本项目将重新分发和不会重新分发的内容,以及在传递转换后的模型之前需要检查什么。
贡献
CONTRIBUTING.md。简而言之:来自这里无人拥有的机器的测量结果比大多数补丁更有价值,并且每次提交都需要一行 Signed-off-by(git commit -s)。
来源:Hacker News · github.com