跳到正文
Hacker News· khalidkhair·· 21 天前精选AI 评分64

Janas:通过从 SSD 流式加载 MoE 专家,让笔记本运行超过内存容量的 LLM

Janas: Run LLMs larger than RAM by streaming experts from SSD

AI 导读

Janas-LLM 是一款用 C 写的开源推理工具,能在 32GB 内存笔记本上通过 NVMe SSD 流式加载 MoE 专家来运行 80B 级大模型。

推荐理由

实测方案较完整,32GB 内存笔记本跑 80B MoE 模型的吞吐数据齐备,并附同一硬件下与 llama.cpp 的逐项速度对比。

正文 · AI 翻译

Status: experimental Platform: Linux | Windows x86-64 LinkedIn Substack

在配备 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