<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>LLM Inference on Hypho - AI Agent 技术博客</title><link>https://blog.hypho.cn/tags/llm-inference/</link><description>Recent content in LLM Inference on Hypho - AI Agent 技术博客</description><image><title>Hypho - AI Agent 技术博客</title><url>https://blog.hypho.cn/papermod-cover.png</url><link>https://blog.hypho.cn/papermod-cover.png</link></image><generator>Hugo -- 0.148.2</generator><language>zh-cn</language><lastBuildDate>Wed, 17 Jun 2026 10:06:52 +0800</lastBuildDate><atom:link href="https://blog.hypho.cn/tags/llm-inference/index.xml" rel="self" type="application/rss+xml"/><item><title>Rust 写 GPU 内核终于安全了？cuTile Rust 的 tile-based 方案和它背后的推理引擎</title><link>https://blog.hypho.cn/posts/cutile-rust-safe-gpu-kernel-programming/</link><pubDate>Wed, 17 Jun 2026 10:06:52 +0800</pubDate><guid>https://blog.hypho.cn/posts/cutile-rust-safe-gpu-kernel-programming/</guid><description>NVIDIA Labs 开源的 cuTile Rust 把 Rust 所有权模型延伸到 GPU 内核编程，实现无数据竞争的 tile-based GPU 计算。本文解析其核心机制、与 cuda-oxide 的路线差异、Grout 推理引擎的性能表现，以及 Rust GPU 编程生态的最新格局。</description><content:encoded><![CDATA[<p>如果你关注 GPU 编程和 AI 基础设施，最近应该注意到一个趋势：Rust 正在悄悄渗透进 GPU 开发的每一个角落。NVIDIA Labs 在同一时间开源了两个 Rust GPU 项目——cuda-oxide（2768 stars）和 cuTile Rust（381 stars），前者是把标准 Rust 代码直接编译成 PTX 的 rustc 后端，后者是我们今天要聊的主角：一个基于 tile 抽象的安全 GPU 内核编程系统。</p>
<p>坦白说，第一次看到 cuTile Rust 的 README 时我有点不以为然——又一个 DSL？但读完论文 <em>Fearless Concurrency on the GPU</em> 之后，我的看法变了。这不是简单的语法糖，而是认认真真地把 Rust 的所有权和借用检查搬到了 GPU 内核层面。</p>
<h2 id="问题gpu-内核编程为什么需要安全">问题：GPU 内核编程为什么需要安全？</h2>
<p>写 CUDA 内核的人大概都踩过这些坑：线程越界访问 shared memory、race condition 导致结果随机出错、异步 kernel launch 后 host 端提前释放了显存。传统 CUDA C++ 对这类问题基本靠程序员自觉——你犯了错，程序不会告诉你，只会给你一个错误结果或者 segfault。</p>
<p>cuTile Rust 的核心思路是：既然 Rust 在 CPU 端已经用所有权系统解决了数据竞争问题，为什么不能把这个保证延伸到 GPU 端？</p>
<p>具体来说，cuTile Rust 做了三件事：</p>
<p><strong>1. 可变 tensor 在 launch 前被切分成不相交的块（partition）</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">api</span>::<span class="n">zeros</span>::<span class="o">&lt;</span><span class="kt">f32</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[</span><span class="mi">1024</span><span class="p">]).</span><span class="n">partition</span><span class="p">([</span><span class="mi">128</span><span class="p">]);</span><span class="w">
</span></span></span></code></pre></div><p>这行代码把 1024 个元素的 tensor 切成 8 块，每块 128 个元素。每个 GPU 线程块只能访问自己那一块，物理上不可能发生跨块写冲突。</p>
<p><strong>2. 不可变 tensor 被标记为共享只读</strong></p>
<p>函数签名里的 <code>&amp;Tensor</code> 和 <code>&amp;mut Tensor</code> 直接表达了访问权限：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">add</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">B</span>: <span class="kt">i32</span><span class="o">&gt;</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">z</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Tensor</span><span class="o">&lt;</span><span class="kt">f32</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="n">B</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="o">&gt;</span><span class="p">,</span><span class="w">  </span><span class="c1">// 唯一可写
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="n">x</span>: <span class="kp">&amp;</span><span class="nc">Tensor</span><span class="o">&lt;</span><span class="kt">f32</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="o">&gt;</span><span class="p">,</span><span class="w">     </span><span class="c1">// 只读共享
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">    </span><span class="n">y</span>: <span class="kp">&amp;</span><span class="nc">Tensor</span><span class="o">&lt;</span><span class="kt">f32</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="o">&gt;</span><span class="p">,</span><span class="w">     </span><span class="c1">// 只读共享
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">)</span><span class="w">
</span></span></span></code></pre></div><p>这不是注释层面的约定，而是编译器强制的。</p>
<p><strong>3. Host 端在 kernel 执行期间保持所有权</strong></p>
<p>launch 一个 kernel 不会把 tensor 的所有权转移走。GPU 在执行时，host 端的 tensor 仍然被&quot;借用&quot;，你没法在这个窗口期意外释放或修改它。这解决了异步执行中最阴险的一类 bug。</p>
<h2 id="性能安全不是免费的这次可能是">性能：安全不是免费的？这次可能是</h2>
<p>论文里的数据相当有说服力。在 NVIDIA B200 上：</p>
<ul>
<li><strong>逐元素操作</strong>：7 TB/s，达到峰值显存带宽的 91%</li>
<li><strong>GEMM（矩阵乘法）</strong>：2 PFlop/s，达到 B200 dense f16 峰值的 92%，和 cuBLAS 差距在 0.3% 以内</li>
<li><strong>Persistent GEMM</strong>：安全版本跑出 2.07 PFlop/s，和低层 Tile IR 版本差距不到 0.3%</li>
</ul>
<p>换句话说，安全抽象带来的运行时开销在测量噪声范围内——几乎为零。</p>
<p>这个结论如果经得起复现，意义很大。它意味着你可以用 Rust 写 GPU 内核，获得编译期安全保证，而不用付出传统上&quot;安全语言写 GPU&quot;的那种性能税。</p>
<h2 id="grout用-cutile-rust-写的推理引擎">Grout：用 cuTile Rust 写的推理引擎</h2>
<p>理论说完了，来看实战。Hugging Face 和 NVIDIA 合作用 cuTile Rust 构建了 <a href="https://github.com/huggingface/grout">Grout</a>，一个纯 Rust 的 Qwen3 推理引擎。</p>
<p>性能数据：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>硬件</th>
          <th>速度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Qwen3-4B</td>
          <td>RTX 5090</td>
          <td>171 tok/s</td>
      </tr>
      <tr>
          <td>Qwen3-32B</td>
          <td>B200</td>
          <td>82 tok/s</td>
      </tr>
  </tbody>
</table>
<p>论文的 HBM roofline 分析显示这些数字和理论带宽上限一致，说明没有明显的效率损失。和 vLLM、SGLang 等成熟的 Python/C++ 推理框架相比，这个性能是 competitive 的。之前我们聊过 <a href="https://blog.hypho.cn/posts/kvarn-vllm-kv-cache-quantization-production/">KVarN 在 vLLM 上做 KV-cache 量化的吞吐优化</a>，以及 <a href="https://blog.hypho.cn/posts/mimo-tilert-1000tps-trillion-parameter-inference/">MiMo × TileRT 的模型-系统联合设计</a>如何在推理吞吐上做到极致——Grout 走的是另一条路：用 Rust 重写整个推理栈，从语言层面消除内存安全隐患。</p>
<p>当然，Grout 目前只有 29 stars，还是个研究性质的 testbed，离生产级推理引擎还有距离。但它证明了一件事：<strong>用 Rust + cuTile Rust 写高性能推理内核是完全可行的</strong>。</p>
<h2 id="cutile-rust-vs-cuda-oxide两条路线">cuTile Rust vs cuda-oxide：两条路线</h2>
<p>NVIDIA Labs 同时维护着两个 Rust GPU 项目，这让不少人困惑。它们的区别其实很清晰：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>cuTile Rust</th>
          <th>cuda-oxide</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>抽象级别</strong></td>
          <td>高层 tile DSL</td>
          <td>底层标准 Rust 语法</td>
      </tr>
      <tr>
          <td><strong>编译路径</strong></td>
          <td>Rust → CUDA Tile IR → cubin</td>
          <td>Rust → Rust MIR → LLVM IR → PTX</td>
      </tr>
      <tr>
          <td><strong>安全保证</strong></td>
          <td>编译器强制的 tile 分区 + 所有权</td>
          <td>&ldquo;safe-ish&rdquo;，部分检查</td>
      </tr>
      <tr>
          <td><strong>适用场景</strong></td>
          <td>tile-based 计算（GEMM、卷积等）</td>
          <td>通用 SIMT 内核</td>
      </tr>
      <tr>
          <td><strong>Stars</strong></td>
          <td>381</td>
          <td>2768</td>
      </tr>
  </tbody>
</table>
<p>cuda-oxide 更像是&quot;让 Rust 成为 CUDA C++ 的替代品&quot;，你写的代码更接近传统 CUDA 内核的风格，只是用了 Rust 语法。cuTile Rust 则是更高层的抽象，让你在 tile 层面思考，编译器帮你处理线程映射和内存安全。</p>
<p>两者不矛盾，更像是同一生态里的不同层次。对于 ML 工程师来说，cuTile Rust 的 tile 抽象更接近日常的 tensor 操作心智模型；对于系统程序员来说，cuda-oxide 的底层控制更灵活。</p>
<h2 id="rust-gpu-编程的全景">Rust GPU 编程的全景</h2>
<p>把视野拉远一点，2026 年的 Rust GPU 生态已经初具规模：</p>
<ul>
<li><strong><a href="https://github.com/Rust-GPU/Rust-GPU">Rust-GPU</a></strong>（Embark Studios，3169 stars）：把 Rust 编译成 SPIR-V，面向 Vulkan 生态</li>
<li><strong><a href="https://github.com/NVlabs/cuda-oxide">cuda-oxide</a></strong>（NVIDIA Labs，2768 stars）：Rust 直接编译 PTX</li>
<li><strong>cuTile Rust</strong>（NVIDIA Labs，381 stars）：tile-based 安全 GPU 编程</li>
<li><strong><a href="https://github.com/vosen/ZLUDA">ZLUDA</a></strong>（14288 stars）：让 CUDA 在 AMD GPU 上跑</li>
</ul>
<p>有意思的是，NVIDIA 自己在大力推 Rust GPU 方向，这在几年前是不可想象的。背后的原因可能和 AI 推理的工程需求有关——当你的推理引擎要处理越来越大的模型、越来越复杂的调度逻辑时，C++ 的内存安全问题就不再是&quot;偶发 bug&quot;而是&quot;系统性风险&quot;。更根本的问题是，<a href="https://blog.hypho.cn/posts/ai-chip-memory-wall-hbm-cost/">GPU 算力的瓶颈正在从计算转向显存</a>，这意味着推理内核的优化空间越来越依赖于精细的内存管理——而这恰恰是 Rust 类型系统最擅长的领域。</p>
<h2 id="我的判断">我的判断</h2>
<p>cuTile Rust 值得关注，但要分清楚&quot;值得关注&quot;和&quot;现在就该用&quot;的区别。</p>
<p><strong>值得关注的原因</strong>：</p>
<ol>
<li>这是 NVIDIA Labs 的研究项目，有论文支撑，不是草根实验</li>
<li>tile-based 抽象和 Rust 所有权的结合思路非常优雅</li>
<li>性能数据（92% cuBLAS，安全零开销）如果可复现，是真正的突破</li>
<li>Grout 证明了在推理场景的可行性</li>
</ol>
<p><strong>现在不急着用的原因</strong>：</p>
<ol>
<li>项目自己说了&quot;early stage, expect bugs and API breakage&quot;</li>
<li>需要 CUDA 13.2，目前主流环境还在 CUDA 12.x</li>
<li>生态还很小（381 stars，Grout 29 stars），遇到问题很难找到帮助</li>
<li>和现有 CUDA C++ 代码的互操作性还不明确</li>
</ol>
<p>对于正在做自定义推理内核优化的团队，建议持续跟踪但先不要迁移。对于研究 GPU 编程语言方向的人，这是必读的——论文 <em>Fearless Concurrency on the GPU</em>（arXiv: 2606.15991）写得很清晰，值得花一个下午细读。</p>
<p>如果你手头有 RTX 5090 或者能接触 B200，可以用 Grout 跑个 benchmark 看看实际表现。对于大多数 ML 巘程师来说，vLLM 和 SGLang 仍然是短期内的务实选择——但 Rust GPU 写推理内核这个方向，三到五年内可能会变得非常重要。</p>
<hr>
<p><strong>信源</strong></p>
<ul>
<li><a href="https://github.com/nvlabs/cutile-rs">cuTile Rust GitHub</a> — NVIDIA Labs，381 stars，Apache 2.0</li>
<li><a href="https://arxiv.org/abs/2606.15991">Fearless Concurrency on the GPU (arXiv: 2606.15991)</a> — cuTile Rust 论文</li>
<li><a href="https://github.com/huggingface/grout">Grout — Qwen3 Inference Engine</a> — HuggingFace，基于 cuTile Rust</li>
<li><a href="https://github.com/NVlabs/cuda-oxide">cuda-oxide</a> — NVIDIA Labs，Rust-to-PTX 编译器，2768 stars</li>
<li><a href="https://github.com/Rust-GPU/Rust-GPU">Rust-GPU</a> — Embark Studios，Rust-to-SPIR-V，3169 stars</li>
<li><a href="https://news.ycombinator.com/item?id=48561410">HN 讨论</a> — cuTile Rust Show HN</li>
</ul>
]]></content:encoded></item><item><title>1T 模型跑出 1000 tok/s：MiMo × TileRT 的模型-系统联合设计到底做了什么</title><link>https://blog.hypho.cn/posts/mimo-tilert-1000tps-trillion-parameter-inference/</link><pubDate>Wed, 10 Jun 2026 10:07:04 +0800</pubDate><guid>https://blog.hypho.cn/posts/mimo-tilert-1000tps-trillion-parameter-inference/</guid><description>小米 MiMo-V2.5-Pro 与 TileRT 合作，在 8 卡 GPU 节点上让 1T 参数 MoE 模型首次突破 1000 tokens/s 生成速度。本文拆解实现这一数字的三层技术栈：FP4 选择性量化、DFlash 块级投机解码、以及 TileRT 的 Tile-Based 持久执行引擎，并分析&amp;#34;模型-系统联合设计&amp;#34;这一新范式对推理基础设施的实际意义。</description><content:encoded><![CDATA[<p>一个万亿参数的模型，在 8 张消费级 GPU 上每秒吐出 1000 个 token——这件事本身并不新鲜，因为类似数字过去只在论文 demo 或特制硬件上见过。但小米 MiMo 团队和 TileRT 推出的 MiMo-V2.5-Pro-UltraSpeed，用的是商品化 GPU、开源推理框架、没有定制芯片。这就有意思了。</p>
<p>更关键的是，实现这个速度的路径不是&quot;把量化做狠一点&quot;或&quot;投机解码多猜几个 token&quot;这么简单。它触及了一个更根本的问题：<strong>当推理系统逼近硬件物理极限时，模型架构和推理引擎必须从设计阶段就开始同步进化，而不是各自优化完再拼到一起。</strong></p>
<p>这篇拆解 MiMo × TileRT 做了什么，以及&quot;Speed Scaling&quot;作为新范式到底意味着什么。</p>
<h2 id="万亿参数推理为什么特别难">万亿参数推理为什么特别难</h2>
<p>先说背景。MoE（Mixture of Experts）架构让万亿参数模型在训练端变得可行——每次前向传播只激活一小部分参数，推理时的计算量远低于密集模型。但推理端有一个不太一样的瓶颈：<strong>显存带宽</strong>。</p>
<p>一个 1T 参数的 MoE 模型，即使只激活几百亿参数，完整的权重还是得住在 GPU 显存里。用 FP16 加载需要 2TB 显存，8 张 80GB H100 只有 640GB，根本装不下。即使用 FP8（1TB），仍然超出单节点容量。</p>
<p>这意味着推理速度的瓶颈不在计算，而在<strong>数据搬运</strong>——每生成一个 token，GPU 都要从显存读取相关权重，读取速度直接决定生成速度。业界称之为&quot;Memory-Bound&quot;场景，token/s 的上限 = 显存带宽 / 每 token 需要读取的字节数。</p>
<p>所以，要让 1T 模型跑快，核心就两件事：<strong>减少每次搬运的数据量</strong>，和<strong>减少搬运次数</strong>。</p>
<h2 id="第一层fp4-选择性量化不是所有参数都值得用低精度">第一层：FP4 选择性量化——不是所有参数都值得用低精度</h2>
<p>减少数据量最直接的方法是量化。MiMo-V2.5-Pro 采用的是 OCP Microscaling (MXFP4) 格式——一种 <a href="https://arxiv.org/abs/2310.10537">Microsoft 主导的 FP4 标准</a>，在极低比特下保持数值稳定性。</p>
<p>但关键不是&quot;全模型 FP4&quot;。如果暴力把所有层都压到 4 bit，模型在复杂推理、代码生成等任务上会出现明显退化。MiMo 的做法是<strong>选择性量化</strong>：</p>
<ul>
<li><strong>MoE Expert 层</strong>：占总参数量的绝大部分，且对量化容忍度最高 → 用 FP4</li>
<li><strong>Router 和 Attention 层</strong>：参数量小但对精度敏感 → 保持 FP8</li>
</ul>
<p>用人话说就是：大部分&quot;搬运工&quot;（Expert）换成了轻装，但&quot;调度员&quot;（Router）和&quot;注意力核心&quot;保留重装。这不是一个拍脑袋的决定，而是 MiMo 团队和 TileRT 在 profiling 阶段反复测量每层的精度敏感度后得出的工程策略。</p>
<p>这种做法和我们之前拆解过的 <a href="https://blog.hypho.cn/posts/kvarn-vllm-kv-cache-quantization-production/">KVarN 用 KV Cache 量化减少推理显存</a> 有异曲同工之处——都是瞄准推理 pipeline 中的带宽瓶颈做定点优化。区别在于，KVarN 压缩的是 KV Cache 的存储，MiMo 压缩的是模型权重本身的搬运。</p>
<h2 id="第二层dflash不只是猜得快而是猜的形态变了">第二层：DFlash——不只是&quot;猜得快&quot;，而是&quot;猜的形态&quot;变了</h2>
<p>量化解决的是&quot;每次搬运多少&quot;的问题，投机解码解决的是&quot;搬运几次&quot;的问题。</p>
<p>传统投机解码（Speculative Decoding）的思路很直觉：用一个小模型快速&quot;猜&quot;若干后续 token，然后大模型一次性验证。如果猜对了，就省了好几轮自回归生成。问题在于，<strong>草稿本身仍然是自回归的</strong>——小模型每猜一个 token 也要一轮前向传播，瓶颈依然存在。</p>
<p>DFlash（来自 <a href="https://github.com/z-lab/dflash">z-lab 的 DFlash 项目</a>，GitHub 近 5000 星）的做法完全不同：它用<strong>块级掩码并行预测</strong>取代了自回归草稿。具体来说：</p>
<ol>
<li>选取一个 token 块（比如 8 个位置），把其中一部分位置 mask 掉</li>
<li>草稿模型<strong>一次性</strong>预测所有被 mask 的位置，不需要逐个生成</li>
<li>大模型验证整个块的正确性</li>
</ol>
<p>这种&quot;块扩散&quot;方式从根本上绕过了草稿阶段的串行约束。我们在 <a href="https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/">之前拆解 DFlash + DDTree 的文章</a> 中详细介绍过这个机制——当时是在消费级 RTX 3090 上跑 Qwen3.5-27B，做到了 207 tok/s。</p>
<p>MiMo × TileRT 把同一个思路搬到了万亿参数场景，并做了针对 MoE 架构的定制优化：</p>
<ul>
<li>使用 Muon 二阶优化器和模型自蒸馏来训练草稿头，确保在 FP4 权重下仍有高接受率</li>
<li>块大小限制在 8 个 token，控制单次验证的计算开销</li>
<li>在代码生成场景实测平均接受长度 6.30，最高 7.14——意味着每轮验证大概能&quot;一口气&quot;确认 6-7 个 token</li>
</ul>
<p>这个数字很重要。接受率太低（比如只有 3-4），投机解码的收益就被验证开销吃掉了。6+ 的接受长度意味着大模型每做一次前向传播，实际产出 6-7 个有效 token，等效地把推理速度翻了 5-6 倍。</p>
<h2 id="第三层tilert-的-tile-based-持久执行引擎">第三层：TileRT 的 Tile-Based 持久执行引擎</h2>
<p>如果说量化和投机解码是&quot;减少工作量&quot;，TileRT 做的是&quot;减少工作的间隙&quot;。</p>
<p>传统的推理框架（vLLM、TensorRT-LLM 等）把模型拆成大量独立算子，每个算子有独立的 kernel launch。在常规速度下（几十 tok/s），每次 launch 的开销（host 端调度、硬件同步、全局内存往返）可以被密集计算掩盖。但在 1000 tok/s 的频率下，每个算子的生命周期被压缩到微秒级，这些开销突然变成了主要瓶颈。</p>
<p>TileRT 的解决方案是一个全新执行模型——<strong>Persistent Engine</strong>：</p>
<ul>
<li>不再逐算子 launch，而是把整个计算管线打包成一个持续运行在 GPU 上的持久化引擎</li>
<li>当一个 Tile（数据块）在 Compute Core 上处理时，下一个 Tile 的数据已经通过多级内存层次（Global → Shared → Register）开始预取</li>
<li>引入 <strong>Warp Specialization</strong>：不同的 Warp 组被分配到不同角色（计算、数据搬运、通信），打破传统&quot;所有 Warp 做同一件事&quot;的刚性执行模式</li>
<li><strong>Heterogeneous Workers</strong> 将这种专业化策略扩展到多个 SM，实现跨 GPU 执行域的协调</li>
</ul>
<p>用人话翻译：传统推理引擎像一个流水线上每个工位都独立接单、独立交付的工厂；TileRT 把它变成了一个连续流动的传送带，每个环节的衔接间隙被压到了接近零。</p>
<p>这解释了为什么 TileRT 能从&quot;几百 tok/s&quot;跨越到&quot;1000+ tok/s&quot;——后者不是前者的线性延伸，而是需要一个质变的执行范式。</p>
<p><a href="https://github.com/tile-ai/TileRT">TileRT 本身是开源项目</a>（1277 星），已经在 GLM-5.1-highspeed 等生产环境中上线，不是纸上谈兵。</p>
<h2 id="三层叠加的工程细节">三层叠加的工程细节</h2>
<p>单独看每一层，都不算革命性创新——量化、投机解码、执行优化，业界都在做。MiMo × TileRT 的真正价值在于<strong>三层之间的协同设计</strong>：</p>
<table>
  <thead>
      <tr>
          <th>技术层</th>
          <th>独立效果</th>
          <th>协同设计的额外收益</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FP4 量化</td>
          <td>减少 50% 显存带宽</td>
          <td>DFlash 草稿模型可以更小（因为目标模型已经是 FP4），验证更快</td>
      </tr>
      <tr>
          <td>DFlash 投机解码</td>
          <td>等效 6-7x 吞吐提升</td>
          <td>TileRT 的 Persistent Engine 消除了验证阶段的算子间歇，验证效率最大化</td>
      </tr>
      <tr>
          <td>TileRT 执行优化</td>
          <td>消除微秒级算子开销</td>
          <td>量化后的权重体积更小，预取管线可以更激进地重叠 I/O 和计算</td>
      </tr>
  </tbody>
</table>
<p>这种&quot;模型-系统联合设计&quot;（Model-System Codesign）是文章中最值得记住的概念。传统流程是：模型团队训好模型 → 系统团队想办法部署 → 各自优化 → 拼到一起。MiMo × TileRT 的做法是：<strong>在模型设计阶段就引入推理系统团队的约束</strong>，让模型架构天然适合超低延迟执行。</p>
<h2 id="1000-toks-到底能做什么">1000 tok/s 到底能做什么</h2>
<p>速度数字本身不是目的。MiMo 的博客列了三个场景，我认为其中两个真正有工程价值：</p>
<p><strong>1. Best-of-N / Tree Search 推理</strong></p>
<p>在相同的时间预算内，1000 tok/s 让模型可以并行跑几十条推理路径，自动选出最优解。这比&quot;等一个答案，祈祷它正确&quot;要可靠得多。对于代码生成、数学证明等需要探索的任务，这意味着质量的实质性提升，而不只是更快的打字机。</p>
<p><strong>2. Coding Agent 的实时交互</strong></p>
<p>开发者用 AI 写代码时，最大的体验杀手是&quot;等&quot;。1000 tok/s 意味着大段代码生成可以在几秒内完成，Agent 可以在同一个交互回合中完成&quot;写代码 → 测试 → 修复&quot;的完整循环，而不是让开发者盯着 loading 动画发呆。</p>
<p>第三个场景是&quot;毫秒级实时决策&quot;（量化交易、反欺诈），坦白说我持保留态度——这些场景对模型输出质量的要求和对延迟的要求往往互相矛盾，1000 tok/s 解决了延迟但没解决可靠性问题。</p>
<h2 id="对工程选型的实际意义">对工程选型的实际意义</h2>
<p>如果你在做 AI 基础设施选型，这个发布有几个值得注意的点：</p>
<p><strong>TileRT 是一个实际可用的开源推理引擎</strong>，不是实验室 demo。它已经部署在 GLM-5.1 的生产环境中。如果你的场景对延迟极度敏感（实时 Agent、交互式编码），值得评估。相比 <a href="https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/">本地推理引擎 Ollama/llama.cpp</a> 的定位是消费级硬件上的便捷部署，TileRT 的定位是数据中心级的极致延迟。</p>
<p><strong>DFlash 的块级预测方式</strong>正在成为推理加速的主流路径。4999 星不是没有原因的——它比传统投机解码更适合大模型、长序列场景。如果你用 vLLM 或 TensorRT-LLM，关注这两个框架对 DFlash 的集成进度。</p>
<p><strong>FP4 量化正在从&quot;勉强可用&quot;变成&quot;生产级&quot;</strong>。MXFP4 标准（<a href="https://github.com/microsoft/microxcaling">Microsoft 主导的 Microscaling 格式</a>）在极低比特下的数值稳定性已经被多个团队验证。但注意，MiMo 的成功依赖于 MoE 架构的特殊性——Expert 层天然对量化友好。如果你的模型是密集架构，全模型 FP4 的效果可能不如预期。</p>
<h2 id="一句话总结">一句话总结</h2>
<p>1000 tok/s 不是一个&quot;量化做得更狠&quot;的结果，而是模型架构和推理系统从设计阶段就深度耦合的产物。当推理速度开始像训练算力一样成为决定模型能力边界的变量时，&ldquo;Speed Scaling&quot;这个概念值得每个做 AI 基础设施的人认真对待。</p>
<hr>
<p><strong>信源</strong>：</p>
<ul>
<li><a href="https://mimo.xiaomi.com/blog/mimo-tilert-1000tps">MiMo × TileRT 官方博客</a></li>
<li><a href="https://www.tilert.ai/blog/breaking-1000-tps.html">TileRT 技术博客：Breaking 1000 TPS</a></li>
<li><a href="https://github.com/tile-ai/TileRT">TileRT GitHub（1277 星）</a></li>
<li><a href="https://github.com/z-lab/dflash">DFlash GitHub（4999 星）</a></li>
<li><a href="https://platform.xiaomimimo.com/docs/en-US/model-intro/mimo-v2.5-pro-ultraspeed">MiMo-V2.5-Pro-UltraSpeed 模型文档</a></li>
<li><a href="https://arxiv.org/abs/2310.10537">MXFP4 Microscaling Formats 规格</a></li>
</ul>
]]></content:encoded></item><item><title>KV-cache 量化终于能跑生产了？KVarN 用方差归一化打破 vLLM 的吞吐量魔咒</title><link>https://blog.hypho.cn/posts/kvarn-vllm-kv-cache-quantization-production/</link><pubDate>Fri, 05 Jun 2026 10:04:37 +0800</pubDate><guid>https://blog.hypho.cn/posts/kvarn-vllm-kv-cache-quantization-production/</guid><description>vLLM 官方基准显示 TurboQuant 等 KV-cache 量化方案普遍损失 40-52% 吞吐量，华为 KVarN 通过 Hadamard 旋转和方差归一化实现了 FP16 级精度、FP16 级吞吐和 3-5 倍缓存容量三者兼得。本文解析 KVarN 的工程原理、与 TurboQuant/FP8 的实测对比，以及在 vLLM 生产环境中一行配置启用的实践路径。</description><content:encoded><![CDATA[<ul>
<li><a href="https://blog.hypho.cn/posts/ai-chip-memory-wall-hbm-cost/">AI 芯片为什么越来越像内存生意？从 HBM 成本看 LLM 推理的真正瓶颈</a></li>
<li><a href="https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/">Gemma 4 的多 token 预测：LLM 推理加速不该只盯着量化</a></li>
</ul>
<h2 id="kv-cache-量化为什么一直不敢开">KV-cache 量化为什么一直&quot;不敢开&quot;</h2>
<p>做过 vLLM 生产部署的人大概都纠结过一个问题：context 越来越长，KV-cache 吃掉的 GPU 显存越来越多，但官方文档里那个 <code>--kv-cache-dtype</code> 参数，你真的敢在生产环境打开吗？</p>
<p>vLLM 团队今年 5 月发了一篇 TurboQuant 的系统性基准测试<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>，结论相当诚实：除了 FP8 之外，所有 KV-cache 量化方案都在&quot;拿吞吐量换容量&quot;。具体来说：</p>
<ul>
<li><strong>TurboQuant 4bit-nc</strong>：最高 3.4 倍 KV-cache 容量，但吞吐量损失 40-52%，延迟增加最高 60%</li>
<li><strong>TurboQuant 3bit-nc</strong>：精度大幅下降，推理和长上下文任务表现尤其差</li>
<li><strong>FP8</strong>：2 倍容量，吞吐量基本无损，但容量增幅有限</li>
</ul>
<p>说白了就是：你要么选 FP8（安全但只翻倍），要么选更激进的量化（容量大但吞吐暴跌）。在推理密集型场景——比如长上下文 Agent、代码生成、数学推理——吞吐量下降意味着请求排队变长、用户等待变久，这在生产环境是不可接受的。</p>
<p>所以 vLLM 官方的建议一直是：<strong>默认用 BF16，显存不够就用 FP8，其他量化方案慎用。</strong></p>
<p>这就是 KVarN 想解决的问题。</p>
<h2 id="kvarn-是什么华为的-kv-cache-量化新方案">KVarN 是什么：华为的 KV-cache 量化新方案</h2>
<p>KVarN（读作 /kvɑːɳ/，瑞典语&quot;研磨机&quot;的意思）来自华为通讯系统实验室（Huawei CSL），论文在 arXiv 上<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>，代码以 Apache 2.0 开源在 GitHub<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>，目前 196 星，最新提交就在今天。</p>
<p>它的核心卖点用一句话概括：<strong>FP16 级精度、FP16 级吞吐、3-5 倍 KV-cache 容量，不需要校准数据。</strong></p>
<p>在 Qwen3-32B 的 AIME25 基准测试中（16K context，TP=2），KVarN 的精度和吞吐量都<strong>匹配甚至超过 FP16</strong>，同时提供约 4 倍的 KV-cache 容量。这在之前的量化方案中从未同时实现过。</p>
<h2 id="它怎么做到的四步流水线">它怎么做到的：四步流水线</h2>
<p>KVarN 的量化流程分四个阶段，每一步都有明确的工程目的：</p>
<p><strong>第一步：Cache</strong> — 原始 FP16 KV-cache 瓦片（channels × tokens），直接来自注意力计算。</p>
<p><strong>第二步：Hadamard 旋转</strong> — 沿通道维度做 Hadamard 变换。这一步的直觉是：原始 KV-cache 中某些通道有极端值（outlier），直接量化会丢失大量信息。Hadamard 旋转是正交变换，不改变注意力分数，但会把极端值&quot;摊开&quot;到所有通道，让量化更容易。</p>
<p><strong>第三步：方差归一化</strong> — 交替沿行和列做标准差归一化（类似 Sinkhorn 迭代），在对数空间中操作。这一步让瓦片内部的方差均匀分布，进一步减少量化误差。</p>
<p><strong>第四步：非对称舍入量化</strong> — 在低比特宽度下做 round-to-nearest，读取时还原 scale。关键设计是<strong>给 key 分配更多比特，给 value 分配更少</strong>（默认配置 <code>kvarn_k4v2_g128</code>：key 4-bit，value 2-bit）。</p>
<p>用人话说就是：先把数据&quot;打散&quot;（旋转），再&quot;抹平&quot;（归一化），最后才&quot;压缩&quot;（量化）。传统量化方法直接在原始数据上压，极端值会让误差爆炸；KVarN 的前两步就是在为量化创造更好的条件。</p>
<h2 id="论文的核心发现推理场景的误差累积">论文的核心发现：推理场景的误差累积</h2>
<p>论文<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>指出了一个之前被忽视的问题：<strong>现有的 KV-cache 量化方法主要在 prefill 类场景中评测，但推理（autoregressive decoding）场景下，量化误差会跨时间步累积。</strong></p>
<p>具体来说，在长序列生成过程中，每一步解码都会读取之前所有 token 的 KV-cache。如果某个 token 的 scale 估错了，这个误差会随着解码的推进不断放大。论文发现，驱动误差累积的主要因素是<strong>不正确的 token scale</strong>。</p>
<p>KVarN 的方差归一化正是针对这个问题：通过对 KV 矩阵的行和列做联合归一化，直接消除不均匀的 token scale，从而大幅减少误差累积。</p>
<p>在 MATH500、AIME24 和 HumanEval 等生成式基准上，KVarN 在 2-bit 精度下达到了新的 state-of-the-art。</p>
<h2 id="与-turboquant-和-fp8-的实测对比">与 TurboQuant 和 FP8 的实测对比</h2>
<p>根据 KVarN 的 README<sup id="fnref1:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> 和 vLLM TurboQuant 博客<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>的数据：</p>
<table>
  <thead>
      <tr>
          <th>方案</th>
          <th>容量倍数</th>
          <th>吞吐量（相对 FP16）</th>
          <th>精度</th>
          <th>校准需求</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FP8</td>
          <td>2×</td>
          <td>≈100%</td>
          <td>接近 FP16</td>
          <td>无</td>
      </tr>
      <tr>
          <td>TurboQuant 4bit-nc</td>
          <td>2.3-3.7×</td>
          <td>48-60%</td>
          <td>降 1-4 分</td>
          <td>无</td>
      </tr>
      <tr>
          <td>TurboQuant 3bit-nc</td>
          <td>3-5×</td>
          <td>更低</td>
          <td>明显下降</td>
          <td>无</td>
      </tr>
      <tr>
          <td><strong>KVarN k4v2_g128</strong></td>
          <td><strong>3-5×</strong></td>
          <td><strong>≥100%</strong></td>
          <td><strong>匹配 FP16</strong></td>
          <td><strong>无</strong></td>
      </tr>
  </tbody>
</table>
<p>KVarN 的 Pareto 前沿占据了 TurboQuant 和 FP8 都够不到的位置：<strong>右上角</strong>——既比 FP8 容量大，又比 TurboQuant 吞吐高，精度还不打折。</p>
<p>vLLM 官方 TurboQuant 博客的结论是&quot;FP8 是目前最安全的默认选择&quot;。但如果 KVarN 的数据经得起更广泛验证，这个结论可能需要更新。</p>
<h2 id="工程实践一行配置启用">工程实践：一行配置启用</h2>
<p>KVarN 的部署极其简单——它是 vLLM v0.22.0 的 fork，安装方式和 vLLM 一样：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/huawei-csl/KVarN.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> KVarN
</span></span><span class="line"><span class="cl"><span class="nv">VLLM_USE_PRECOMPILED</span><span class="o">=</span><span class="m">1</span> pip install -e .
</span></span></code></pre></div><p>使用时只需要加一个参数：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">vllm</span> <span class="kn">import</span> <span class="n">LLM</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">llm</span> <span class="o">=</span> <span class="n">LLM</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;Qwen/Qwen3-32B&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">dtype</span><span class="o">=</span><span class="s2">&#34;float16&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">kv_cache_dtype</span><span class="o">=</span><span class="s2">&#34;kvarn_k4v2_g128&#34;</span><span class="p">,</span>  <span class="c1"># ← 就这一行</span>
</span></span><span class="line"><span class="cl">    <span class="n">block_size</span><span class="o">=</span><span class="mi">128</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></div><p>Serving 模式同理：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">vllm serve Qwen/Qwen3-32B --dtype float16 --kv-cache-dtype kvarn_k4v2_g128 --block-size <span class="m">128</span>
</span></span></code></pre></div><p>没有模型改动，没有校准数据集，没有额外配置。KVarN 的 kernel 是 Triton 实现的，运行时 JIT 编译。</p>
<p>有一个需要注意的点：在单卡显存紧张的情况下，vLLM 的 CUDA graph 内存分析器可能会过度预留显存，导致 KV-cache 池缩小。可以通过设置 <code>VLLM_MEMORY_PROFILER_ESTIMATE_CUDAGRAPHS=0</code> 或提高 <code>--gpu-memory-utilization</code> 来恢复完整容量。</p>
<h2 id="需要关注的几个问题">需要关注的几个问题</h2>
<p><strong>1. 为什么是 fork 而不是 PR？</strong></p>
<p>HN 评论区<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>第一条就问了这个问题。KVarN 选择 fork vLLM 而不是提交 PR 到上游，可能是因为它的 kernel 实现需要修改 vLLM 的注意力后端接口。短期内 fork 意味着你需要自己同步 vLLM 的更新，长期能否合并回上游还有待观察。</p>
<p><strong>2. 196 星，能用在生产吗？</strong></p>
<p>项目很新（论文和代码都是 2026 年 6 月），社区验证还在早期阶段。如果你的场景对精度极其敏感（比如金融计算），建议先在测试环境跑自己的基准。但如果你只是想在有限显存下跑更长的 context——比如 32K 甚至 128K 的 Agent 场景——KVarN 的风险收益比相当不错。</p>
<p><strong>3. 目前只支持 128 的 block size</strong></p>
<p>README 说其他 page size &ldquo;coming soon&rdquo;。在那之前，你需要确保 <code>block_size=128</code> 与你的工作负载兼容。</p>
<p><strong>4. 对硬件的要求</strong></p>
<p>KVarN 的 kernel 基于 Triton，理论上支持所有能跑 vLLM 的 GPU。但实际性能可能因硬件而异，A100/H100 上的表现和消费级卡上可能不同。</p>
<h2 id="我的判断">我的判断</h2>
<p>KV-cache 量化是 LLM 推理优化中被低估的一个方向。大家的注意力大多在模型量化（GPTQ、AWQ）、投机解码、架构创新上，但对长上下文场景来说，KV-cache 才是真正的显存瓶颈。</p>
<p>KVarN 的工程价值在于它<strong>打破了&quot;容量 vs 吞吐&quot;的二选一困境</strong>，而且实现方式极其轻量——不需要校准数据，不需要改模型，一行配置搞定。如果后续社区验证它在更多模型和场景上的一致性，它很可能成为 vLLM 长上下文部署的标配。</p>
<p>对于正在用 vLLM 做生产部署的团队，我的建议是：</p>
<ol>
<li><strong>短上下文、显存充裕</strong>：继续用 BF16，不用折腾</li>
<li><strong>中等上下文、显存紧张</strong>：FP8 是安全选择，2 倍容量，无损吞吐</li>
<li><strong>长上下文 Agent / 推理密集型</strong>：关注 KVarN，它可能给你 4 倍容量的同时不牺牲吞吐</li>
<li><strong>想尝鲜</strong>：在测试环境部署 KVarN，跑你自己的业务 benchmark，对比 FP16 和 FP8</li>
</ol>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://vllm.ai/blog/2026-05-11-turboquant">A First Comprehensive Study of TurboQuant: Accuracy and Performance | vLLM Blog</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://arxiv.org/abs/2606.03458">KVarN: Variance-Normalized KV-Cache Quantization Mitigates Error Accumulation in Reasoning Tasks (arXiv:2606.03458)</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://github.com/huawei-csl/KVarN">huawei-csl/KVarN — GitHub</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://news.ycombinator.com/item?id=48399974">HN Discussion: KVarN — 114 points</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>1-bit 图像生成不再是玄学：PrismML Bonsai Image 如何让 Diffusion 模型跑在 iPhone 上</title><link>https://blog.hypho.cn/posts/bonsai-image-1bit-edge-image-generation/</link><pubDate>Mon, 01 Jun 2026 12:23:14 +0800</pubDate><guid>https://blog.hypho.cn/posts/bonsai-image-1bit-edge-image-generation/</guid><description>PrismML 将 1-bit 量化从文本模型扩展到图像生成，发布 Bonsai Image 4B，基于 FLUX.2 架构，实现 8× 模型压缩和 5.6× 推理加速，首次让 Diffusion Transformer 在 iPhone 上本地运行。本文解析其技术原理、社区基准测试、实际部署流程，以及 1-bit 量化在边缘 AI 推理中的工程价值。</description><content:encoded><![CDATA[<p>前几天看到 PrismML 发布了 Bonsai Image 4B，声称可以在 iPhone 上本地跑图像生成，我的第一反应是&quot;又一个宣传噱头&quot;。毕竟图像生成模型动辄几个 GB，Diffusion Transformer 的计算量比文本 LLM 大得多，怎么压缩到手机能跑？</p>
<p>但仔细看了他们的技术方案和社区基准之后，我改了主意。这不是简单的模型量化，而是从训练阶段就用 1-bit 权重做端到端训练——换句话说，模型天生就是&quot;压缩态&quot;的，不是训好之后再硬压。</p>
<p>这和我们之前讨论过的<a href="https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/">推理优化路线</a>完全不同。量化只是推理阶段的事，但 PrismML 的思路是：<strong>让模型在训练时就接受 1-bit 的约束</strong>，这样精度损失是渐进的，而不是事后的暴力截断。</p>
<h2 id="从-bonsai-8b-到-bonsai-image一条技术路线的延伸">从 Bonsai-8B 到 Bonsai Image：一条技术路线的延伸</h2>
<p>PrismML 这家公司来头不小——脱胎于 Caltech 研究，拿了 Khosla Ventures、Cerberus 和 Google 的投资。他们今年 3 月发布的 Bonsai-8B 是全球第一个&quot;商业可行的 1-bit LLM&quot;，整数权重只有 {-1, 0, +1} 三种取值。</p>
<p>用人话说就是：传统模型的每个权重参数是一个 16 位浮点数，占 2 字节。Bonsai 的每个权重只占 1 bit（甚至 ternary 版本约 1.58 bit）。一个 8B 参数模型，FP16 版本要 16 GB 内存，Bonsai-8B 只要 <strong>1.15 GB</strong>。</p>
<p>这个压缩比有多大？14 倍。在 RTX 4090 上推理速度提升 6.2 倍，能耗降低 4-5 倍。这就是为什么他们敢说&quot;可以在手机上跑&quot;——不是噱头，是真的把模型缩小到了手机内存能装下的程度。</p>
<p>Bonsai Image 4B 延续了同样的技术路线，但对象从文本生成换成了图像生成。基座模型是 Black Forest Labs 的 FLUX.2-klein-4B（一个 4B 参数的 Diffusion Transformer），PrismML 在此基础上做了 1-bit 和 ternary 两种量化版本。</p>
<h2 id="具体怎么做的">具体怎么做的？</h2>
<p>Bonsai Image 提供两个量化变体：</p>
<ul>
<li><strong>Binary (1-bit)</strong>：权重严格为 {-1, +1}，模型最小，适合内存极度受限的设备</li>
<li><strong>Ternary (1.58-bit)</strong>：权重为 {-1, 0, +1}，质量更好，是推荐版本</li>
</ul>
<p>在推理层面，PrismML 没有依赖 llama.cpp 或任何 C/C++ 运行时，而是用了两条技术栈：</p>
<ul>
<li><strong>Apple Silicon</strong>：通过 <a href="https://github.com/ml-explore/mlx">MLX</a> 框架原生运行，利用 mlx-2bit 格式</li>
<li><strong>NVIDIA GPU</strong>：通过 <a href="https://github.com/mobiusml/gemlite">gemlite</a> + <a href="https://github.com/dropbox/hqq">HQQ</a> 的低比特 GEMM 内核</li>
</ul>
<p>一个有意思的社区项目是 <a href="https://github.com/cool-japan/oxibonsai">OxiBonsai</a>——一个纯 Rust 实现的推理引擎，完全不依赖 C/C++ 运行时。它支持 CPU（SIMD）、Apple Silicon（Metal）和 NVIDIA（CUDA），已经有 156k 行 Rust 代码，4553 个测试通过。这说明 1-bit 推理引擎已经不是实验室玩具，开始有社区在认真做工程化了。</p>
<h2 id="社区基准和-qwen35-正面对比">社区基准：和 Qwen3.5 正面对比</h2>
<p>最有说服力的数据来自社区基准测试——<a href="https://github.com/ArmanJR/PrismML-Bonsai-vs-Qwen3.5-Benchmark">PrismML-Bonsai-vs-Qwen3.5-Benchmark</a> 在 NVIDIA Jetson Orin 上跑了一系列对比，覆盖 98 个问题、7 个类别（通用知识、数学、编程、历史、逻辑推理、语言理解、波斯语）。</p>
<p>关键数据：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>参数</th>
          <th>量化</th>
          <th>准确率</th>
          <th>生成速度 (tok/s)</th>
          <th>模型大小</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Qwen3.5-27B</td>
          <td>26.9B</td>
          <td>Q4_K_M</td>
          <td><strong>95.7%</strong></td>
          <td>9.5</td>
          <td>15.6 GiB</td>
      </tr>
      <tr>
          <td>Qwen3.5-9B</td>
          <td>8.95B</td>
          <td>Q4_K_M</td>
          <td>90.2%</td>
          <td>27.0</td>
          <td>5.3 GiB</td>
      </tr>
      <tr>
          <td>Qwen3.5-4B</td>
          <td>4.21B</td>
          <td>Q4_K_M</td>
          <td>85.2%</td>
          <td>36.7</td>
          <td>2.6 GiB</td>
      </tr>
      <tr>
          <td>Ternary-Bonsai-8B</td>
          <td>8.19B</td>
          <td>mlx-2bit</td>
          <td>85.0%</td>
          <td>15.0</td>
          <td>2.1 GiB</td>
      </tr>
      <tr>
          <td>Ternary-Bonsai-4B</td>
          <td>4.02B</td>
          <td>mlx-2bit</td>
          <td>83.0%</td>
          <td>23.9</td>
          <td>1.1 GiB</td>
      </tr>
      <tr>
          <td>Bonsai-8B</td>
          <td>8.19B</td>
          <td>Q1_0</td>
          <td>78.9%</td>
          <td><strong>46.5</strong></td>
          <td><strong>1.1 GiB</strong></td>
      </tr>
  </tbody>
</table>
<p>注意最后两行。Ternary-Bonsai-8B 只有 2.1 GiB，准确率和 2.6 GiB 的 Qwen3.5-4B 基本持平（85.0% vs 85.2%）。而 Bonsai-8B 的 Q1_0 格式只有 1.1 GiB，生成速度达到 46.5 tok/s，是所有 8B 级模型里最快的。</p>
<p>换一个角度看&quot;效率密度&quot;——准确率除以模型大小：</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>准确率/GiB</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Ternary-Bonsai-1.7B</td>
          <td><strong>1.44</strong></td>
      </tr>
      <tr>
          <td>Qwen3.5-0.8B</td>
          <td>1.13</td>
      </tr>
      <tr>
          <td>Ternary-Bonsai-4B</td>
          <td>0.79</td>
      </tr>
      <tr>
          <td>Bonsai-8B</td>
          <td>0.72</td>
      </tr>
      <tr>
          <td>Qwen3.5-4B</td>
          <td>0.55</td>
      </tr>
      <tr>
          <td>Qwen3.5-9B</td>
          <td>0.43</td>
      </tr>
  </tbody>
</table>
<p>Ternary-Bonsai-1.7B 只有 462 MiB，但效率密度是所有模型里最高的。这就是 1-bit 量化的核心价值：<strong>在有限硬件上挤出最多的智能</strong>。</p>
<p>说白了就是——Bonsai 不是在和 27B 模型比绝对性能，而是在&quot;每 GB 内存能买到多少智能&quot;这个维度上碾压。</p>
<h2 id="图像生成的特殊挑战">图像生成的特殊挑战</h2>
<p>文本模型压缩到 1-bit 已经很了不起了，但图像生成是另一回事。</p>
<p>Diffusion Transformer 要做的工作远比文本 LLM 复杂：它需要在多个去噪步骤中逐步从噪声中&quot;雕琢&quot;出图像，每一步都涉及大量的矩阵运算。传统图像生成模型（如 SDXL 3.5B 参数）需要 GPU 加速才能勉强运行，手机上基本是奢望。</p>
<p>Bonsai Image 4B 的关键创新是把 1-bit 量化应用到了 Diffusion Transformer 的<strong>全部层</strong>——不只是 MLP，还包括注意力投影层。这使得 Diffusion Transformer 的体积缩小了最高 8 倍，推理速度提升最高 5.6 倍。</p>
<p>HN 评论里有人指出一个值得注意的细节：Bonsai Image 的文本编码器仍然是 4-bit 量化的，不是 1-bit。这意味着整个管线并不是纯 1-bit——文本理解部分还是用的传统量化方式，只有图像生成的 Diffusion Transformer 部分是 1-bit。这其实很合理：文本编码器的参数量相对较小，压缩它带来的收益有限，但对理解质量影响很大。</p>
<p>也有人质疑&quot;第一个在 iPhone 上跑的图像模型&quot;的说法——SDXL 3.5B 参数，理论上也能在 iPhone 13 Pro 上跑。但 PrismML 的意思是 Bonsai Image 是第一个专门为移动端优化的 1-bit 图像生成模型，而不是简单地把桌面模型硬塞进手机。</p>
<h2 id="怎么跑起来">怎么跑起来？</h2>
<p>PrismML 提供了相当友好的部署流程。在 macOS 上：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/PrismML-Eng/Bonsai-Image-Demo
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> Bonsai-Image-Demo
</span></span><span class="line"><span class="cl">./setup.sh
</span></span><span class="line"><span class="cl">./scripts/generate.sh --prompt <span class="s2">&#34;An icy Bonsai tree in a rainy forest&#34;</span>
</span></span></code></pre></div><p><code>setup.sh</code> 会自动检测平台，macOS 走 MLX 路径，Linux 走 gemlite/HQQ 路径。Windows 也有 PowerShell 脚本支持，不需要 WSL2。</p>
<p>更轻量的体验方式是直接用 <a href="https://huggingface.co/spaces/prism-ml/Bonsai-image-demo">HuggingFace Space</a> 或 <a href="https://colab.research.google.com/github/PrismML-Eng/Bonsai-image-demo/blob/main/notebooks/bonsai_image_colab.ipynb">Google Colab</a>。</p>
<h2 id="这对边缘-ai-意味着什么">这对边缘 AI 意味着什么？</h2>
<p>我们之前讨论过 <a href="https://blog.hypho.cn/posts/ai-chip-memory-wall-hbm-cost/">AI 芯片的内存瓶颈</a>——HBM 的成本越来越高，数据中心的能耗压力越来越大。1-bit 量化提供了一条完全不同的思路：与其堆更多更快的内存，不如把模型本身压缩到极致。</p>
<p>这对几个场景有直接意义：</p>
<p><strong>端侧推理</strong>：手机、树莓派、Jetson 这类设备内存有限，1-bit 模型可以把原本需要云端的推理任务拉到本地。图像生成只是开始，视频生成、3D 生成都有可能。</p>
<p><strong>隐私敏感场景</strong>：本地推理意味着数据不出设备。这对医疗影像、安防监控等场景有天然吸引力。</p>
<p><strong>成本控制</strong>：我们之前分析过 <a href="https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/">本地 LLM 推理的成本优势</a>，1-bit 量化把这个优势放大了一个数量级。</p>
<p>当然，1-bit 量化也有明显的局限。社区基准已经表明，Bonsai-8B 在绝对准确率上和 Qwen3.5-27B 差了将近 17 个百分点。压缩是有代价的——复杂推理、长上下文理解、边缘案例处理，这些任务对权重精度的要求更高，1-bit 模型在这些场景下会明显吃力。</p>
<p>对图像生成来说，质量损失可能更直观。你压缩文本模型，输出可能只是措辞不够精准；但压缩图像模型，可能直接出现视觉伪影、细节丢失、风格偏移。PrismML 的白皮书声称&quot;保持了强视觉质量&quot;，但 HN 评论里也有人反馈 WebGL demo 在手机上崩溃、iOS-only 的 demo 限制了受众。</p>
<h2 id="工程判断">工程判断</h2>
<p>如果你在做边缘 AI 部署，我的建议是：</p>
<ol>
<li>
<p><strong>Ternary-Bonsai 是首选</strong>。1.58-bit 的 ternary 版本在质量-大小平衡上明显优于纯 1-bit binary 版本。多出来的 0.58 bit 换来的准确率提升非常可观。</p>
</li>
<li>
<p><strong>不要指望替代云端大模型</strong>。Bonsai 的定位是&quot;在有限硬件上提供可用的智能&quot;，而不是和 GPT-4 或 Flux Pro 比绝对质量。用对场景很关键。</p>
</li>
<li>
<p><strong>关注 OxiBonsai 这样的社区项目</strong>。纯 Rust 推理引擎意味着更好的跨平台一致性和更少的 C/C++ 依赖问题。如果 PrismML 的官方工具链不能满足你的需求，OxiBonsai 值得一试。</p>
</li>
<li>
<p><strong>图像生成目前还处于早期</strong>。Bonsai Image 4B 刚发布，社区工具链（ComfyUI 集成、Ollama 支持等）还在路上。生产环境部署建议等社区验证一轮再上。</p>
</li>
</ol>
<p>1-bit 量化从文本扩展到图像，这不是一个孤立事件。它代表的是 AI 推理从&quot;堆算力&quot;到&quot;极致压缩&quot;的范式转移。在 AI 芯片越来越贵、能耗越来越高的今天，这条路线的工程价值只会越来越大。</p>
]]></content:encoded></item><item><title>AI 芯片为什么越来越像内存生意？从 HBM 成本看 LLM 推理的真正瓶颈</title><link>https://blog.hypho.cn/posts/ai-chip-memory-wall-hbm-cost/</link><pubDate>Mon, 25 May 2026 10:03:25 +0800</pubDate><guid>https://blog.hypho.cn/posts/ai-chip-memory-wall-hbm-cost/</guid><description>Epoch AI 的最新拆解显示，HBM 已占 AI 芯片组件成本约 63%。本文从 memory wall、KV cache、batch size 和推理吞吐角度分析：为什么 LLM 部署不能只盯算力，企业在选 GPU、做 RAG 与本地推理时应该怎样理解显存容量、带宽和成本的真实取舍。</description><content:encoded><![CDATA[<p>如果你还在用“这张卡有多少 TFLOPS”来判断一套 LLM 推理系统值不值得买，我建议先停一下。</p>
<p>这不是说算力不重要。训练大模型、跑高吞吐推理，当然离不开矩阵乘法能力。但最近 Hacker News 上一篇 <a href="https://epoch.ai/data-insights/ai-chip-component-cost-shares">Epoch AI 的芯片成本拆解</a>很值得看：他们估算，在 Nvidia、AMD、Google、Amazon 等 AI 芯片的组件成本里，高带宽内存 HBM 的占比已经从 2024 年一季度的 52% 上升到 2025 年四季度的 63%。</p>
<p>也就是说，今天一颗 AI 加速器越来越不像“纯算力商品”，反而更像一块被昂贵内存包围的计算核心。</p>
<p>这个变化对做应用的人也有直接影响。你在云上选 H100/H200，或者在本地纠结 4090、Mac Studio、工作站多卡，并不是在买一个抽象的“AI 能力”。你买的是：模型权重能不能放下，KV cache 能不能撑住上下文，batch size 能不能拉起来，以及 token 流水线会不会被内存带宽卡死。</p>
<p>说白了，LLM 推理的很多瓶颈，最后都会变成内存问题。</p>
<h2 id="hbm-成本占比上升说明了什么">HBM 成本占比上升，说明了什么？</h2>
<p>Epoch AI 这篇文章的核心数字很简单：HBM 在 AI 芯片组件成本中的占比，从 52% 增长到 63%；同时 logic dies 大约维持在 13%，先进封装和其他辅助组件占比下降。这个结论不是单一芯片报价，而是按生产量加权估算出来的行业平均值。</p>
<p>我不建议把这个数字理解成“GPU 厂商利润被内存厂吃掉了”这么简单。更有用的读法是：产业链正在用真金白银投票，承认 AI 工作负载对内存系统的饥渴程度越来越高。</p>
<p>为什么？因为 LLM 不是只做一次矩阵乘法就结束。</p>
<p>模型推理至少有两类阶段：prefill 和 decode。prefill 阶段要把提示词一次性喂进去，计算密度相对高；decode 阶段则是一个 token 一个 token 往外吐，每一步都要读模型权重，还要读写不断增长的 KV cache。上下文越长、并发越高，显存容量和带宽压力越明显。</p>
<p>这也是为什么 NVIDIA 在介绍 <a href="https://www.nvidia.com/en-us/data-center/h200/">H200</a> 时，重点强调的不是又多了多少理论算力，而是 141GB HBM3e、4.8TB/s 内存带宽，以及相比 H100 更大的容量和更高带宽。Micron 的 <a href="https://www.micron.com/products/memory/hbm/hbm3e">HBM3E 页面</a>也把“高容量、高带宽、低功耗”直接绑定到生成式 AI 和超算场景。</p>
<p>厂商宣传当然有营销成分，但方向没错：大模型时代，内存系统正在从配角变成主角。</p>
<h2 id="memory-wall不是论文里的抽象词">“Memory Wall”不是论文里的抽象词</h2>
<p>如果你想找一个更学术的背景，可以看 2024 年 arXiv 上的 <a href="https://arxiv.org/abs/2403.14123">AI and Memory Wall</a>。论文里有个很直观的判断：过去二十年，服务器峰值 FLOPS 的增长速度明显快过 DRAM 和互连带宽，结果就是很多 AI 应用，尤其是 serving，瓶颈越来越偏向内存而不是计算。</p>
<p>人话翻译：芯片算得越来越快，但数据喂不进去。</p>
<p>在传统后端系统里，我们很熟悉这种问题。数据库查询慢，不一定是 CPU 不够，可能是随机 IO、缓存命中率、网络往返。LLM 推理其实也类似，只是“数据库”换成了模型权重和 KV cache，“索引命中”换成了批处理、attention 优化和显存布局。</p>
<p>这也是我不太喜欢只用 tokens/s 讨论推理引擎的原因。tokens/s 是结果，不是原因。你要追问它是在什么上下文长度、什么 batch size、什么量化精度、什么显存占用、什么并发模型下测出来的。否则两个数字放在一起，很容易变成跑分游戏。</p>
<p>Hypho Blog 之前写过 <a href="https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/">Gemma 4 多 token 预测</a>，里面提到 speculative decoding 和多 token 预测的价值，本质上就是减少昂贵大模型调用次数，让一部分 token 由更便宜的草稿路径先猜。它看起来是“算法加速”，但落到系统层面，仍然是在缓解 decode 阶段对内存访问和调度的压力。</p>
<p>同样，<a href="https://blog.hypho.cn/posts/local-llm-inference-engine-ollama-llama-cpp/">本地 LLM 推理引擎之争</a>里讨论 llama.cpp、Ollama 这些工具时，真正该看的也不是谁的命令行更漂亮，而是谁能更稳定地利用硬件内存层级：量化格式、KV cache 策略、Metal/CUDA 后端、batch 调度，都会直接影响可用性。</p>
<h2 id="对工程选型的第一个影响显存容量不是越大越好而是决定边界">对工程选型的第一个影响：显存容量不是“越大越好”，而是决定边界</h2>
<p>很多团队买 GPU 时会问：“这张卡能不能跑 70B？”</p>
<p>这个问题不够精确。更好的问法是：</p>
<ul>
<li>用什么精度跑？FP16、INT8、4-bit，还是更激进的 2-bit/3-bit？</li>
<li>目标上下文长度是多少？8K、32K、128K，还是 1M？</li>
<li>是单用户交互，还是几十路并发？</li>
<li>是否需要工具调用、RAG、长文档、多轮对话保留上下文？</li>
<li>失败时是慢一点可以接受，还是延迟抖动会直接影响业务？</li>
</ul>
<p>因为显存容量决定的是系统边界。模型权重放不下，谈不上推理；KV cache 放不下，长上下文和并发就会突然崩；中间 buffer 和框架开销没算进去，部署时就会出现“理论可跑，线上 OOM”的尴尬。</p>
<p>我踩过的一个坑是，很多评估表只写“某模型 4-bit 需要 X GB 显存”，但实际系统还要留给 tokenizer、runtime、KV cache、embedding/rerank 模型、监控 sidecar、甚至同机其他服务。纸面上 24GB 能跑，生产上可能只能跑一个很憋屈的 demo。</p>
<p>这不是小题大做。RAG 系统尤其容易低估这件事。检索阶段可能很快，但一旦把多段文档塞进 prompt，prefill 成本和 KV cache 都会上来。如果你还要 rerank、引用溯源、工具调用，那显存压力不是线性增长那么简单。</p>
<h2 id="第二个影响带宽决定吞吐容量决定能不能活">第二个影响：带宽决定吞吐，容量决定能不能活</h2>
<p>容量和带宽经常被混在一起讲，但工程含义不同。</p>
<p>容量回答“能不能放下”。带宽回答“放下以后能不能喂得动”。</p>
<p>对于 decode 阶段，模型每生成一个 token 都要访问大量权重和缓存。计算核心如果等数据，就会空转。你看到 GPU 利用率不高，不一定是 batch 太小，也可能是内存带宽成了瓶颈。增加 batch size 有时能提高利用率，但 batch size 又会吃更多 KV cache，最后又回到容量问题。</p>
<p>这就是为什么 HBM 贵但绕不开。它不是普通 DDR 的升级版，而是为了把更多内存堆到计算核心旁边，用更宽的总线提供更高带宽。代价也明显：封装复杂、供应链紧张、成本高。Epoch AI 的 63% 数字，本质上就是这个代价在账面上的体现。</p>
<p>对企业来说，这里有个反直觉结论：不是所有场景都应该追求最高端 HBM GPU。</p>
<p>如果你的场景是低并发内部知识库、固定短上下文、延迟要求不高，也许一套便宜得多的本地推理方案就够了。反过来，如果你做的是多租户 Agent 平台、长上下文代码分析、实时客服或者高并发 RAG，省 GPU 预算可能会在延迟、稳定性和工程复杂度上加倍还回来。</p>
<p>硬件便宜，不等于系统便宜。</p>
<h2 id="第三个影响优化路线会更偏少搬数据">第三个影响：优化路线会更偏“少搬数据”</h2>
<p>既然内存越来越贵，推理优化就不会只围绕“算得更快”。我更看好几类减少数据搬运或提高有效利用率的方向：</p>
<p>第一是量化。它最直观，权重变小，显存占用下降，带宽压力也下降。但量化不是免费午餐，精度、模型兼容性、算子支持都会影响最终效果。尤其生产环境里，你不能只看一个 benchmark，要看业务数据上的退化。</p>
<p>第二是 KV cache 优化。长上下文和 Agent 场景会让 KV cache 变成吞显存的大户。分页 KV、压缩 KV、滑动窗口、prefix cache 都是在想办法让历史上下文不要无限制挤爆显存。</p>
<p>第三是 speculative decoding、多 token 预测和 draft model。它们的共同思路是：别让大模型每一步都全力出手。如果草稿路径猜得够准，就能减少主模型的昂贵 decode 次数。</p>
<p>第四是请求调度。很多推理系统的问题不是单请求慢，而是混合负载下互相拖累。短请求被长上下文请求堵住，交互请求被批处理吞吐策略牺牲，最后用户感知很差。好的调度不是把 GPU 塞满就完事，而是在吞吐、延迟和显存碎片之间做取舍。</p>
<p>这些方向看起来分散，其实都围绕同一件事：让有限的内存容量和带宽产生更多有效 token。</p>
<h2 id="那么企业应该怎么选">那么，企业应该怎么选？</h2>
<p>我的建议比较朴素：先用工作负载画像倒推硬件，而不是先买卡再找场景。</p>
<p>如果你做的是企业内部 RAG，先统计真实 prompt 长度、文档片段数量、并发峰值、可接受延迟，再决定是用云上高端 GPU、托管 API，还是本地小模型加 rerank。不要为了“数据不出门”盲目自建，也不要为了“省运维”把所有请求都扔给外部 API。</p>
<p>如果你做 AI coding 或 Agent 平台，重点看长上下文和工具调用带来的 KV cache 压力。代码库分析、日志读取、多轮修复，这些都不是短 prompt。单次 demo 流畅，不代表持续任务稳定。</p>
<p>如果你做本地推理产品，要把“可运行模型列表”改成“在目标硬件上的稳定体验”。用户不关心你理论支持多少模型，他们关心 32GB 内存的机器跑 7B 会不会卡，64GB 统一内存的 Mac 跑长上下文会不会慢到不可用，消费级 GPU 上下文一长是不是直接爆显存。</p>
<p>最后，如果预算有限，不要只盯 GPU 型号。很多时候，模型选择、上下文裁剪、检索质量、rerank 策略、缓存设计，比硬件升级更划算。硬件能买来上限，但系统设计决定你能不能接近这个上限。</p>
<h2 id="结语ai-基础设施正在回到系统工程">结语：AI 基础设施正在回到系统工程</h2>
<p>HBM 占 AI 芯片成本 63% 这个数字，我觉得它最大的意义不是“内存涨价了”，而是提醒我们：LLM 规模化落地已经不再是单纯模型能力问题，而是系统工程问题。</p>
<p>模型参数、显存容量、内存带宽、KV cache、batch 调度、RAG prompt 长度、用户延迟预期，这些东西必须放在一起看。</p>
<p>也许几年后，新的架构会缓解今天的 memory wall；也许 HBM 供应会更充足，成本曲线会下去。这块我不敢下定论。但至少现在，如果一个 AI 基础设施方案只讲“我们有多少算力”，却不讲内存和调度，我会非常谨慎。</p>
<p>因为在 LLM 推理里，算力决定你能跑多快；内存往往决定你能不能真正跑起来。</p>
<h2 id="参考信源">参考信源</h2>
<ul>
<li><a href="https://epoch.ai/data-insights/ai-chip-component-cost-shares">Epoch AI: AI Chip Component Costs — Memory at 63%</a></li>
<li><a href="https://news.ycombinator.com/item?id=48258684">Hacker News 讨论：Memory has grown to nearly two-thirds of AI chip component costs</a></li>
<li><a href="https://www.nvidia.com/en-us/data-center/h200/">NVIDIA H200 Tensor Core GPU</a></li>
<li><a href="https://www.micron.com/products/memory/hbm/hbm3e">Micron HBM3E 产品说明</a></li>
<li><a href="https://arxiv.org/abs/2403.14123">AI and Memory Wall, arXiv:2403.14123</a></li>
</ul>
]]></content:encoded></item><item><title>Forge Guardrails：本地 8B 模型能不能跑生产级工具调用 Agent？</title><link>https://blog.hypho.cn/posts/forge-guardrails-local-llm-agent-reliability/</link><pubDate>Wed, 20 May 2026 10:02:35 +0800</pubDate><guid>https://blog.hypho.cn/posts/forge-guardrails-local-llm-agent-reliability/</guid><description>Forge Guardrails 是一个面向本地 LLM 工具调用的开源可靠性层，试图用解析修复、重试提示、步骤约束和上下文管理，让 8B 模型承担多步 Agent 工作流。本文结合 HN 讨论、GitHub README、Model Guide 与 Eval Guide，分析它适合哪些生产场景、该如何评估，以及它不能替代权限隔离和业务判断的边界。</description><content:encoded><![CDATA[<p>本地 LLM 做 Agent，最容易被低估的不是模型能不能回答问题，而是它能不能稳定地把一串工具调用跑完。</p>
<p>这句话听起来有点扫兴。毕竟现在 7B、8B、14B 模型的 benchmark 分数越来越好，Ollama、llama.cpp、llama-server 也把本地部署门槛降到了很低。我之前写过一篇 <a href="https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/">本地 LLM 推理工具的取舍</a>，当时重点放在推理后端、模型格式和生态锁定上。但如果你真的想把本地模型接进自动化工作流，另一个问题会更快冒出来：模型单步看起来不错，多步之后为什么还是崩？</p>
<p>HN 上这两天有个项目 <a href="https://github.com/antoinezambelli/forge">Forge</a> 很适合拿来讨论这个问题。它的标题很抓人：“Guardrails take an 8B model from 53% to 99% on agentic tasks”。我对这种数字一向谨慎，因为 agentic task 的定义、评测场景和采样参数都会强烈影响结果。但 Forge 真正值得看的地方，不是“8B 追平 frontier model”这个营销点，而是它把本地 Agent 失败拆成了几个非常工程化的小故障：工具调用解析失败、走错步骤、错误恢复失败、上下文预算失控，以及多个工作流争用同一个 GPU 推理槽。</p>
<p>说白了，它不是在训练一个更聪明的模型，而是在给一个不够稳定的模型加流程控制。</p>
<h2 id="为什么本地-agent-会在多步任务里快速掉队">为什么本地 Agent 会在多步任务里快速掉队</h2>
<p>很多人第一次做工具调用 Agent，会拿一个天气查询、数据库查询或者代码搜索 demo 开始。模型需要做的事情很简单：读用户问题，选择工具，填参数，拿结果，再回答。单步成功率只要看起来有 90%，体验就会很好。</p>
<p>问题出在复合任务上。</p>
<p>假设一个工作流有 5 步，每一步成功率都是 90%。如果这些步骤必须全部正确，整体成功率不是 90%，而是 0.9 的 5 次方，大约 59%。这还是独立错误的理想情况；真实 Agent 里，前一步的轻微偏差会污染后续上下文，错误会复利。</p>
<p>Forge 作者在 <a href="https://news.ycombinator.com/item?id=48192383">HN 发布帖</a> 里也用了类似的“compounding math”解释：本地模型每一步都不算太差，但连续工具调用会把小错误放大成任务失败。这其实是我最认同它的地方。生产环境的 Agent 可靠性，很多时候不是靠“再换一个大模型”解决，而是靠把可控部分从自然语言里拿出来，交给确定性系统。</p>
<p>这也是为什么我会把 Forge 和之前写过的 <a href="https://blog.hypho.cn/posts/statewright-state-machine-agent-guardrails/">Statewright 状态机护栏</a> 放在同一类问题里看。Statewright 更偏“限制 Agent 在什么阶段能做什么”，Forge 更偏“当模型工具调用出错时，如何修、如何重试、如何阻止它跳步骤”。两者的共同点是：它们都不再迷信一个超长 system prompt。</p>
<h2 id="forge-到底加了哪几层护栏">Forge 到底加了哪几层护栏</h2>
<p>从 <a href="https://github.com/antoinezambelli/forge">Forge README</a> 看，它定位为 “a reliability layer for self-hosted LLM tool-calling”，支持 Ollama、llama-server、Llamafile 和 Anthropic 后端。它有三种用法：直接用 WorkflowRunner 构建工作流；把 Guardrails middleware 嵌进已有 orchestration loop；或者跑一个 OpenAI-compatible proxy，让 opencode、Continue、aider 这类客户端以为自己在调用一个更可靠的模型服务。</p>
<p>我更关心第二种和第三种，因为它们说明 Forge 不是又造一个全家桶 Agent 框架，而是试图站在“可靠性中间层”的位置。</p>
<p>第一层是 response validation 和 rescue parsing。小模型在工具调用里经常犯一种很烦的错：明明知道应该调用 <code>search</code>，却把 JSON 写坏、参数名写错，或者把解释性文字混在结构化输出里。Forge 的做法不是立刻失败，而是先尝试解析修复；修不了，再给模型一个更明确的 retry nudge。人话翻译就是：别把模型第一次输出当圣旨，先把低级格式错误拦下来。</p>
<p>第二层是 step enforcement。很多多步任务并不是“模型自由探索”越多越好，而是必须先 A 后 B。例如先检索，再读取详情，最后汇总；先跑测试，再改代码；先查库存，再下单。Forge 允许你声明 required steps 和 terminal tool，模型如果想过早结束或者跳过中间步骤，护栏会把它挡回去。这个思路和状态机很像，只是粒度更贴近工具调用循环。</p>
<p>第三层是 error recovery 和 context management。README 里提到 Forge 有 VRAM-aware budgets、tiered compaction，还提供 SlotWorker 给多 Agent 架构共享一个推理槽。这个点很现实：本地模型不是云 API，你可能只有一张 12GB、16GB 或 24GB 显卡。上下文开太大，速度慢、显存炸；上下文压太狠，Agent 忘掉关键状态。Forge 的 <a href="https://github.com/antoinezambelli/forge/blob/main/docs/MODEL_GUIDE.md">Model Guide</a> 把评测拆成 OG-18 和 advanced_reasoning 两层，并明确说多数实际 agentic flows 更接近 mechanical/mid，而不是最难的 adversarial 场景。这种说法比单纯贴一个总分诚实一些。</p>
<h2 id="8b-从-53-到-99该怎么理解">“8B 从 53% 到 99%”该怎么理解</h2>
<p>我不建议把这个数字直接理解成“本地 8B 模型已经能替代 Claude Sonnet”。</p>
<p>Forge README 当前写的是：Ministral-3 8B Instruct Q8 在 llama-server 上，跨 26 个场景得分 86.5%，hard tier 为 76%。HN 作者帖里则提到论文版本在 18 个场景上有 99.3% 的结果。两组数字不完全一样，原因可能包括评测集扩展、难度分层变化、模型/后端配置更新。对外部读者来说，最稳妥的读法是：<strong>Forge 在它定义的工具调用评测里显著提高了小模型稳定性，但这些数字不应直接外推到所有生产 Agent。</strong></p>
<p>这不是泼冷水，而是工程上必须说清楚边界。</p>
<p>如果你的 Agent 工作流高度结构化，工具集合有限，失败模式主要是 JSON 格式、步骤顺序、可恢复 API 错误，那么 Forge 这类护栏很可能有效。比如个人知识库检索、代码仓库内的固定检查、内部数据查询、批量文档处理，这些任务通常有清晰的步骤和终止条件。</p>
<p>但如果你的任务本身需要开放式规划、复杂业务判断、跨系统权限决策，或者工具返回结果非常嘈杂，护栏只能减少机械错误，不能替你补齐模型的判断力。一个小模型在错误事实基础上做出“格式完美”的工具调用，仍然是错的。</p>
<p>我自己的判断是：Forge 更像是本地 Agent 的“可靠性放大器”，不是“能力放大器”。它能让一个已经基本会做任务的模型少翻车，却不能让一个不会做任务的模型突然会做。</p>
<h2 id="什么时候值得引入-forge">什么时候值得引入 Forge</h2>
<p>如果你满足下面三个条件，我会认真考虑 Forge：</p>
<p>第一，你已经决定自托管模型。可能是成本原因，也可能是隐私、延迟、离线运行或者数据合规原因。否则最简单的方案仍然是先用 frontier API，把产品闭环跑通，再考虑本地化。</p>
<p>第二，你的 Agent 任务可以被描述成有限工具集 + 明确步骤 + 可验证终点。Forge 的强项正是这种场景：它可以检查工具名、参数、步骤顺序、终止条件和错误预算。如果你的工作流每次都要重新发明任务计划，它的收益会下降。</p>
<p>第三，你愿意维护评测。Forge 自带 <a href="https://github.com/antoinezambelli/forge/blob/main/docs/EVAL_GUIDE.md">Eval Guide</a>，但生产系统不能只看项目自带的 26 或 30 个场景。你需要把自己的真实任务抽样成 eval：成功标准是什么、允许几次重试、错误如何分类、上下文压缩后是否仍保留关键证据。没有这一步，所有护栏最后都会变成“看起来更稳”。</p>
<p>反过来，如果你只是想做一个聊天机器人，或者只是偶尔调用一两个工具，我不建议一上来引入这类中间层。复杂度是有成本的。你要理解 Workflow、ToolDef、Guardrails、backend adapter、context budget，还要处理本地模型服务本身的运维。很多团队真正需要的不是 Forge，而是更清晰的任务边界和更少的自动化野心。</p>
<h2 id="和提示词状态机安全沙箱的关系">和提示词、状态机、安全沙箱的关系</h2>
<p>这里还有一个容易混淆的点：guardrails 不是万能安全系统。</p>
<p>Forge 主要解决的是工具调用可靠性：解析、重试、步骤、上下文、后端适配。它不等于权限沙箱，也不等于供应链安全，也不等于 prompt injection 防护。如果 Agent 能调用 <code>rm -rf</code>、发邮件、转账或者修改生产数据库，你仍然需要独立的权限隔离、审批流、审计日志和最小权限设计。之前那篇 <a href="https://blog.hypho.cn/posts/agentarmor-8-layer-security-framework/">AgentArmor 安全框架</a> 讨论的就是另一层问题：当 Agent 有真实外部动作能力时，安全边界不能只靠模型自觉。</p>
<p>更准确地说，Forge 位于“模型输出”和“工具执行”之间。它检查模型想做的动作是否符合工作流规则，但不负责判断这个动作在业务上是否应该被允许。这个分工很重要。</p>
<p>我会把一个相对成熟的本地 Agent 架构分成四层：底层是推理后端，比如 llama-server 或 Ollama；上面是工具调用可靠性层，比如 Forge；再上面是工作流状态机或任务编排，比如 Statewright/OpenClaw 这类思路；最外层才是权限、安全和人工审批。少一层都可以做 demo，但要进生产，每一层迟早都会回来找你。</p>
<h2 id="我的结论先把可恢复错误工程化">我的结论：先把“可恢复错误”工程化</h2>
<p>Forge 这类项目让我比较乐观的一点是，它把 Agent 讨论从“模型会不会思考”拉回了“系统如何处理错误”。这是 AI 工程化必须经历的一步。</p>
<p>在过去一年里，很多 Agent 产品的默认叙事是：等模型更强，Agent 就会自然可靠。这个判断只对了一半。模型变强当然重要，但只要系统包含工具、状态、权限、上下文和外部副作用，可靠性就不可能只靠模型参数解决。Web 服务不会因为 CPU 更快就不需要重试、幂等和限流；Agent 也一样。</p>
<p>所以我对 Forge 的建议是：可以试，但不要神化。</p>
<p>把它放到一两个窄工作流里，拿自己的任务做 eval；把 bare loop、只加提示词、加 Forge guardrails 三种方案放在一起比；记录每次失败到底是解析错误、步骤错误、模型判断错误，还是工具本身错误。只有当你能说清楚失败类型，guardrails 才有意义。</p>
<p>如果最后发现 70% 的失败都是格式和流程问题，那 Forge 很可能是便宜有效的解法。如果 70% 的失败来自模型误解业务、检索证据不足或者工具权限设计混乱，那就别怪 8B 模型，也别怪护栏——你需要改的是系统边界。</p>
<p>本地 Agent 真正的生产化，不是把小模型包装成大模型，而是承认它会犯错，然后把每一种可预期的错误变成可检测、可重试、可回滚的工程机制。</p>
<p>Forge 做的，正是其中一块。</p>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://github.com/antoinezambelli/forge">Forge GitHub 仓库</a></li>
<li><a href="https://news.ycombinator.com/item?id=48192383">Forge HN 发布讨论</a></li>
<li><a href="https://github.com/antoinezambelli/forge/blob/main/docs/MODEL_GUIDE.md">Forge Model Guide</a></li>
<li><a href="https://github.com/antoinezambelli/forge/blob/main/docs/EVAL_GUIDE.md">Forge Eval Guide</a></li>
<li><a href="https://pypi.org/project/forge-guardrails/">forge-guardrails PyPI 页面</a></li>
</ul>
]]></content:encoded></item><item><title>Needle 26M 工具调用模型：Agent 真需要大模型来选工具吗？</title><link>https://blog.hypho.cn/posts/needle-26m-tool-calling-model/</link><pubDate>Wed, 13 May 2026 10:03:15 +0800</pubDate><guid>https://blog.hypho.cn/posts/needle-26m-tool-calling-model/</guid><description>Needle 是 Cactus 开源的 26M 参数工具调用模型，主张把单轮 function calling 视为检索与组装问题，而不是通用推理问题。本文从 Simple Attention Networks、端侧推理、微调和生产边界出发，分析小模型在 AI Agent 工具路由中的工程价值与风险。</description><content:encoded><![CDATA[<p>如果你正在做 AI Agent，有一个问题很容易被忽略：<strong>Agent 到底需不需要一个很大的模型来“选择工具”？</strong></p>
<p>我以前默认答案是“需要”。毕竟工具调用看起来像推理：用户说“明天早上 8 点提醒我带伞”，模型要理解意图、找到日历或提醒工具、抽取时间、地点和参数，最后输出一段合法 JSON。让 7B、14B 甚至更大的模型来做，似乎很自然。</p>
<p>但这两天 HN 上的 <a href="https://news.ycombinator.com/item?id=48111896">Needle</a> 把这个直觉反过来了。Cactus 团队开源了一个只有 26M 参数的 function calling 模型，README 里说它是把 Gemini 3.1 的工具调用能力蒸馏到一个 “Simple Attention Network” 上，目标是跑在手机、手表、眼镜这类消费设备上。项目目前 MIT 开源，代码在 <a href="https://github.com/cactus-compute/needle">cactus-compute/needle</a>，权重放在 <a href="https://huggingface.co/Cactus-Compute/needle">Hugging Face</a>。</p>
<p>26M 是什么概念？比很多 embedding 模型还小，比常见的 0.5B/1.5B 小模型又小一个数量级。它不打算写诗、聊天、做数学题，只做一件事：给定用户 query 和工具 schema，吐出应该调用的工具及参数。</p>
<p>坦白说，我觉得这个方向比“又一个端侧聊天机器人”更值得写。因为生产里的 Agent 系统，最先遇到瓶颈的往往不是“模型不够聪明”，而是“每一步都太贵、太慢、太不稳定”。</p>
<h2 id="把工具调用从推理降级成路由">把工具调用从“推理”降级成“路由”</h2>
<p>Needle 的核心判断很激进：单轮工具调用本质上不是开放式推理，而是 retrieval-and-assembly。</p>
<p>用人话说，就是三步：先从工具列表里匹配哪个工具最像用户意图；再从用户句子里抽参数；最后按 schema 拼成 JSON。这个过程当然需要语言理解，但它未必需要一个装满世界知识的大模型。工具说明和参数 schema 已经作为输入给了模型，事实知识在上下文里，不必塞进 FFN 权重里。</p>
<p>这也是它的架构为什么反常。Needle 的 <a href="https://github.com/cactus-compute/needle/blob/main/docs/simple_attention_networks.md">Simple Attention Networks 文档</a> 里明确写到：实验发现，如果任务依赖外部结构化知识，Transformer 里的 MLP/FFN 可以被完全拿掉，模型主要靠 attention 和 gating 工作。Needle 的结构是 12 层 encoder 加 8 层 decoder，隐藏维度 512，8 个 attention head，BPE 词表 8192；README 还强调 “no MLPs anywhere”。</p>
<p>这句话的工程含义很直白：FFN 更像模型的“记忆仓库”和非线性加工层，而工具调用场景里的“记忆”已经外置成工具列表了。既然你每次都把 <code>get_weather(location)</code>、<code>create_timer(duration)</code>、<code>send_message(contact, text)</code> 这些 schema 喂给模型，它要做的就不是背知识，而是对齐 query 与 schema。</p>
<p>这有点像 RAG 里的 rerank。你不会让一个通用大模型从全世界知识里凭空猜文档，而是先给它候选，再让它排序。此前我在写 <a href="https://blog.hypho.cn/posts/rerank-bi-encoder-cross-encoder/">RAG 重排里的 Bi-Encoder 与 Cross-Encoder</a> 时就说过：一旦候选空间被压小，专用模型往往比通用模型更划算。Needle 放到 Agent 里也是类似逻辑：工具集就是候选空间，function calling 模型就是路由器。</p>
<p>说白了，它不是想替代 GPT-5，而是想替代 Agent 系统里那一层“每次都请大模型选工具”的昂贵默认值。</p>
<h2 id="小模型真正省下来的不是钱而是系统复杂度">小模型真正省下来的不是钱，而是系统复杂度</h2>
<p>README 里给了一个很抓眼球的数字：Needle 在 Cactus 上可以达到 6000 tokens/s prefill、1200 tokens/s decode。这个数字要谨慎看，因为它和硬件、量化、输入长度、batch 方式都有关，不能直接拿来和云端 API 或 vLLM 服务做横向对比。但即便打个折，它也说明一个事实：26M 参数模型的部署形态完全不同。</p>
<p>大模型工具调用通常意味着：请求从 App 发到后端，后端调用 LLM API 或自建推理服务，模型返回 JSON，业务再执行工具。这里面有网络、鉴权、队列、限流、日志脱敏、失败重试和成本核算。每多一次 Agent step，都多一次系统不确定性。</p>
<p>如果工具路由能在端侧或本地服务完成，架构会简单很多。比如手机上的个人助手要在“计时器、短信、日历、导航、智能家居”之间选择工具，它不一定需要把用户原话发到云端；浏览器插件要对页面做轻量操作，也不一定要每次走服务器。这个判断和我之前写 <a href="https://blog.hypho.cn/posts/chrome-prompt-api-browser-local-llm/">Chrome Prompt API</a> 时的结论一致：端侧模型的核心价值不是更聪明，而是更靠近数据、更低延迟、更少合规解释。</p>
<p>当然，Needle 不是 Chrome 内置能力，它是一个开源模型和训练/微调工具链。但它代表的是同一条路线：把低风险、结构化、可校验的 AI 子任务从“大模型中心”拆出来，下沉到更便宜的位置。</p>
<p>我更看重的是这件事对 Agent 编排的影响。很多 Agent 框架现在喜欢把所有步骤都丢给同一个大模型：规划、选工具、写参数、观察结果、再规划。这样做 Demo 很快，但线上很难控。一个更工程化的拆法应该是：</p>
<ul>
<li>复杂规划交给强模型；</li>
<li>工具路由交给小模型或规则+模型混合层；</li>
<li>参数校验交给 schema validator；</li>
<li>高风险动作再让强模型或人工复核。</li>
</ul>
<p>Needle 正好卡在第二层。</p>
<h2 id="但别把它误读成26m-打败大模型">但别把它误读成“26M 打败大模型”</h2>
<p>我不太喜欢一些小模型项目的宣传口径：动不动就“beats Qwen / Gemma / Granite”。Needle README 里也提到它在单轮 function calling 上优于 FunctionGemma-270M、Qwen-0.6B、Granite-350M、LFM2.5-350M，但同时也承认这些模型的能力范围更大，聊天和通用任务更强，小模型也会比较 finicky。</p>
<p>这点很重要。</p>
<p>工具调用在生产里不是一个单一 benchmark。真实系统里会出现很多脏情况：用户一句话包含多个意图；工具 schema 写得含糊；业务参数有隐式默认值；同名联系人需要 disambiguation；模型输出 JSON 合法但业务语义错；多轮上下文里前一句的“它”到底指哪个对象。26M 模型如果只做 single-shot function call，遇到这些场景就需要外部系统补位。</p>
<p>所以我的建议不是“把 Agent 的工具调用全部换成 Needle”，而是先把任务分层。</p>
<p>适合 Needle 这类小模型的场景，大概有三个特征：第一，工具集合稳定且数量有限；第二，用户表达比较短，主要是单轮命令；第三，错误可以被校验、回退或二次确认。比如本地设备助手、浏览器扩展、企业内部固定流程、IoT 控制、低风险自动化命令。</p>
<p>不适合的场景也很明显：跨系统长链路规划、金融/医疗/法律等高风险动作、强多轮上下文依赖、工具 schema 高频变化、需要复杂业务推理的 Agent。这些地方小模型可以做候选路由，但不该单独拍板。</p>
<p>换句话说，Needle 的生产价值不是“更强”，而是“更窄”。窄到可以测试、可以微调、可以部署在边缘，也可以被工程系统包住。</p>
<h2 id="微调按钮很诱人数据质量才是坑">微调按钮很诱人，数据质量才是坑</h2>
<p>Needle 提供了 playground、CLI 和 Python API。README 的 Quickstart 是：clone 仓库，<code>cd needle &amp;&amp; source ./setup</code>，然后 <code>needle playground</code> 打开本地 Web UI；Python 里可以加载 checkpoint，把 query 和 tools 传给 <code>generate()</code>，得到类似 <code>[{&quot;name&quot;:&quot;get_weather&quot;,&quot;arguments&quot;:{&quot;location&quot;:&quot;San Francisco&quot;}}]</code> 的结果。它还支持 <code>needle finetune data.jsonl</code>，并且可以用 Gemini 生成训练数据。</p>
<p>这个体验看起来很顺，但我会特别提醒一句：微调工具调用模型，最难的不是跑训练，而是定义“正确”。</p>
<p>比如一个 CRM Agent 里有 <code>create_lead</code>、<code>update_contact</code>、<code>log_activity</code> 三个工具。用户说“把刚才那个客户加到下周跟进里”，到底应该调哪个？如果业务流程要求先查联系人再建任务，单轮数据里只标一个最终工具可能就是错的。再比如参数抽取，时间、币种、地区、权限范围都可能有业务默认值，这些默认值不在用户原话里，模型很容易学出看似合理但实际危险的补全。</p>
<p>所以，如果真要把 Needle 用到内部系统，我会这样落地：先从日志里抽取高频、低风险、单工具动作；人工审核一小批高质量 JSON 标注；用 schema validator 做硬约束；上线后只让它处理置信度高的请求；低置信度或校验失败就回退到强模型。不要一上来就让小模型接管所有工具调用。</p>
<p>这和我们做 <a href="https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/">本地 LLM 推理选型</a> 时的经验一样：模型只是系统的一块。真正决定可用性的，是输入边界、失败回退、观测指标和数据闭环。</p>
<h2 id="我会怎么评价-needle">我会怎么评价 Needle</h2>
<p>先说优点。它把一个长期被大模型垄断的子任务拆了出来，并且给了代码、权重、训练入口和架构解释。GitHub API 显示，Needle 仓库有 400+ stars，最近提交就在 2026 年 5 月 12 日，根目录包含 <code>needle/</code>、<code>pyproject.toml</code>、<code>requirements.txt</code>、<code>setup</code> 和训练脚本，不是只有白皮书的概念项目。背后的 <a href="https://github.com/cactus-compute/cactus">Cactus</a> 也是一个移动端低延迟 AI 引擎，stars 已经超过 4.7k，说明团队不是临时拼了一个 README。</p>
<p>再说保留意见。第一，Needle 目前更像一个实验性专用模型，而不是成熟平台。它的最佳场景是 single-shot function calling；如果你的 Agent 依赖复杂多轮状态，它不会神奇解决问题。第二，公开 benchmark 还需要更多第三方复现。README 里的速度和效果数字值得关注，但生产选型不能只看项目方自测。第三，端侧部署还涉及模型更新、兼容性、隐私日志、用户授权和安全策略，这些都不是 26M 参数本身能解决的。</p>
<p>但我依然觉得它值得跟进。原因不是它“打败了大模型”，而是它逼我们重新拆分 Agent 架构：哪些步骤真的需要强推理？哪些只是结构化映射？哪些可以由小模型、本地模型甚至规则系统完成？</p>
<p>这会是未来 Agent 工程里很现实的一条优化线。</p>
<p>如果你现在已经有 Agent 产品，我建议做一个小实验：把最近一周的工具调用日志拿出来，按“单轮/多轮、单工具/多工具、低风险/高风险、可校验/不可校验”四个维度打标签。你可能会发现，相当一部分调用并不需要昂贵的大模型。它们需要的是一个快、便宜、可控的工具路由层。</p>
<p>Needle 给这个路由层提供了一个可验证的开源起点。</p>
]]></content:encoded></item><item><title>DeepSeek V4 Flash 本地推理：ds4.c 的窄引擎路线值得跟吗？</title><link>https://blog.hypho.cn/posts/deepseek-v4-flash-ds4-metal-inference/</link><pubDate>Fri, 08 May 2026 14:19:08 +0800</pubDate><guid>https://blog.hypho.cn/posts/deepseek-v4-flash-ds4-metal-inference/</guid><description>ds4.c 是 antirez 为 DeepSeek V4 Flash 写的 Metal 本地推理引擎，主打 1M 上下文、2-bit MoE 量化、磁盘 KV cache 和 OpenAI/Anthropic 兼容接口。本文分析它相对 llama.cpp、Ollama 的工程价值、硬件门槛与生产落地边界，帮助判断是否值得投入。</description><content:encoded><![CDATA[<p>如果你已经在本地跑过大模型，应该很熟悉这个循环：先等通用推理框架支持新模型，再等量化格式稳定，再等各种 wrapper 把 API、工具调用、流式输出补齐。等一切能用时，下一代模型又来了。</p>
<p>所以我看到 Hacker News 上 <a href="https://news.ycombinator.com/item?id=48050751">DeepSeek 4 Flash local inference engine for Metal</a> 这条讨论时，第一反应不是“又一个本地 LLM 项目”，而是：<strong>它把通用框架的路线反过来了。</strong></p>
<p><a href="https://github.com/antirez/ds4">ds4.c</a> 不是一个新的 llama.cpp 替代品，也不是 Ollama 那种“模型管理 + 服务封装”。README 开头就把边界画得很死：它是一个只服务 DeepSeek V4 Flash 的原生推理引擎，主路径是 DeepSeek V4 Flash 专用的 Metal graph executor、DS4 专用加载器、prompt rendering、KV state 和 server API glue。换成人话说，它不是想做“什么模型都能跑”，而是想把一个特定模型在 Apple Silicon 上榨干。</p>
<p>坦白说，我挺喜欢这种不讨好所有人的设计。因为本地推理这件事，很多时候不是缺一个更漂亮的客户端，而是缺一条足够明确的工程假设。</p>
<h2 id="窄引擎到底在赌什么">“窄引擎”到底在赌什么</h2>
<p>通用推理框架的优势很明显：模型覆盖广、社区大、格式生态成熟。比如 <a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a> 已经是 GGUF 世界的事实底座，GitHub API 显示它仍在高频更新，star 超过 10 万。Hypho 之前写过 <a href="https://blog.hypho.cn/posts/local-llm-inference-engine-ollama-llama-cpp/">本地 LLM 推理引擎之争</a>，核心判断也是：如果你要严肃做本地部署，底层引擎的透明度和社区活跃度比“安装是否一行命令”更重要。</p>
<p>但通用性有代价。</p>
<p>一个框架要支持几十种架构，就很难为某个模型的奇怪结构做激进假设。ds4.c 选择了另一边：它接受自己只能跑 DeepSeek V4 Flash，换来对这个模型的深度适配。项目 README 里列出的几个卖点很有代表性：DeepSeek V4 Flash 的 active parameters 更少；thinking 模式下推理段落更短；上下文窗口达到 1M tokens；KV cache 可以高度压缩并持久化到磁盘；2-bit 量化在特定 MoE 专家上效果可接受。</p>
<p>这里最值得看的不是“2-bit”三个字，而是它量化的对象。ds4.c 的模型说明写得很细：2-bit quantization 不是把所有权重粗暴压到 2 bit，而是主要压缩 routed MoE experts，其中 up/gate 用 <code>IQ2_XXS</code>，down 用 <code>Q2_K</code>，shared experts、projections、routing 等部分保留。人话翻译：它压的是模型里最占空间、同时相对更能承受压缩的那部分，不是拿精度当祭品换一个营销数字。</p>
<p>这也是为什么它能把目标机器定在 128GB RAM 的 MacBook / Mac Studio 上。注意，这不是消费级“随便一台电脑都能跑”。它更像高端个人工作站上的本地准前沿模型实验。</p>
<h2 id="磁盘-kv-cache-这个点比很多人想得重要">磁盘 KV cache 这个点，比很多人想得重要</h2>
<p>我觉得 ds4.c 最有意思的地方不是 Metal，也不是 OpenAI 兼容接口，而是它把 KV cache 当成“一等磁盘公民”。</p>
<p>传统直觉里，KV cache 应该放在显存或内存，因为生成过程会频繁读写它。但 1M tokens 上下文会把这个直觉打爆：上下文越长，KV cache 越像一个巨大、持续增长、但访问模式相对可预期的状态存储。ds4.c 的 README 明确建议本地 agent 场景使用 <code>--kv-disk-dir</code> 和 <code>--kv-disk-space-mb</code>，并提示 1M context 大约会带来 26GB 级别的额外内存占用，压缩索引器本身可能接近 22GB。</p>
<p>说白了就是：如果你想让一个本地 coding agent 真正读完整个仓库、保留长会话、不中途清上下文，瓶颈未必只是“模型能不能加载”，而是“长期上下文状态放在哪里”。</p>
<p>这和我最近写 <a href="https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/">Gemma 4 多 token 预测</a> 时的感受类似：下一阶段推理优化不会只靠量化。量化解决“模型放不放得下”，投机解码解决“每秒吐多少 token”，而 KV cache 管理解决“长任务能不能不断片”。本地 agent 真要进入生产工作流，这三件事都绕不开。</p>
<p>当然，把 KV cache 放磁盘也不是免费午餐。现代 MacBook SSD 很快，但它不是 HBM；不同任务的访问局部性也不一样。ds4.c 现在的实现更像一个明确方向：在高内存 Apple Silicon 上，用压缩和磁盘持久化换取超长上下文可用性。至于它在多并发、长时间服务、异常恢复下能稳到什么程度，还需要更多实测。</p>
<h2 id="api-兼容不是装饰而是-agent-落地的入口">API 兼容不是装饰，而是 agent 落地的入口</h2>
<p>很多本地推理项目会停在 CLI demo：能问答，能跑 benchmark，但接入真实工具链时一地鸡毛。ds4.c 这点做得比较务实。它的 server 支持 <code>GET /v1/models</code>、OpenAI 风格的 <code>/v1/chat/completions</code> 和 <code>/v1/completions</code>，也提供 Anthropic 兼容的 <code>/v1/messages</code>。README 还特别提到工具 schema 会被渲染成 DeepSeek 的 DSML tool format，再把生成的 DSML tool calls 映射回 OpenAI tool calls；thinking 模式下 reasoning 会以原生 API 形态流式返回，而不是混进最终文本。</p>
<p>这听起来像接口细节，但对 coding agent 很关键。Claude Code、OpenAI-compatible clients、内部 agent runtime 往往已经围绕这些 API 形态写好了。一个本地引擎如果不能稳定处理 tool calls、streaming、stop sequences、context limit，开发者就要在 adapter 层补一堆脆弱胶水。</p>
<p>我对这里的判断是：ds4.c 的目标不是“让普通用户聊天”，而是“让本地高端模型接进 agent 工作流”。这解释了为什么它会同时关心长上下文、工具调用、Anthropic endpoint、SSE streaming 和磁盘 KV。它不是产品包装，而是面向工程集成的最小闭环。</p>
<p>但也别误会，这不等于它已经适合生产多租户服务。README 说当前 server 不会 batch 多个独立请求；并发请求会在单个 live graph/session 上排队。这个限制很诚实，也很重要。你可以把它放在个人开发机、团队内部实验机、单用户 coding agent 后端；但如果你想把它当成公司统一 LLM gateway 后面的共享推理池，那大概率会踩到吞吐和隔离问题。</p>
<h2 id="它和-llamacpp--ollama-不是同一类选择">它和 llama.cpp / Ollama 不是同一类选择</h2>
<p>如果你问“ds4.c 能不能替代 llama.cpp”，我的答案是：不该这么问。</p>
<p>llama.cpp 的价值在生态。它支持大量模型、量化格式、硬件后端和社区工具，是本地 LLM 的基础设施层。ds4.c 的价值在垂直优化：围绕 DeepSeek V4 Flash 做强假设，甚至模型权重也要求使用项目发布的 GGUF；README 明确说它不是通用 GGUF loader，任意 DeepSeek/GGUF 文件不会具备引擎期望的 tensor layout、量化组合、metadata 或 optional MTP state。</p>
<p>Ollama 则是另一回事。它降低了下载和启动门槛，但抽象层也会遮住很多底层细节。对于“今天临时试个模型”的用户，Ollama 仍然方便；对于“我要知道 KV cache 怎么管、工具调用怎么映射、量化到底压了哪部分”的工程团队，ds4.c 这种窄而透明的项目反而更有参考价值。</p>
<p>所以我的建议很简单：</p>
<ul>
<li>如果你要广泛评估模型，用 llama.cpp 或基于它的工具链；</li>
<li>如果你要给非技术用户一个本地聊天入口，用 Ollama/LM Studio 这类产品化工具更省事；</li>
<li>如果你正在研究 Apple Silicon 上的本地 coding agent、长上下文仓库理解、DeepSeek V4 Flash 专用部署，ds4.c 值得单独拉出来测试；</li>
<li>如果你的目标是生产级多用户推理服务，先别急着押注，至少要补并发、观测、限流、崩溃恢复和模型升级策略。</li>
</ul>
<p>这块我也不想说得太满。ds4.c 创建时间很新，GitHub API 显示仓库在 2026-05-06 创建、2026-05-07 仍有 push，star 已超过 900，说明它真实活跃，但生命周期还很短。短期内，它更适合作为工程路线样本，而不是稳定基础设施承诺。</p>
<h2 id="我真正想从-ds4c-里带走的三件事">我真正想从 ds4.c 里带走的三件事</h2>
<p>第一，本地推理正在从“通用运行时”分叉出“模型专用运行时”。当模型结构越来越复杂，MoE、MTP、压缩 KV、专用 tool format 都可能让通用抽象变重。窄引擎未必会成为主流，但它会逼通用框架吸收更激进的优化。</p>
<p>第二，Apple Silicon 的角色在变化。过去 Mac 跑大模型常被看成玩具或开发体验；现在 128GB/256GB 统一内存机器开始进入“本地准前沿推理”的讨论。它不一定比数据中心 GPU 更划算，但在隐私、离线、个人 agent、长上下文代码库分析上，有自己的位置。</p>
<p>第三，agent 推理优化不能只看 tokens/s。长上下文状态、工具调用一致性、API 兼容、reasoning 流式输出、缓存持久化，都会影响真实可用性。一个 benchmark 上快 20% 的引擎，如果每次工具调用都要你手写 adapter，最后未必省时间。</p>
<p>我的结论是：ds4.c 不适合被当成“下一代通用本地 LLM 平台”来吹，但它非常适合当作一个问题来研究——<strong>当我们愿意为一个模型放弃通用性，本地推理到底能换回多少工程确定性？</strong></p>
<p>这个问题，比又一个漂亮聊天界面重要多了。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://github.com/antirez/ds4">antirez/ds4 GitHub README</a></li>
<li><a href="https://news.ycombinator.com/item?id=48050751">DeepSeek 4 Flash local inference engine for Metal - Hacker News</a></li>
<li><a href="https://huggingface.co/antirez/deepseek-v4-gguf">antirez/deepseek-v4-gguf on Hugging Face</a></li>
<li><a href="https://huggingface.co/deepseek-ai/DeepSeek-V3.2-Exp">DeepSeek-V3.2-Exp on Hugging Face</a></li>
<li><a href="https://github.com/ggml-org/llama.cpp">llama.cpp GitHub repository</a></li>
</ul>
]]></content:encoded></item><item><title>Gemma 4 的多 token 预测：LLM 推理加速不该只盯着量化</title><link>https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/</link><pubDate>Wed, 06 May 2026 10:03:32 +0800</pubDate><guid>https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/</guid><description>Google 在 Gemma 4 中引入多 token 预测草稿器，宣称推理最高可提速 3 倍。本文从 speculative decoding、MTP 训练目标、推理框架调度和生产部署取舍角度分析：为什么 LLM 推理优化不能只盯着量化，哪些场景适合多 token 预测，哪些场景仍要谨慎评估。</description><content:encoded><![CDATA[<p>如果你最近还在把“LLM 推理优化”等同于量化，我建议停一下。</p>
<p>量化当然重要，尤其是本地部署和消费级 GPU 场景。但 Google 刚发的 Gemma 4 多 token 预测（Multi-Token Prediction, MTP）让我更确信一件事：下一轮推理加速的主战场，不只是在“把模型压小”，而是在<strong>减少大模型被调用的次数</strong>。</p>
<p>Google 在官方博客里说，Gemma 4 通过 MTP drafters 在推理阶段最高可以做到 <a href="https://blog.google/innovation-and-ai/technology/developers-tools/multi-token-prediction-gemma-4/">up to 3x faster</a>。这个数字本身很抓眼球，但我更关心它背后的工程含义：如果草稿器能一次猜中多个后续 token，大模型就不必老老实实一个 token 一个 token 地跑完整前向传播。</p>
<p>说白了就是：以前是大模型每吐一个字都要“亲自审批”；现在是小模型先写一小段，大模型批量盖章。</p>
<h2 id="为什么一个-token-一次前向这么浪费">为什么“一个 token 一次前向”这么浪费</h2>
<p>自回归 LLM 的默认解码方式很朴素：给定上下文，预测下一个 token；把这个 token 拼回上下文，再预测下一个。这个循环看起来合理，但对硬件很不友好。</p>
<p>每生成一个 token，模型都要访问大量权重。对于 27B、70B 这种规模，瓶颈往往不是矩阵乘法算不动，而是显存带宽和调度开销被小步循环吃掉。你可以把它理解成：GPU 明明适合一次搬一大车货，结果我们让它每次只送一个快递。</p>
<p>这也是为什么我之前写 <a href="https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/">DFlash + DDTree 投机解码</a> 时，最看重的不是某个 benchmark 数字，而是“平均接受长度”。只要一次验证能接受更多 token，大模型前向次数就会下降，吞吐自然上来。</p>
<p>Gemma 4 的 MTP 走的是同一条大方向，但实现路径更靠近模型训练本身。</p>
<p>传统 speculative decoding 通常需要一个独立的小 draft model。经典论文 <a href="https://arxiv.org/abs/2302.01318">Speculative Sampling</a> 的思路就是：小模型先生成候选，大模型并行验证，最后用修正过的采样过程保证输出分布不变。这套方法很漂亮，但工程上有两个麻烦：你要维护两个模型，还要处理 tokenizer、KV cache、调度和显存布局。</p>
<p>MTP 的反直觉之处在于，它不一定非要靠“另一个完整小模型”来猜。Meta 的论文 <a href="https://arxiv.org/abs/2404.19737">Better &amp; Faster Large Language Models via Multi-token Prediction</a> 提出，在训练时让模型不只预测下一个 token，而是同时预测未来多个 token。技术上可以看成在共享 trunk 上接多个输出 head，训练目标从“只看一步”扩展到“顺手看几步”。</p>
<p>人话翻译：模型训练时被迫学习“接下来一小段会怎么走”，而不是只盯着下一个词。</p>
<h2 id="gemma-4-的关键变化草稿器变成模型能力的一部分">Gemma 4 的关键变化：草稿器变成模型能力的一部分</h2>
<p>Google 这次讲 Gemma 4 的重点，是把 MTP drafters 用在推理加速上。按照官方描述，Gemma 4 会用多 token 预测草稿器生成候选 token，然后由主模型验证，从而降低延迟、提高吞吐。Gemma 系列本身是 Google 面向开发者开放的轻量模型家族，相关文档可以在 <a href="https://ai.google.dev/gemma/docs">Gemma 官方文档</a> 里看到；如果你更关心本地 C++ 推理，Google 也维护了 <a href="https://github.com/google/gemma.cpp">gemma.cpp</a>，这是一个专门服务 Gemma 模型的轻量推理引擎。</p>
<p>这里有个细节很重要：MTP 不只是“再外挂一个小模型”。如果训练阶段就把多步预测能力纳入目标函数，草稿器的命中率可能会比临时找一个小模型更稳定。命中率越高，大模型一次验证接受的 token 越多，加速越接近理论上限。</p>
<p>但我不会把它理解成“所有 LLM 推理都要马上换 MTP”。工程上至少有三件事要先问清楚。</p>
<p>第一，<strong>你的场景是 latency-bound 还是 throughput-bound</strong>。如果是单用户聊天，用户感知最明显的是首 token 延迟和流式输出节奏；MTP 可能让后续 token 更快，但未必显著改善 first token。如果是代码补全、批量生成、离线摘要，MTP 的收益通常更实在，因为这些任务可以吃到连续 token 的批量验证红利。</p>
<p>第二，<strong>你的输出是否足够可预测</strong>。代码、结构化文本、模板化报告通常更容易被草稿器猜中；开放式创意写作、强采样、多轮工具调用则不一定。草稿命中率一低，验证成本还在，加速就会打折。</p>
<p>第三，<strong>推理框架是否真的支持这套调度</strong>。很多人看到论文数字就想上线，但真正难的是 runtime：KV cache 怎么复用、draft tokens 怎么批量验证、失败回退怎么处理、batch 内不同请求的接受长度不同怎么办。Google 自家栈可以先做起来，不代表你今天拿 vLLM、llama.cpp 或自研服务就能无缝吃到同样收益。</p>
<p>这也是我对 Gemma 4 MTP 的判断：它是一个值得跟进的推理方向，但不是“替代量化”的银弹。</p>
<h2 id="量化投机解码mtp-应该怎么选">量化、投机解码、MTP 应该怎么选</h2>
<p>如果你在做生产部署，我会按这个顺序考虑。</p>
<p>先做量化，因为它最确定。INT8、INT4、GGUF、AWQ、GPTQ 这些路线解决的是“能不能装下、能不能便宜跑”的问题。我之前在 <a href="https://blog.hypho.cn/posts/local-llm-inference-engine-ollama-llama-cpp/">本地 LLM 推理引擎对比</a> 里也提过，本地推理首先要选对 runtime，否则模型再小也会被后端拖垮。</p>
<p>然后再看 speculative decoding 或 MTP，因为它解决的是“同样一次大模型计算，能不能多吐几个 token”。这类优化对服务端很诱人：吞吐上来，单位 token 成本下降；延迟下降，用户体验也更接近即时反馈。</p>
<p>但别跳过验证。至少要测四个指标：</p>
<ul>
<li>平均接受长度：一次验证平均能保留多少 draft token</li>
<li>首 token 延迟：用户是不是更快看到第一个字</li>
<li>端到端 tokens/s：包含草稿、验证、回退后的真实吞吐</li>
<li>质量一致性：高温采样、代码生成、长上下文下是否偏离原模型</li>
</ul>
<p>最后一个指标经常被忽略。Speculative Sampling 论文强调可以保持目标模型分布，这是理论上很强的保证；但到了具体工程实现，采样参数、数值精度、batch 调度都可能引入偏差。生产环境里，性能优化只要悄悄改变输出行为，就不是纯优化，而是一次模型行为变更。</p>
<h2 id="我真正看好的是什么">我真正看好的是什么</h2>
<p>我看好 MTP，不是因为“Gemma 4 快 3 倍”这个宣传数字，而是因为它把推理加速从外部 hack 推向了模型原生能力。</p>
<p>过去两年，LLM 基础设施的很多优化都是补丁式的：量化、PagedAttention、KV cache、FlashAttention、投机解码，各自解决一段瓶颈。MTP 的意义在于，训练目标本身开始为推理效率让路。模型不再只学“下一个 token”，而是学“未来一小段”。这听起来只是训练技巧，实际上会改变 runtime 的设计假设。</p>
<p>不过我也保留一点怀疑：Google 现在给出的还是官方博客级别的结果，真实开源权重、不同硬件、不同任务上的收益需要社区复现。尤其是中文、代码、长上下文和 agent 工具调用场景，接受长度可能差异很大。这里我也不敢拍胸脯说一定有效。</p>
<p>如果你今天要做决策，我的建议很简单：</p>
<ul>
<li>本地/边缘部署：先关注量化和 runtime，MTP 等生态成熟</li>
<li>服务端高吞吐生成：尽快把 speculative decoding / MTP 纳入 benchmark</li>
<li>代码生成和结构化输出：优先测试，因为草稿命中率可能最高</li>
<li>Agent 工具调用：谨慎，工具边界会打断连续生成，收益未必稳定</li>
</ul>
<p>Gemma 4 这次提醒我们，LLM 推理优化不能只盯着“模型变小”。更大的机会可能在于：让大模型少干重复劳动，把它真正用在验证和决策上。</p>
<p>这条路才刚开始。</p>
]]></content:encoded></item><item><title>单卡 207 tok/s：DFlash + DDTree 让 Qwen3.5-27B 在 RTX 3090 上跑出推理新纪录</title><link>https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/</link><pubDate>Tue, 21 Apr 2026 10:05:00 +0800</pubDate><guid>https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/</guid><description>DFlash 块扩散草稿 + DDTree 树验证，在单张 RTX 3090 上把 Qwen3.5-27B Q4_K_M 推到 207 tok/s，比自回归解码快 5.46 倍。Lucebox 项目开源了首个 GGUF 版本的 DFlash 实现，揭开消费级 GPU 跑大模型推理的新思路。</description><content:encoded><![CDATA[<p>一个 27B 参数的大模型，在一张 2021 年买的游戏显卡上能跑多快？</p>
<p>Lucebox 团队给出了一个让很多人没想到的数字：<strong>207.6 token/s</strong>。用的还是 Qwen3.5-27B 官方模型，不是蒸馏，不是 INT8 量化残血版——就是 Q4_K_M 量化版本，目标加草稿模型全部加载在一张 24 GB VRAM 的 RTX 3090 上。</p>
<p>这个成绩靠的不是等英伟达下一代消费级显卡，而是对<strong>解码算法本身</strong>动刀子。</p>
<h2 id="为什么自回归解码是瓶颈">为什么自回归解码是瓶颈</h2>
<p>大多数人聊 LLM 推理优化，会先想到量化、KV cache 压缩、batch 并行。但对单卡消费级 GPU 来说，这些都已经做到头了——Q4_K_M 量化能压缩到约 16 GB，再压下去效果肉眼可见地降。</p>
<p>问题出在<strong>自回归解码本身</strong>。每生成一个 token，GPU 要完整跑一遍 27B 参数的前向传播。27B 参数在 Q4_K_M 下大约 16 GB，VRAM 带宽是 936 GB/s——每次解码都要把这 16 GB 从显存读一遍，理论带宽利用率撑死不到 20%。这是机械式的物理限制，不是软件优化能绕过去的。</p>
<p>speculative decoding（投机解码）解决的就是这个问题：用一个<strong>小草稿模型</strong>一次生成多个候选 token，再用<strong>大模型</strong>一次验证整串。如果草稿猜得准，大模型只跑一次就能吐出五六个 token，GPU 计算资源用得更充分。</p>
<h2 id="dflash块扩散草稿比-chain-eagle-更容易命中">DFlash：块扩散草稿，比 Chain EAGLE 更容易命中</h2>
<p>主流投机解码方案是 EAGLE（及其 chain 版），草稿模型做自回归预测，每步大约能接受 3 个 token。<strong>DFlash（2026）</strong> 换了个思路：用<strong>块扩散（block diffusion）</strong> 做草稿——一个 5 层非因果的去噪网络，同时预测多个位置，而不是逐个生成。</p>
<p>效果如何？看数字：</p>
<table>
  <thead>
      <tr>
          <th>任务</th>
          <th style="text-align: center">AR 基线（tok/s）</th>
          <th style="text-align: center">DFlash+DDTree（tok/s）</th>
          <th style="text-align: center">加速比</th>
          <th style="text-align: center">平均接受长度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HumanEval</td>
          <td style="text-align: center">37.78</td>
          <td style="text-align: center"><strong>129.52</strong></td>
          <td style="text-align: center"><strong>3.43×</strong></td>
          <td style="text-align: center">8.31</td>
      </tr>
      <tr>
          <td>Math500</td>
          <td style="text-align: center">37.71</td>
          <td style="text-align: center"><strong>110.51</strong></td>
          <td style="text-align: center"><strong>2.93×</strong></td>
          <td style="text-align: center">7.04</td>
      </tr>
      <tr>
          <td>GSM8K</td>
          <td style="text-align: center">37.65</td>
          <td style="text-align: center"><strong>96.15</strong></td>
          <td style="text-align: center"><strong>2.55×</strong></td>
          <td style="text-align: center">6.14</td>
      </tr>
  </tbody>
</table>
<p>AR 基线是 Qwen3.5-27B Q4_K_M 在 RTX 3090 上的原生速度，也是 llama.cpp、SGLang AWQ 等框架在同一硬件上的天花板。DFlash 把这个天花板一口气推到 3 倍以上——而且<strong>平均每次验证接受 8 个 token</strong>，比 EAGLE 的 ~3 高了将近两倍。</p>
<p>但这里有个工程问题：官方 DFlash 实现跑在 BF16 下，需要 60+ GB VRAM 的 B200 专业卡才能装下目标+草稿+验证树。消费级 GPU 想用，得从头移植。</p>
<h2 id="gguf-移植q4_k_m-是-24-gb-的最优解">GGUF 移植：Q4_K_M 是 24 GB 的最优解</h2>
<p>Lucebox 的贡献就是这个移植。他们选了 <strong>Q4_K_M 量化目标（~16 GB）+ BF16 草稿（~3.46 GB）+ DDTree 验证树（budget=22）</strong>，刚好能在 24 GB VRAM 里塞下整个推理链路。</p>
<p>GGUF 是 llama.cpp 的量化格式，在消费级 GPU 上生态最成熟。选择 ggml 作为运行时而非 libllama，是因为 ggml 有<strong>原生 Gated DeltaNet CUDA kernel</strong>，不需要额外改硬件抽象。</p>
<p>整个移植约 2000 行 C++/CUDA 代码，fork 了 llama.cpp 增加了三个 tree-mode 操作：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ggml_ssm_conv_tree</span>      <span class="c1">// SSM 卷积树结构
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">ggml_gated_delta_net_tree</span>        <span class="c1">// Gated DeltaNet 树验证
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">ggml_gated_delta_net_tree_persist</span> <span class="c1">// 持久化状态
</span></span></span></code></pre></div><p>硬编码了 Qwen3.5-27B + Qwen3.5-27B-DFlash 这一个模型组合，没有通用性——但消费级单卡跑 27B 规模，这个组合恰好是最有价值的一个。</p>
<h2 id="128k-context-怎么塞进去">128K context 怎么塞进去</h2>
<p>原生 DFlash 在 128K 上下文时会爆显存，因为 KV cache 太大。Lucebox 的解法是<strong>Q4_0 KV cache + 滑动 target_feat ring</strong>（4096 槽位）：</p>
<ul>
<li>Q4_0 比 BF16 省 8 倍显存</li>
<li>Sliding window 限制历史 KV 长度</li>
<li>target_feat 做 ring buffer，超长 prompt 自动驱逐旧状态</li>
</ul>
<p>代价是 Acceptance Length 约下降 3%，但换来了<strong>128K context 稳定在 24 GB 内</strong>，128K 模式下仍能跑出 ~135 tok/s。这对需要超长上下文的应用（代码库分析、长文档对话）是实打实的突破。</p>
<h2 id="关键洞察消费级-gpu-的-llm-推理还没到头">关键洞察：消费级 GPU 的 LLM 推理还没到头</h2>
<p>看完 Lucebox 的实现，有几个工程结论值得关注：</p>
<p><strong>1. 量化不是终点，算法才是</strong></p>
<p>Q4_K_M 已经把 27B 压到 16 GB，这个路径的边际收益越来越小。但在 Q4_K_M 基础上加 DFlash，能在不降低模型质量的前提下再快 3 倍——这说明解码算法的优化空间远没有到头。下一个突破点很可能是<strong>草稿模型和目标模型的协同训练</strong>，而不是继续压缩精度。</p>
<p><strong>2. GGUF 生态正在变厚</strong></p>
<p>Llama.cpp 的 GGUF 量化格式原本是&quot;省显存&quot;的妥协方案，但随着 ggml 支持更多的 CUDA kernel（SSM、Gated DeltaNet），它在某些场景下已经不只是&quot;能用&quot;，而是&quot;最优解&quot;。这对想在消费级硬件上做推理优化的开发者是好消息——不需要自己写 CUDA kernel，现成的生态已经能跑起来。</p>
<p><strong>3. 单卡 27B 的实用边界在拓宽</strong></p>
<p>207 tok/s 意味着什么？实际体验大概是：每秒能吐出大约 150-200 个中文词，或者 300-400 个英文词。这个速度已经能支持<strong>实时交互式 AI 助手</strong>——不是等几秒才回一个字，而是几乎感知不到延迟的流式响应。加上 128K 上下文，单卡 27B 能做的事比去年这个时候多了很多。</p>
<h2 id="快速上手">快速上手</h2>
<p>项目在 GitHub，clone 下来大概需要知道这几步：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 1. 克隆（含 submodule）</span>
</span></span><span class="line"><span class="cl">git clone --recurse-submodules https://github.com/Luce-Org/lucebox-hub
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> lucebox-hub/dflash
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. 编译（CUDA 12+, RTX 3090/sm_86）</span>
</span></span><span class="line"><span class="cl">cmake -B build -S . -DCMAKE_CUDA_ARCHITECTURES<span class="o">=</span><span class="m">86</span> -DCMAKE_BUILD_TYPE<span class="o">=</span>Release
</span></span><span class="line"><span class="cl">cmake --build build --target test_dflash -j
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. 下载模型（约 20 GB）</span>
</span></span><span class="line"><span class="cl">huggingface-cli download unsloth/Qwen3.5-27B-GGUF Qwen3.5-27B-Q4_K_M.gguf --local-dir models/
</span></span><span class="line"><span class="cl">huggingface-cli download z-lab/Qwen3.5-27B-DFlash model.safetensors --local-dir models/draft/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 4. 运行</span>
</span></span><span class="line"><span class="cl">python3 scripts/run.py --prompt <span class="s2">&#34;def fibonacci(n):&#34;</span>
</span></span></code></pre></div><p>完整的 benchmark 结果在 <a href="https://github.com/Luce-Org/lucebox-hub/tree/main/dflash/RESULTS.md">RESULTS.md</a>，包括不同模型、不同 context 长度下的吞吐和内存数据。</p>
<h2 id="信源">信源</h2>
<ul>
<li>Lucebox DFlash 实现：https://github.com/Luce-Org/lucebox-hub</li>
<li>DFlash 论文：https://arxiv.org/abs/2602.06036</li>
<li>DDTree 论文：https://arxiv.org/abs/2604.12989</li>
<li>Lucebox 官方博客：https://lucebox.com/blog/dflash27b</li>
<li>Qwen3.5-27B GGUF 量化模型：https://huggingface.co/unsloth/Qwen3.5-27B-GGUF</li>
<li>Qwen3.5-27B-DFlash 草稿模型：https://huggingface.co/z-lab/Qwen3.5-27B-DFlash</li>
</ul>
]]></content:encoded></item><item><title>本地 LLM 推理：为什么我不推荐 Ollama，以及真正值得用的开源替代</title><link>https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/</link><pubDate>Fri, 17 Apr 2026 10:15:32 +0800</pubDate><guid>https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/</guid><description>Ollama 是最流行的本地 LLM 推理工具，但它的问题被社区诟病已久。本文从许可证归属、性能差距、供应商锁定三个维度深度解析 Ollama 的历史问题，并给出 llama.cpp、LM Studio、Jan 等经过验证的开源替代方案实测对比。</description><content:encoded><![CDATA[<h2 id="引言一个只修皮毛的工具为什么获得-16-万星">引言：一个「只修皮毛」的工具为什么获得 16 万星</h2>
<p>2023 年，Ollama 以「Docker for LLMs」的定位进入开发者视野——一行命令下载模型，本地跑起来。这种低门槛让它迅速积累了 <a href="https://github.com/ollama/ollama">16.9 万 GitHub Stars</a>，成为本地运行大模型的事实标准。</p>
<p>然而，它的底层问题正在被更多开发者意识到：许可证归属争议长达一年未处理、自研后端性能反而低于 llama.cpp 30-50%、模型格式产生供应商锁定……这些问题在 Hacker News 上引发了大量讨论，<a href="https://news.ycombinator.com/item?id=47772725">HN 热帖</a>当天获得 603 分。</p>
<p>本文不是「二选一」的观点稿，而是一次基于事实的深度拆解——<strong>为什么 Ollama 的工程实践存在系统性缺陷，以及真正值得投入生产的替代方案是什么</strong>。</p>
<hr>
<h2 id="背景llamacpp-才是本地-llm-的真正引擎">背景：llama.cpp 才是本地 LLM 的真正引擎</h2>
<p>要理解 Ollama 的问题，先要了解它依赖的底层技术。</p>
<p><a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a> 由 Georgi Gerganov 于 2023 年 3 月用一个晚间编写，最初只是一个将 LLaMA 模型跑在消费级硬件上的 C++ 推理引擎。它的核心创新是 <strong>GGUF 量化格式</strong>——让数十亿参数的大模型能够在普通电脑的 CPU 和 GPU 上高效运行。</p>
<p>今天，llama.cpp 拥有：</p>
<ul>
<li><strong>104,116 Stars</strong>，450+ 贡献者</li>
<li>MIT 许可证，完全开源</li>
<li>2026 年 2 月，ggml.ai 项目并入 Hugging Face，确保长期可持续发展</li>
</ul>
<p>可以说，没有 llama.cpp，就没有本地 LLM 生态的今天。</p>
<p><strong>问题是：Ollama 几乎从未承认这一点。</strong></p>
<hr>
<h2 id="问题一长达-400-天的许可证争议">问题一：长达 400 天的许可证争议</h2>
<p>Ollama 于 2023 年 6 月公开，基于 MIT 许可证开源。然而，其二进制发布包中包含 llama.cpp 代码，却<strong>从未附带 llama.cpp 要求的版权声明</strong>——这是 MIT 许可证的唯一主要义务。</p>
<p>社区在 2024 年 3 月提交了 <a href="https://github.com/ollama/ollama/issues/3185">GitHub Issue #3185</a>，明确指出这一问题。<strong>Ollama 团队 400 多天没有任何回应</strong>。</p>
<p>直到 2024 年 4 月，社区成员主动提交了 PR 直接添加归属声明，Ollama 才在 README 底部加了一行小字：</p>
<blockquote>
<p>&ldquo;llama.cpp project founded by Georgi Gerganov&rdquo;</p></blockquote>
<p>而官方 PR 的回复更能说明问题：</p>
<blockquote>
<p>&ldquo;We spend a large chunk of time fixing and patching it up to ensure a smooth experience for Ollama users… Overtime, we will be transitioning to more systematically built engines.&rdquo;</p></blockquote>
<p>翻译：他们不打算给 llama.cpp 显式 credited，还要逐步替换掉它。</p>
<hr>
<h2 id="问题二自研后端导致性能反而下降-30-70">问题二：自研后端导致性能反而下降 30-70%</h2>
<p>Ollama 真的做到了「更稳定的体验」吗？社区基准测试给出了截然不同的答案。</p>
<h3 id="性能测试数据来自多篇社区对比评测">性能测试数据（来自多篇社区对比评测）</h3>
<table>
  <thead>
      <tr>
          <th>测试场景</th>
          <th>llama.cpp</th>
          <th>Ollama</th>
          <th>差距</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPU 推理（相同硬件，Qwen-3 Coder 32B）</td>
          <td>161 tokens/s</td>
          <td>89 tokens/s</td>
          <td><strong>Ollama 慢 44%</strong></td>
      </tr>
      <tr>
          <td>CPU 推理</td>
          <td>基准值</td>
          <td>低于基准 30-50%</td>
          <td><strong>Ollama 慢 30-50%</strong></td>
      </tr>
      <tr>
          <td>Qwen-3 Coder 32B 吞吐量</td>
          <td>~70% 更高</td>
          <td>基准</td>
          <td><strong>llama.cpp 胜出</strong></td>
      </tr>
  </tbody>
</table>
<p>性能差距的根源在于 Ollama 2025 年中做出的一次关键决策——<strong>放弃直接使用 llama.cpp，转而基于 ggml 底层库自建推理后端</strong>。</p>
<p>Ollama 官方理由是「llama.cpp 变动太快，企业用户需要稳定性」。然而实际结果截然相反：</p>
<ul>
<li><strong>结构化输出（structured output）支持损坏</strong></li>
<li><strong>视觉模型（vision model）失效</strong></li>
<li><strong>GGML assertion 崩溃</strong>，在 llama.cpp 早已修复的版本中重现</li>
<li><strong>GPT-OSS 20B 新版模型不支持</strong>所需的新 tensor 类型</li>
</ul>
<p>llama.cpp 作者 Georgi Gerganov 本人确认：Ollama 分叉并对 GGML 做了破坏性修改。</p>
<hr>
<h2 id="问题三供应商锁定的模型格式">问题三：供应商锁定的模型格式</h2>
<p>Ollama 下载的模型以<strong>哈希文件名存储在自己的格式中</strong>，无法被 llama.cpp、LM Studio 或其他 GGUF 工具直接使用。</p>
<p>用户如果想把在 Ollama 中下载的模型迁移到 llama.cpp，需要额外工作。这与「开放」的开源理念背道而驰——你下载的模型，实际上不是你的。</p>
<p>相比之下，llama.cpp 的模型文件（GGUF 格式）是真正的开放标准，任何支持 GGUF 的工具都可以使用。</p>
<hr>
<h2 id="问题四误导性的模型命名">问题四：误导性的模型命名</h2>
<p>当 DeepSeek 在 2025 年 1 月发布 R1 模型族时，Ollama 做了一个微妙的操作：</p>
<p>将 <strong>DeepSeek-R1-Distill-Qwen-32B</strong>（由 Qwen 微调而来的蒸馏版本）直接在库中和 CLI 中标记为「DeepSeek-R1」。</p>
<p>实际运行效果与真正的 6710 亿参数 R1 天差地别，但下载量因为「DeepSeek-R1」这个标题暴涨。</p>
<p>GitHub Issues <a href="https://github.com/ollama/ollama/issues/8557">#8557</a> 和 <a href="https://github.com/ollama/ollama/issues/8698">#8698</a> 明确请求区分命名，两个 issue 均被关闭，<strong>没有修复</strong>。</p>
<p>直到今天，<code>ollama run deepseek-r1</code> 运行的仍然是小模型蒸馏版本。</p>
<hr>
<h2 id="问题五2025-年-7-月的闭源-gui-应用">问题五：2025 年 7 月的闭源 GUI 应用</h2>
<p>2025 年 7 月，Ollama 发布了 macOS 和 Windows 的 GUI 桌面应用，但：</p>
<ul>
<li>代码在<strong>私有仓库</strong>开发（github.com/ollama/app）</li>
<li><strong>没有开源许可证</strong></li>
<li>二进制包中包含疑似 AGPL-3.0 依赖</li>
<li>下载页面把开源 MIT 链接放在旁边，给用户「这是开源工具」的印象</li>
</ul>
<p>这是一个以开源闻名、享受社区红利的项目，在关键时刻选择关闭源代码。</p>
<hr>
<h2 id="真正的替代方案开源本地-llm-推理工具横评">真正的替代方案：开源本地 LLM 推理工具横评</h2>
<table>
  <thead>
      <tr>
          <th>工具</th>
          <th>底层引擎</th>
          <th>许可证</th>
          <th>GUI</th>
          <th>特色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong><a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a></strong></td>
          <td>原生</td>
          <td>MIT</td>
          <td>可选（llama-server）</td>
          <td>性能最优，生态最广</td>
      </tr>
      <tr>
          <td><strong><a href="https://lmstudio.ai/">LM Studio</a></strong></td>
          <td>llama.cpp</td>
          <td>专有（免费）</td>
          <td>✅</td>
          <td>图形界面完整，可视化调参</td>
      </tr>
      <tr>
          <td><strong><a href="https://jan.ai/">Jan</a></strong></td>
          <td>llama.cpp</td>
          <td>AGPL</td>
          <td>✅</td>
          <td>开源，local-first 设计</td>
      </tr>
      <tr>
          <td><strong><a href="https://github.com/LostRuins/koboldcpp">koboldcpp</a></strong></td>
          <td>llama.cpp</td>
          <td>AGPL</td>
          <td>✅</td>
          <td>Web UI，配置选项丰富</td>
      </tr>
      <tr>
          <td><strong><a href="https://github.com/containers/ramalama">ramalama</a></strong></td>
          <td>多引擎</td>
          <td>APL 2.0</td>
          <td>CLI</td>
          <td>容器化，明确注明上游依赖</td>
      </tr>
      <tr>
          <td><strong><a href="https://github.com/BerriAI/litellm">LiteLLM</a></strong></td>
          <td>多后端</td>
          <td>MIT</td>
          <td>代理层</td>
          <td>OpenAI 兼容 API，统一路由</td>
      </tr>
      <tr>
          <td><strong><a href="https://github.com/ggml-org/llama.cpp">llama-swap</a></strong></td>
          <td>llama.cpp</td>
          <td>MIT</td>
          <td>—</td>
          <td>多模型编排，热加载</td>
      </tr>
  </tbody>
</table>
<p>这些工具设置起来并不复杂。llama.cpp 官方提供 <code>llama-server</code>，自带 OpenAI 兼容 API 和 Web UI，配置上下文窗口和采样参数完全可控。</p>
<hr>
<h2 id="工程实践建议">工程实践建议</h2>
<h3 id="1-如果你追求最高性能直接用-llamacpp">1. 如果你追求<strong>最高性能</strong>：直接用 llama.cpp</h3>
<p>llama.cpp 在所有硬件配置下都明显领先。它 2026 年 2 月并入 Hugging Face，生态有长期保障。</p>
<h3 id="2-如果你需要图形界面lm-studio-或-jan">2. 如果你需要<strong>图形界面</strong>：LM Studio 或 Jan</h3>
<p>LM Studio 提供完整的可视化调参界面，适合不想写命令行的场景。Jan 是 AGPL 开源替代，隐私优先设计。</p>
<h3 id="3-如果你需要多模型统一管理llama-swap--litellm">3. 如果你需要<strong>多模型统一管理</strong>：llama-swap + LiteLLM</h3>
<p>llama-swap 支持多模型热加载和动态切换，配合 LiteLLM 可以做统一的 OpenAI 兼容代理，按模型自动路由到不同后端。</p>
<h3 id="4-永远不要把模型文件锁在单一工具里">4. 永远不要把模型文件锁在单一工具里</h3>
<p>使用 GGUF 格式存储模型，任何工具都能读取。避免 Ollama 的哈希文件名格式——它会让你日后迁移困难。</p>
<hr>
<h2 id="结论">结论</h2>
<p>Ollama 的核心问题是<strong>工程激励与开源社区期望的根本错位</strong>：一边享受开源社区对 llama.cpp 的依赖带来的流量，一边拒绝透明承认这种依赖；在性能上自研后端反而开倒车；在许可证上绕过 MIT 要求；在产品上发布闭源应用。</p>
<p>真正值得关注的是 <strong>llama.cpp 生态本身</strong>——它才是本地 LLM 推理的根基，性能领先、许可证清晰、社区驱动。所有「llama.cpp 替代品」中，最值得投入的是直接使用 llama.cpp，或者在其基础上做用户体验封装的 LM Studio 和 Jan。</p>
<hr>
<h2 id="信源">信源</h2>
<ul>
<li><a href="https://news.ycombinator.com/item?id=47772725">Hacker News 讨论：The local LLM ecosystem doesn&rsquo;t need Ollama</a></li>
<li><a href="https://github.com/ollama/ollama/issues/3185">Ollama GitHub：Issue #3185 - 许可证归属争议</a></li>
<li><a href="https://github.com/ollama/ollama/issues/8557">Ollama GitHub：Issue #8557/#8698 - DeepSeek 命名误导</a></li>
<li><a href="https://github.com/ggml-org/llama.cpp">llama.cpp GitHub（ggml-org）</a> - 104,116 Stars，MIT 许可证</li>
<li><a href="https://github.com/ollama/ollama">Ollama GitHub</a> - 169,199 Stars，MIT 许可证</li>
<li><a href="https://lmstudio.ai/">LM Studio</a></li>
<li><a href="https://jan.ai/">Jan</a></li>
<li><a href="https://github.com/LostRuins/koboldcpp">koboldcpp GitHub</a></li>
<li><a href="https://github.com/containers/ramalama">ramalama GitHub</a></li>
<li><a href="https://github.com/BerriAI/litellm">LiteLLM GitHub</a></li>
</ul>
]]></content:encoded></item></channel></rss>