技术速递|边缘 AI 的 Token 经济学:基于 WinML CLI 在 Windows NPU 上运行 Qwen3
作者:卢建晖 - 微软高级云技术布道师
排版:Alan Wang
改变对话的那个数字
大多数关于“本地运行大语言模型”的教程,都会从模型本身讲起。而这篇文章,将从一张账单开始。
云端大模型生成的每一个 Token 都需要计费。单次请求的成本或许微不足道,但智能体从来不会只发起一次请求——它们会不断循环调用、反复重试,并在每一天为每一位用户执行成千上万次请求。一个成功 AI 功能的成本曲线并不是平缓的,而是会随着用户规模的增长不断上升。让产品变得受欢迎的因素,往往也是让它变得昂贵的原因。
这正是 Token 经济学背后那个令人无法回避的现实:在云端,智能的边际成本永远不会降为零。只要功能还在运行,你就需要按照 Token 数量持续为智能付费。
而边缘侧推理则彻底改变了这个公式。当模型运行在用户已经拥有的硬件设备上时,下一个 Token 的边际成本会逐渐趋近于零。你只需为硬件——也就是芯片——支付一次固定成本,之后便可以持续生成任意数量的 Token。
对于聊天助手、文本摘要、分类器、设备端 Copilot 等一大类应用场景而言,这意味着一种从根本上不同的成本模型。也正因如此,“推理究竟应该运行在哪里”正悄然成为今年最重要的架构决策之一。
为了让这些概念更加具体,本文将围绕一个真实可运行的开源项目展开:kinfey/winml-qwen3-chat。该项目基于 Windows ML CLI,将 Qwen3-0.6B部署到 Windows NPU 上运行,并与 CPU 推理进行性能对比测试,同时提供一个桌面聊天应用,实现逐 Token 流式输出的完整体验。
为什么选择边缘侧,而不仅仅是为了节省成本
成本是最容易被看到的优势,但这并不是全部。当推理从云端迁移到设备本地时,你实际上一次性获得了四项关键收益:
-
成本。 每个新增 Token 的边际成本趋近于零。无需按请求计费,也不会因为某个功能突然爆火而收到意料之外的云服务账单。
-
延迟。 无需经过网络往返。模型距离应用只有一次函数调用的距离,而不再是一次 HTTPS 请求的距离。对于交互式聊天场景而言,这正是“响应迅速”和“加载转圈”之间的区别。
-
隐私。 提示词和数据始终保留在本地设备上。对于受监管数据、个人文档,或者任何用户不愿上传到公共云端的信息来说,“数据从未离开这台电脑”是能够提供的最强隐私保障。
-
可用性。 即使在飞机上、隧道中、企业防火墙后,甚至云服务发生故障时,应用依然能够正常运行。离线不再是一种降级模式,而是默认运行模式。
然而,长期以来的难点在于:**CPU 并不擅长这项工作。**通用 CPU 执行 Transformer 模型前向推理不仅速度较慢,而且延迟波动明显。当操作系统不断调度核心资源时,推理时间也会随之抖动。这正是专用 AI 芯片登场的原因。
NPU:为模型推理而生的处理器
现代 AI PC 通常拥有三类计算单元,而 Windows ML 为它们分别提供了对应的执行提供程序:
| 计算单元 | 参考硬件(Snapdragon X Elite) | 执行提供程序 |
|---|---|---|
| NPU | Qualcomm Hexagon NPU(X1E80100) | QNNExecutionProvider |
| GPU | Qualcomm Adreno X1-85 | DmlExecutionProvider |
| CPU | Snapdragon X 12 核 @ 3.40 GHz | CPUExecutionProvider |
NPU(Neural Processing Unit,神经网络处理器)并不是“更快的 CPU”。它是一种完全不同类型的处理器,专门为一个任务而设计:执行模型推理过程中大量且重复的矩阵乘法运算。CPU 是一个能力全面的通才,而 NPU 则是高度专业化的专家。它能够以更高吞吐量、更低功耗,以及更稳定的性能完成 Transformer 模型所需的计算任务。
而最后这一点——稳定性——往往比人们想象得更加重要。对于交互式 AI 助手而言,可预测的响应时间往往比极限性能更有价值。持续稳定地在约 1 秒内返回结果,通常比平均耗时 0.8 秒但偶尔卡顿 5 秒的体验更好。在后续基准测试中我们将看到这一点:NPU 不仅比 CPU 更快,而且在响应稳定性方面领先一个数量级。
此外,NPU 的能耗也远低于 CPU。与让 12 个 CPU 核心持续满载运行相比,使用 Hexagon NPU 执行推理意味着:风扇保持安静,设备温度更低,电池续航时间更长。而对于一个始终在线的本地 AI Copilot 来说,这正是其存在的意义。
WinML CLI:从模型源码到硬件优化产物
关于 NPU,人们常常忽略一个关键事实:Hugging Face 上下载的模型并不能直接运行在 NPU 上。你无法直接把一个 model.safetensors 文件交给 Hexagon NPU,然后期待它开始生成 Token。在“PyTorch 权重文件”与“真正运行在 NPU 上”之间,还隔着一条完整的工程化流水线:导出为 ONNX 格式、图优化、量化、编译为厂商专用上下文二进制文件。
而这正是 Windows ML CLI 的价值所在。正如官方描述的那样:
它能够将来自 Hugging Face 或自定义训练流程的源模型,通过可重复的工作流转换为面向特定硬件优化的部署产物。
整个过程自动完成模型转换、图优化、模型编译,并支持 AMD、Intel、NVIDIA 与 Qualcomm 等多种硬件平台。开发者既可以手动控制整个流程:export → analyze → optimize → quantize → compile,也可以直接使用 winml build 自动生成完整配置并完成构建。更重要的是,同一套命令能够面向所有 Windows ML Execution Provider 工作。这意味着:一次构建,多种硬件运行。
WinML CLI 本质上是一个通过 Python Wheel 安装的命令行工具,可以轻松集成到 CI/CD 流程中。也正因为如此,边缘 AI 部署终于从一次性的实验项目,演进为可复现、可自动化、可规模化交付的工程实践。
实战演练:为 NPU 构建 Qwen3-0.6B
这一部分是 winml-qwen3-chat 项目的核心内容。整个流程可以概括为五个步骤:安装 → 检查 → 构建 → 性能测试 → 应用运行。
0. 环境准备
本项目在以下环境中完成验证:
-
Snapdragon X Elite(ARM64)设备
-
Windows 11 24H2(NPU 支持必需)
-
Python 3.11
-
uv 包管理工具
-
(用于示例应用).NET 10 SDK + WinUI Workload
1. 安装 WinML CLI
WinML CLI 已发布至 PyPI,可以通过 uv 创建独立环境并安装:
# Pin the exact Python the project needs
uv python install 3.11
# Create and activate a 3.11 virtual environment
uv venv --python 3.11 winml-env
.\winml-env\Scripts\activate
# Install the CLI from PyPI
uv pip install winml-cli
# Verify
winml --version # -> winml, version 0.1.0
然后让 CLI 对你的机器进行自检——这是你的第一次“健全性检查”,用来确认 NPU 是否真的可见:
winml sys
在参考设备上,这个命令会按优先级枚举所有三类计算单元(NPU → GPU → CPU),以及它们背后的执行提供程序(QNNExecutionProvider、DmlExecutionProvider、CPUExecutionProvider)。如果这里没有出现 NPU,那么后续任何流程都无法使用它——因此,winml sys 就是你进行问题诊断的起点。
2. 构建前先检查模型
💡 **在执行构建之前,务必先执行 Inspect。**这样可以在几秒钟内发现模型架构是否受支持,而不必等到导出流程运行了二十分钟后才发现构建失败。
winml inspect -m Qwen/Qwen3-0.6B
对于 Qwen3-0.6B,inspect 命令会展示即将构建模型的基本信息:这是一个文本生成模型,对应 WinML 中的 WinMLModelForCausalLM(Composite) 类;模型架构为 Qwen3ForCausalLM,包含 28 层,隐藏层维度为 1024,词表大小为 151,936,使用 ONNX Opset 17。其输入包括 input_ids、attention_mask 和 position_ids,输出则为 logits。
这里有一个值得尽早理解的重要细节:Qwen3 是一个组合式模型。在导出过程中,它不会被转换为单个 ONNX 计算图,而是会导出为多个相互关联的 ONNX 组件。这一设计细节在后续量化阶段会变得尤为重要——事实上,后面遇到的一些量化问题,正是由这种组合式结构所带来的。不过换个角度看,也正是这些问题帮助我们更深入地理解了模型部署链路中的关键环节。
3. 为 NPU 构建模型
下面这条命令完成整个核心构建流程:
winml build -m Qwen/Qwen3-0.6B -o output\qwen3-0.6b --ep qnn --device npu --compile -v
该命令会自动执行:Export、Optimize、Quantize、Compile全部针对 QNN Execution Provider 和 NPU 目标平台。
底层运行分为四个阶段。以参考设备为例:
| 阶段 | 时间 | 输出 |
|---|---|---|
| Export | 133.2 秒 | export.onnx(2.9GB) |
| Optimize | 157.6 秒 | optimized.onnx(2.9GB) |
| Quantize | 227.6 秒 | quantized.onnx(868MB) |
| Compile | 437.8 秒 | compiled_qnn.bin(913MB) |
| 总计 | 1191.5 秒(约20分钟) | model.onnx |
这四个阶段串联起来,实际上浓缩了边缘 AI 部署的完整故事:一个 2.9GB 的浮点精度模型,首先被量化压缩至 868MB——转换为更适合 NPU 执行的整数精度表示;随后再被编译为 Qualcomm HTP Context Binary,即 Hexagon NPU 能够直接执行的计算图。最终生成的部署产物是:output\qwen3-0.6b\model.onnx。它并不是一个普通的 ONNX 模型,而是一个组合式入口图,用于指向已经编译完成的 NPU Context。需要说明的是,构建过程中产生的大约 9GB .onnx.data 中间文件,在构建完成后都可以安全删除,以回收磁盘空间。
不过,项目文档也坦诚地指出了一个当前存在的限制:由于文本生成任务尚未被纳入 WinML CLI 内置的校准任务列表,因此在量化阶段,工具会退回使用 RandomDataset(随机数据集) 来完成校准。对于以延迟测试为目标的性能基准来说,这种做法是合理且无害的;但如果目标是生产环境中的模型质量和生成效果,这就会成为一个需要额外处理的问题。事实上,这正是示例应用后续需要专门修复和优化的关键环节。
4. 性能测试:NPU vs CPU
使用 WinML CLI 的 perf 命令测试模型性能:
# NPU (QNN) — runs the compiled context
winml perf -m output\qwen3-0.6b\model.onnx --task text-generation --ep qnn --device npu --iterations 100 --warmup 10
# CPU — the compiled NPU graph can't run on CPU, so benchmark the
# pre-compile quantized.onnx (QDQ) instead
winml perf -m output\qwen3-0.6b\quantized.onnx --task text-generation --ep cpu --device cpu --iterations 50 --warmup 5
测试结果,序列长度 1024 的完整 Prefill Forward Pass:
| 设备 | EP | 精度 | 平均延迟 | 吞吐量 | 标准差 |
|---|---|---|---|---|---|
| NPU | QNN | w16a16 | 960.8 ms | 1.04 samples/s | 3.4 ms |
| CPU | CPU | w8a16 | 5793.3 ms | 0.17 samples/s | 828.3 ms |
这里有两个关键结论,而第二个结论尤其值得关注:
-
在这一测试场景下,NPU 的推理速度约为 CPU 的 6 倍。
-
NPU 的性能稳定性约为 CPU 的 240 倍——其延迟标准差仅为 3.4 毫秒,而 CPU 高达 828 毫秒。CPU 的推理延迟在不同运行之间可能波动接近整整 1 秒,而 NPU 几乎每次都能在相同时间内完成推理。对于交互式聊天应用而言,这种稳定性本身就是一种核心能力。
这正是 Token 经济学在现实世界中的具体体现:同一个模型,运行在用户已经拥有的硬件设备上,以接近零的 Token 边际成本提供接近云端服务级别的交互体验,而且其响应时间甚至比 CPU 方案更加稳定、可预测。换句话说,边缘 AI 的价值不仅在于更低的成本,更在于能够以更稳定的方式交付高质量的用户体验。
5. 从模型到应用
仅仅拥有一个编译完成的 .onnx 模型,并不意味着已经拥有了一个可交付的产品。为了弥合从“模型”到“应用”之间的差距,winml-qwen3-chat 项目提供了一个完整的桌面应用示例,并直接基于前面构建的 NPU 模型运行:
-
app/WinMLChat/一个基于 WinUI 3(C# / .NET 10 / MVVM)的聊天界面应用。它支持 Token Streaming(逐 Token 流式输出),能够像 ChatGPT 一样实时展示生成内容,从而将 NPU 低延迟且稳定的推理能力直接转化为流畅自然的“打字机式”交互体验。 -
backend/一个基于 FastAPI 构建的后端服务。它对外提供与 OpenAI API 兼容的流式接口,而底层模型加载与推理则由winml.modelkit.WinMLAutoModel驱动。
整个项目中最值得关注的设计之一位于后端:混合式 NPU / CPU 路由。对于较短的 Prompt,请求会优先路由到经过量化的 NPU 模型,以获得更高的推理速度和更低的功耗;而对于较长的 Prompt,则会自动切换到未量化的 CPU 推理路径,以支持更长的上下文长度。从概念上看,其路由逻辑类似于:
# Illustrative — the backend picks an execution path per request
def choose_backend(prompt_tokens: int):
if prompt_tokens <= NPU_PREFILL_LIMIT:
return npu_model # quantized w16a16, QNN -> fast, low-power
return cpu_model # unquantized fallback -> handles long context
由于后端 API 采用了 OpenAI 兼容的流式接口协议,因此 WinUI 前端(以及任何兼容 OpenAI API 的客户端)都能够直接接入,而无需编写额外的适配层。换句话说,NPU 的存在被隐藏在一个开发者熟悉的 /chat/completions 接口之下,应用层无需关心底层究竟运行在 CPU、GPU 还是 NPU 上。
面向生产环境的关键挑战:为组合式 Decoder 修复量化流程
还记得前面提到的 RandomDataset 校准警告 吗?这其实正是“能够完成性能测试”和“能够交付生产应用”之间的一条真实分界线,而项目也选择正面解决这一问题。
WinML CLI 0.1.0 目前还无法开箱即用地完成 Qwen3 组合式 Decoder 在 QNN 平台上的量化。其默认的校准数据读取器遗漏了 position_ids 以及 28 层 Decoder 所需的 Past KV(Key/Value Cache)输入,因此量化阶段使用的校准数据与模型实际运行时接收到的数据并不一致。示例项目通过 backend/winml_npu_patch.py 从根本上修复了这一问题,具体包括:
-
提供真实的 KV Cache 校准数据,即 Decoder 实际需要的
position_ids以及每一层对应的 Past Key/Value Tensor; -
改用 Per-Channel W16A16 量化方案,并将
lm_head排除在量化范围之外。
这正是“性能测试表现良好的模型”和“实际生成效果优秀的模型”之间的区别所在:真正有效的量化,需要基于具有代表性的真实输入进行校准,而不是随机生成的数据;同时,对于像输出投影层(lm_head)这样对精度高度敏感的模块,需要保留更高精度,以确保生成 Token 的质量不会受到明显影响。
仍有待完善之处
如果在这里就开始庆祝成功,那未免有些言过其实。毕竟这项工作仍处于早期阶段,而这一点也体现在许多细节之中。
-
Qwen3-0.6B——以及当前大多数小参数大语言模型——单独使用时仍然存在明显局限。 0.6B 参数规模非常适合作为验证整条部署链路的技术样例,但其推理能力相对有限。对于许多真实业务场景,你可能仍然需要更大规模的本地模型、检索增强(Retrieval)能力,或者边缘与云端协同的混合架构。某种程度上,可以说硬件已经准备好了,而小模型的能力仍在持续追赶。
-
性能和优化方面同样还有提升空间。 虽然当前的构建流程已经能够完整跑通,但仍存在一些需要进一步打磨的地方:文本生成任务的量化校准仍会退回使用 RandomDataset;组合式 Decoder 仍需要额外编写补丁才能正确完成量化;winml-cli 0.1.0 尚不支持算子级性能分析(–op-tracing);而本文展示的吞吐量数据也只是一个起点,而非性能上限。后续仍有大量值得探索和调优的空间。
不过,这些问题并不是等待观望的理由,恰恰相反,它们正是参与进来的理由。整个工具链是开源的,而且发展速度很快。推动其成熟最快的方式,不是等待它变得完美,而是在真实场景中使用它、测试它,并反馈实际遇到的问题。
如果你发现了 Bug、遇到了限制,或者有新的想法,欢迎前往 github.com/microsoft/winml-cli/issues 提交 Issue。来自真实构建和真实应用场景的反馈,正是帮助这些工具不断完善的重要动力。
总结
边缘 AI 值得关注的原因并不在于“新奇”,而在于经济规律和物理规律恰好指向了同一个方向。
-
从 Token 经济学的角度来看,云端推理的每个 Token 都需要持续计费,其边际成本永远无法降为零;而边缘推理则通过一次性的硬件投入,让后续 Token 的边际成本不断趋近于零。对于高频调用、交互密集以及隐私敏感的工作负载而言,这并非微不足道的成本优化,而是一种结构性的优势。
-
NPU 则是让这一模式真正可行的关键硬件。它专为 Transformer 模型的前向推理而设计,在本文的测试中,以远低于 CPU 的功耗,实现了约 6 倍于 CPU 的推理性能,以及约 240 倍于 CPU 的稳定性。
-
WinML CLI 则充当了连接模型与硬件之间的桥梁。它通过一条可重复、可自动化的流程——Inspect → Build → Perf——将 Hugging Face 模型转换为面向特定硬件优化的部署产物,并支持 Windows ML 的所有 Execution Provider。
-
而 winml-qwen3-chat 则将这一切串联起来:一个真实运行在 NPU 上的 Qwen3-0.6B 部署案例、一份客观透明的性能基准测试、一个支持流式输出的 WinUI 聊天应用、一个兼容 OpenAI API 的混合路由后端,以及——最具启发意义的——一个展示如何从“能够运行”走向“能够交付”的量化修复实践。
对于开发者而言,最值得关注的结论是:**推理运行在哪里,已经不再是一个部署细节,而是一项架构决策。**当你的工作负载具有高调用频率、低延迟要求或严格隐私约束时,答案越来越可能不是继续增加云服务预算,而是充分利用用户设备中已经存在的 NPU。而今天,通往这一目标的工具链已经准备就绪。
从这里开始
-
Sample Code:kinfey/winml-qwen3-chat
-
WinML CLI:microsoft/winml-cli
更多推荐



所有评论(0)