Janas:通过从 SSD 流式加载 MoE 专家,让笔记本运行超过内存容量的 LLM
Janas: Run LLMs larger than RAM by streaming experts from SSD
Janas-LLM 是一款用 C 写的开源推理工具,能在 32GB 内存笔记本上通过 NVMe SSD 流式加载 MoE 专家来运行 80B 级大模型。
实测方案较完整,32GB 内存笔记本跑 80B MoE 模型的吞吐数据齐备,并附同一硬件下与 llama.cpp 的逐项速度对比。
在配备 32 GB 内存的笔记本上,Qwen3-Next-80B(一个 48 GB 模型)达到 37 tok/s,无草稿时为 24 tok/s,而 llama.cpp 仅 2.8;读取 prompt 时为 62 tok/s 对比 16。 在同一台笔记本上(Debian 13 Linux、Intel Core Ultra 9 185H、其集成的 Arc GPU、32 GB、NVMe SSD;2026 年 10 月 9-11 日;整机如下),Janas-LLM 在所有对比模型上都比 llama.cpp 快:
| 模型 | 读取 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 读取 prompt 比 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 tok/s),读取 prompt 时混合模型(Qwen3-30B-A3B 132 tok/s)同样快,稠密模型(Qwen3-4B 346 tok/s 对比 193)则快 1.8 倍——后者的完整块通过 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 RAM 的笔记本上运行并给出回答。
由 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 自家的显卡驱动:测试在那里均通过,运行速度见上文 Or on Windows 一节。
引擎的每一步操作都依据其实测结果进行选择,因此换一台机器会产生不同的选择——这部分设计为可移植。未曾尝试的则是其余情况:其他 CPU(尤其是没有 AVX-VNNI 的,或 AMD)、独立显卡、更慢的磁盘、更多或更少的内存。如果你在其他环境中运行,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 token。此处集成 GPU 读取每个提示词(即下文的快速提示词),引擎最终确定的线程数为:几乎在所有模型上,提示词和单个 token 都用性能核心的 12 个线程;少量 token 同时生成时则使用所有可用核心(性能核与能效核,不含低功耗核)。在另一台机器上,引擎可能选择其他线程:每种 pass 的前几次会尝试每个核心——每个性能核心一个线程以及性能核心的线程——保留最快的,之后偶尔再尝试其余线程,因此预热后的机器可能会改变结论(在 i9-14900HX 上,每个线程的速度都不及性能核心 16 个线程的一半)。各轮交替运行,因此机器预热和缓存填充对各种设置的影响相同。不同运行之间会有几个百分点的偏差,首次运行时偏差会更小一些,此时缓存仍在填充中。不用 GPU 时(JANAS_GPU=0),Qwen3-4B 读取相同提示词的速度为 85 tok/s,写入为 27 tok/s。
最后一列是猜测下一个 token 的草稿以及模型对它们的验证,这是同一段文本以更高速率的处理——其全部说明在--mtp下:Qwen3.5 和 Qwen3.6 模型及 Qwen3-Next 自带的预测块,Gemma 4 的助手(自带的小型草稿模型)。它是在聊天回复上测量的:一个普通的英文问题("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 tok/s。当时的 MoE 数据(29 和 30)恰好低于今天的数据;详情见 ChangeLog。
本页顶部与 llama.cpp 的比较是这样测得的:llama.cpp(2026 年 9 月 18 日的构建 2b18470)在同一集成 GPU 上使用其 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 写入前没有 prompt;janas-bench 是在 1,024 个 token 之后),且这是在同一台机器上的结果。llama.cpp 自己的 CPU 后端在这台笔记本上读取表现逊于其 Vulkan 后端(Qwen3-4B 在 20 线程下 70 tok/s),写入则持平。
先在空闲的机器上试一试。 专家缓存会占用模型打开时系统中的空闲内存,模型的其余部分在回答时从磁盘读取,因此任何其他正在运行的程序都会分走自己的一份。它是平缓降速而非崩溃:实测开着浏览器和编辑器时,同一个模型保持约四分之三的速度,磁盘等待时间变为原来的五倍。但你首先看到的应该是这台机器的实际速度,而你打算发给他人的任何测量,都必须在机器独享时取得。
文档
- INSTALL.md — 构建所需的依赖、如何准备模型,以及首次运行
- ChangeLog.md — 变更内容,最新置顶
- MODELS.md — 转换后模型的许可证,以及可以再分发的内容
- CONTRIBUTING.md — 如何贡献,以及署名(sign-off)
- 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 服务器的工具,以及一边读取一边观察的长 prompt:docs/chat.md。
代码补全
janas-server 在编辑器的光标处补全代码,使用代码模型(如 Qwen3-Coder-30B-A3B):llama.vscode 请求 OpenAI 的 /v1/completions 与 suffix,以及 llama.cpp 的 /infill。每次按键发送的窗口保持不动,以便按键只读取它所改变的内容:在笔记本上生成一条建议需 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)。
它立足于他人的工作之上,并予以说明:
- 它运行的模型归其作者所有:阿里巴巴云 Qwen 团队的 Qwen3、Qwen3.5、Qwen3.6 和 Qwen3-Next,谷歌的 Gemma 4;GGUF 量化由 Qwen、bartowski 和 unsloth 完成(MODELS.md 列出每个来源)。
- llama.cpp 和 ggml 是引擎对照检查的参考(logits、tokens、速度);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(数据遵循开放数据库许可证)及adsb.fi读取飞机的位置,从adsbdb.com读取航线,并在用户提供密钥的情况下从AviationStack读取航班时刻表;其地点表格由OurAirports(公共领域)、GeoNames(CC BY 4.0)和Natural Earth(公共领域)构建。janas-quakes从INGV(意大利国家地球物理与火山学研究所,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)读取警报,从意大利民防部(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 许可,每个回答都会给出页面地址。- 在自己机器上试用并报告所见情况的人,在本仓库的议题中:他们的反馈不止一次改变了引擎(所选的线程、提示词的进度、GPU 的诊断)。
许可证
版权 © 2026 Maurizio "camauri" Cammalleri。
Janas 是基于 GNU 通用公共许可证第三版或更高版本的自由软件——详见 LICENSE。每个源文件都带有其 SPDX 标识行。
janas-server(且仅有它)内置编译了两个第三方库,其源代码未做修改,保留在 src/third_party/ 中,并附带各自的许可证及来源信息:GNU libmicrohttpd 1.0.10(LGPL 2.1 或更高版本,或 eCos 许可证——按此处构建方式不含 HTTPS),以及 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