[控场AI]
· 15 分钟阅读· 7,808 字

NVIDIA Nemotron Dory 4B 本地部署指南:循环架构与 llama.cpp PR 尝鲜

NVIDIA Nemotron Dory 4B 本地部署指南:循环架构与 llama.cpp PR 尝鲜

NVIDIA Dory 4B 以循环架构实现小体积深计算,智能体任务强但运行时支持尚未就绪。

NVIDIA 于 10 月 16 日悄然发布 Nemotron Labs Dory 1.0,一个 4B 参数、采用循环架构的模型:输入块 8 层、共享循环块 20 层(可重复 1 至 4 次)、输出块 8 层,4 次循环时每 token 计算量相当于 96 层深度模型,而磁盘体积不变。基准显示其在 IFBench、AA-LCR 和 SWE-bench 等指令遵循与智能体编程任务上领先同尺寸 Qwen3.5-4B,SWE-bench Verified 达 61.8 分,但在 GPQA、HLE、AA-Omniscience 等知识类任务上明显落后,循环无法弥补参数里装不下的知识。支持现状尴尬:llama.cpp PR 仍为草稿,vLLM PR 未获批,Transformers 无实现,Ollama 无法直接运行。Q5_K_M GGUF 仅 3.67 GB,配合 last_loop 缓存模式可将 256K 上下文显存从约 24 GiB 降至约 9 GiB。

NVIDIA Nemotron Dory 4B 本地部署指南:循环架构与 llama.cpp PR 尝鲜

NVIDIA 新发布的 4B 模型 Nemotron Labs Dory 1.0 在 SWE-bench Verified 上拿到了 61.8 分(NVIDIA 自测),比它大一倍多的 Qwen3.5-9B 也只有 61 分。但尴尬的是,截至 10 月 18 日,官方支持的 llama.cpp、vLLM 和 Transformers 全都还没合并或缺失,想跑起来得自己动手。

Dory 于 10 月 16 日悄然上线 Hugging Face,附带模型卡和 GGUF 仓库,却没有 NVIDIA 官方博客,也没有论文链接。这篇文章会梳理它的核心设计、内存需求,以及如何用 llama.cpp 的 PR 构建在本地跑起来,最后看看 Ollama、vLLM 和 Transformers 的支持现状。

NVIDIA Nemotron Dory 4B 模型发布信息

循环架构:4B 的参数量,更深的计算量

大多数小模型每个 token 只经过一次固定的层堆叠,而 Dory 由三部分组成:输入块(8 层)、共享循环块(20 层,可重复 1 到 4 次)和输出块(8 层)。输入会在每次循环时重新注入,循环次数在启动时指定,无需重新训练。

  • 1 次循环:最便宜,每 token 经过 36 层
  • 2 次循环:NVIDIA 推荐的默认值,「大部分精度提升来自第二次循环」
  • 4 次循环:面向 SWE-bench、Terminal-Bench 等智能体编程任务,每 token 经过 8 + 80 + 8 = 96 层

「4B」只是磁盘上的体积。在 4 次循环下,每 token 的计算量相当于一个深得多的模型,但存储仍然很小。

其他关键规格:

  • 归一化 GPT 架构,滑动窗口注意力(1024 token 窗口)与全注意力层混合,每三层滑动对应一层全注意力
  • 256K 上下文(模型卡标注为已验证)
  • 131,072 token 词表,隐藏维度 2560,16 个查询头,4 个 KV 头,头维度 256
  • 约 6T 预训练 token,前 4.5T 使用 NVFP4 原生训练,后续 BF16,再加 300B token 的上下文扩展,以及 SFT 和基于 GRPO 的强化学习
  • 仅支持英语,训练涵盖 43 种编程语言
  • OpenMDW License v1.1,模型卡称「可用于商业或非商业用途」

许可证值得肯定。OpenMDW 授予「模型材料」(包括架构和参数)「无限制」的权利,对于选择 4B 模型的公司来说,这比任何单项基准分数都重要。

循环架构(Recurrent / Looped Transformer) 指同一组权重被多次重复执行,而非堆叠更多独立层。其思想可追溯到 Universal Transformer 与 Deep Equilibrium Models:通过增加「计算深度」而不增加「参数数量」来提升推理能力。由于每次循环共享参数,模型体积保持不变,但每 token 的 FLOPs 随循环次数线性增长。NVIDIA 的「输入重注入」是在每次进入循环块前把原始输入表示加回去,防止深层循环中信息被稀释,这使它无需重新训练即可在推理时改变循环次数——一次训练、多种深度。代价是 KV 缓存的分配策略变成新问题:共享层在循环中是否复用同一份缓存,直接决定显存占用,这正是后文 per_loop 与 last_loop 两种模式的分歧所在。

基准测试:智能体任务强,知识事实弱

以下数据均来自 NVIDIA 自己的测试工具(NeMo Gym / NeMo Evaluator),目前尚未找到独立复现。模型卡中的 Artificial Analysis 指数图表是内部估算,可能与官方 AA 分数有偏差。

基准测试Dory 1 循环Dory 2 循环Dory 4 循环Qwen3.5-4BQwen3.5-9B
SWE-bench Verified50.359.561.854.761
Terminal-Bench 2.112.518.122.21524
IFBench74.2977.947953.8359
AA-LCR63717364.768.4
GPQA Diamond69.1972.4172.1677.7180.93
HLE(文本,无工具)8.2510.8910.4311.3115.43
AA-Omniscience10.0310.0810.0315.0218.05

AA-Omniscience 一行从 1 次循环到 4 次循环几乎没变化(10.03、10.08、10.03)。循环给了模型更多步骤来推理,但无法增加 4B 参数里装不下的知识。GPQA 和 HLE 也是同样趋势:Dory 在每个循环次数下都落后于 Qwen3.5-4B。

Dory 胜出的领域是指令遵循(IFBench 领先 Qwen3.5-4B 超过 20 分)、长上下文推理(AA-LCR)和 2 次以上循环的 SWE-bench。这正是本地编码智能体或工具调用 Worker 需要的画像,而不适合做口袋百科全书。

对比需注意:模型卡还列出了 Gemma 4 26B A4B 和 Qwen3.6-35B-A3B 等更大模型,其中 Qwen3.6 的 SWE-bench 分数(73.4)是 NVIDIA 引用而非亲自运行。模型卡没有 Phi 行,也没有同尺寸的 Gemma 模型,所以期待与 Phi-4-mini 等算力对齐的对比落空了。

模型基准测试数据展示

内存与显存需求

模型卡未给出最低内存要求,但根据文件和配置可以推算。

格式磁盘权重运行平台
BF167.95 GB任何有 ~10 GB+ 空闲显存的 GPU,另加 KV 缓存
Q5_K_M GGUF3.67 GB笔记本、Apple Silicon、6-8 GB 显存 GPU
MXFP84.75 GBHopper/Blackwell,DGX Spark 上 batch size 1 比 BF16 快 1.69-1.84 倍
NVFP43.20 GBHopper/Blackwell,DGX Spark 上 batch size 1 比 BF16 快 2.17-2.44 倍

KV 缓存是循环架构的主要开销。默认 per_loop 模式下,每次通过循环块都保留独立缓存。根据 config.json 的 layer_types 计算,共有 9 个全注意力层(输入块 2 个、循环块 5 个、输出块 2 个),每层每 token 存储 4 个 KV 头 × 256 维 × K 和 V × 2 字节 = 4 KiB。在 per_loop 模式下,循环块的 5 层按循环次数重复计算:2 次循环意味着 14 个全注意力缓存,32K 上下文约 1.75 GiB,256K 上下文约 14 GiB;4 次循环则是 24 个缓存,256K 下约 24 GiB。滑动窗口层最多只存 1024 token,几乎可忽略。

解决方法是切换到 last_loop 模式,无论循环多少次都「每个循环注意力层只保留单个缓存」,回到 9 个缓存(256K 下约 9 GiB,32K 下约 1.1 GiB)。NVIDIA 表示精度「接近 per-loop 模式」。内存紧张时优先设置这个。

KV 缓存是大模型推理时保存历史 token 的 Key/Value 张量,避免每生成一个新 token 都重算全部上下文。其大小公式为:层数 × 2(K 和 V)× KV 头数 × 头维度 × 上下文长度 × 每元素字节数。文中每层每 token 4 KiB 即来自 2 × 4 × 256 × 2 字节。多头注意力中 GQA(分组查询注意力) 让多个查询头共享少数 KV 头,Dory 的 16 查询头对 4 KV 头正是 4:1 的 GQA,这也是其缓存相对同规模模型更省的原因。滑动窗口注意力则只保留最近 1024 个 token 的 KV,缓存上限被窗口封顶,因此文中称其「几乎可忽略」。循环架构的特殊之处在于共享层被多次执行,若每次循环都保留独立缓存,总缓存数会随循环次数成倍增加,因此缓存模式的选择比普通模型更关键。

用 llama.cpp PR 构建在本地运行

支持位于 llama.cpp PR #30306,目前是草稿状态,需要两个批准,仍在等待 CISC 和 ggerganov 的审查。10 月 17 日有人询问是否还有阻碍,尚无回复。PR 描述承认 Metal 未测试,长上下文资格认证未完成。有趣的是,GGUF 模型卡的构建说明却是面向 Apple Silicon 的 Metal,使用作者 fork 中的固定提交:

git init llama.cpp-dory
cd llama.cpp-dory
git remote add origin https://github.com/brianchmielNV/llama.cpp.git
git fetch --depth 1 origin 98a74c97ea09ac72f6ceda1559808fc0a2f447ce
git checkout --detach FETCH_HEAD

完整的 macOS cmake 调用(Metal、Apple BLAS、仅服务器)在 GGUF 页面。在 Linux + NVIDIA 显卡上,可以用常规方式构建同一提交(cmake -B build -DGGML_CUDA=ON)。PR 报告 CPU 和 CUDA 上 96/96 数值检查通过,但 NVIDIA 没有发布 Linux 配方。

仓库中的文件名是 NVIDIA-Nemotron-Labs-Dory1.0-4B-Q5_K_M.gguf,而模型卡命令期望 dory-q5_k_m.gguf,下载后需重命名。校验文件后启动服务器:

echo "96080be49ffd67b916018b7bdef8c484762576fb52780e10ab98ac4978a660e0  dory-q5_k_m.gguf" | shasum -a 256 -c -

./build/bin/llama-server \
    -m ./dory-q5_k_m.gguf \
    --alias dory \
    --host 127.0.0.1 --port 8080 \
    -ngl 999 \
    --ctx-size 4096 --parallel 1 \
    --batch-size 512 --ubatch-size 512 \
    --cache-type-k f16 --cache-type-v f16 \
    --flash-attn off \
    --no-context-shift \
    --jinja --reasoning on \
    --temp 1.0 --top-p 0.95 --top-k 0 --min-p 0 --repeat-penalty 1 \
    --override-kv "dory.num_loops=int:2,dory.recurrent_kv_cache_mode=str:per_loop"

调整 dory.num_loops(1 到 4)来权衡精度与速度。将 per_loop 改为 last_loop 以限制缓存。--no-context-shift 是必需的,因为 PR 不支持上下文移位。当达到 4,096 token 时请求会停止,如果内存允许可提高 --ctx-size。

对于编码智能体,模型卡建议在 extra_body 中传入 "chat_template_kwargs": {"force_nonempty_content": True}。

llama.cpp 的 PR 流程决定了新架构多快能被普通用户用上:新模型架构需在 ggml 与 llama 层添加张量类型、图构建和元数据解析代码,通常由模型厂商工程师提交,需至少两名维护者批准并完成 CI 与数值一致性检查。草稿(Draft)状态下 PR 无法合并,且 API 与配置键随时可能改动——文中提到的 dory.num_loops、recurrent_kv_cache_mode 等 --override-kv 键都可能在合并前改名,这是建议「等一两周」的技术原因。GGUF 是 llama.cpp 使用的单文件模型格式,内含权重、分词器和元数据;文中的 Q5_K_M 指 5 位量化、K-quant 中等混合方案,在体积与精度间取得平衡。-ngl 控制卸载到 GPU 的层数,--flash-attn 与 --jinja 分别启用 FlashAttention 和 Jinja 聊天模板。

Ollama、vLLM 和 Transformers 现状

Hugging Face 的 Local Apps 菜单在 GGUF 页面提供了 ollama run hf.co/nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-GGUF:Q5_K_M,但模型卡本身只记录了 llama.cpp PR 构建,从未提及 Ollama 或通过它覆盖循环参数。预计这个一行命令还无法工作。Ollama 只能运行其引擎支持的架构,而 dory 架构尚未进入上游 llama.cpp,PR 也未提及 Ollama。需要等待合并及 Ollama 新版本。

vLLM 支持在 PR #60149,目前开放且无批准。一位维护者要求模型先进入 Transformers,以免 vLLM 频繁更改配置。作者表示没有 Transformers PR 计划,维护者最终接受了尽力遵循 Transformers 配置约定的方案。另外,作者主张保持 PR 原生实现而不是通过 vLLM 的 Transformers 后端,尚无 vLLM 维护者回复。如果构建该分支,模型卡的 serve 命令如下:

vllm serve --model nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16 \
  --hf-overrides '{"n_recurrent_loops": 2, "recurrent_kv_cache_mode": "per_loop"}' \
  --max-model-len 262144 \
  --max-num-seqs 128 \
  --enable-prefix-caching \
  --async-scheduling \
  --reasoning-parser nemotron_v3 \
  --tool-call-parser qwen3_coder \
  --enable-auto-tool-choice

vLLM 中推理始终开启。如果 GPU 没有空间容纳 256K 的 per_loop 缓存,降低 --max-model-len。

Transformers 的情况最奇怪。仓库标记了 library_name: transformers,但模型卡没有 Transformers 代码片段。config.json 声明 "model_type": "dory",仓库没有 modeling_*.py,截至今日 Transformers 主分支没有 models/dory 目录(最新 PyPI 版本为 5.20.1)。在 vLLM 讨论中,作者表示 NVIDIA 目前不计划提交 Transformers PR,因此当前版本预计会遇到未知架构错误。如果你能用 AutoModelForCausalLM 加载,请告知版本。

Transformers 的 model_type 机制是理解兼容性困局的关键:AutoModelForCausalLM 依据 config.json 中的 model_type 字段在 transformers.models 下查找同名目录和 modeling_*.py 实现,找不到就抛出「未知架构」错误。因此即便 Hugging Face 页面标注 library_name: transformers,只要上游未合并 models/dory,标准加载路径就会失败。vLLM 维护者要求模型先进入 Transformers,是因为 vLLM 会复用 Transformers 的配置类来解析超参,否则每次配置变动都要在 vLLM 内单独维护,增加回归风险。Ollama 则绑定上游 llama.cpp 的架构支持,只有 PR 合并并进入新版本后,ollama run hf.co/... 这类一行命令才可能真正生效。

这周值得尝试吗?

在拥有 8 GB 空闲内存的 Mac 上,值得。构建固定提交,用 last_loop 运行 2 次循环,指向一个小型编码智能体。循环设计是今年 4B 发布中最有趣的东西,启动时改变深度是我希望每个小模型都具备的能力。

在其他平台上,建议等一两周。基准是自报的,两个运行时 PR 可能还会更改配置键,知识分数意味着你仍然需要 Qwen3.5-4B 来处理依赖记忆事实的任务。

你现在本地实际运行哪个 4B 模型?像 Dory 这样的循环模型有机会取代它吗?如果你在 CUDA 上跑通了 PR 构建,欢迎分享 1 次 vs 4 次循环的 tokens/sec——目前还没人公布这些数据。

#NVIDIA Nemotron Dory 4B#本地部署#llama.cpp#循环架构#SWE-bench#vLLM#Ollama#小模型
分享:

相关推荐