从 LLaMA-Factory 微调到高通 NPU 部署: Qwen-0.6B 全链路移植指南

前言

在大模型端侧化部署的趋势下,如何将微调后的 LLM 跑在手机 NPU 上是很多开发者的痛点。本文将手把手教你如何将使用 LLaMA-Factory 微调后的 Qwen-0.6B 模型,一步步移植到高通(Qualcomm)骁龙平台的 NPU 上,实现低功耗、高速度的本地化推理。

一、 导出微调模型

首先,在 LLaMA-Factory 界面中选择好微调后的检查点(Checkpoint),填写导出路径,点击 “开始导出”

[图片]

导出成功后,你会在目录下看到如下文件:

  • model.safetensors(模型权重)
  • config.json(模型配置)
  • tokenizer.json 等(分词器相关)

要将微调后的 Qwen-0.6B 模型移植到高通 NPU,第一步就是格式转换。safetensors 是目前 Hugging Face 推崇的安全权重格式,而 ONNX 则是进入高通工具链(QNN/SNPE)的通用门票。
以下是详细的操作步骤

二、 格式转换:从 Safetensors 到 ONNX

1. 转换为 PyTorch 权重

由于部分旧版转换工具不支持 safetensors,建议先将其转回标准的 pytorch_model.bin

import torch from safetensors.torch import load_file # 1. 路径设置 safetensors_path ="./qwen0_6b/model.safetensors" pytorch_bin_path ="./qwen0_6b/pytorch_model.bin"# 2. 加载并保存 weights = load_file(safetensors_path) torch.save(weights, pytorch_bin_path)[cite_start]print(f"转换成功:{pytorch_bin_path}")[cite:42,43,44,46,51,54]

注意:转换后,请确保你的 config.json 中的 architectures 字段正确(对于 Qwen0.6B 通常是 Qwen2ForCausalLM)。

2. 使用 Optimum 导出 ONNX

导出 LLM 涉及复杂的 KV Cache 处理,强烈建议使用 Hugging Face 的 Optimum 库 。

安装工具:

[cite_start]pip install optimum[exporters] onnx onnxruntime [cite: 62]

执行导出:
针对 NPU 部署,必须开启 with past 模式以保证推理速度 。

optimum-cli export onnx \ --model ./qwen0_6b \ --task text-generation-with-past \ --trust-remote-code \[cite_start]./qwen_onnx_out/ [cite: 67, 69, 71, 73, 75]

输出结果:你会得到 decoder_model.onnxdecoder_with_past_model.onnx

注意:--task text-generation-with-past:这非常关键!这会生成两个模型,一个处理初始 Prompt,另一个利用 KV Cache 负责后续 Token 生成 。

三、 高通 NPU 关键优化(必看!)

高通 Hexagon NPU 对算子有特定要求,进入工具链前需完成以下优化:

  1. Opset 版本: 建议使用 Opset 17 或更高版本 。如果 optimum 默认导出较低,可以指定:
--opset 17
  1. 静态形状(Static Shapes): NPU 在静态形状下性能最强。建议将输入固定,如 batch_size=1, sequence_length=512
  2. 模型简化: 使用 onnxsim 消除冗余算子,降低报错率 。
pip install onnxsim onnxsim ./qwen_onnx_out/decoder_model.onnx ./qwen_onnx_out/decoder_model_sim.onnx 

四、验证 ONNX 模型

在交给高通工具链之前,先确保 ONNX 模型是正确的:

import onnx import onnxruntime as ort model = onnx.load("./qwen_onnx_out/decoder_model.onnx") onnx.checker.check_model(model) print("ONNX 模型校验通过!")

五、 高通工具链(QNN)模型编译

1. 环境准备

确保你的 Linux 开发机已安装:

  • Qualcomm AI Engine Direct SDK (QNN)
  • Android NDK (建议 r25c 或 r26)
  • 设置环境变量
exportQNN_SDK_ROOT=/path/to/qnn_sdk exportANDROID_NDK_ROOT=/path/to/android_ndk source$QNN_SDK_ROOT/bin/envsetup.sh 

一旦你拿到了 decoder_model.onnx,你接下来的操作流程是:

  • 准备量化数据:从你的微调数据集中抽取 100 条样本,用于高通工具的 Post-Training Quantization (PTQ)。
  • 使用 QNN Converter
qnn-onnx-converter -i decoder_model.onnx -o qwen_qnn.cpp --input_list_file calibration_data.txt 

要把微调后的 Qwen-0.6B 最终跑在手机 NPU 上,你需要经历交叉编译的过程。高通 QNN SDK 提供了专门的工具,将转换后的中间代码(.cpp / .bin)编译成手机端可执行的二进制文件。
在高通架构中,通常涉及两种文件:

  • .so (Model Library):模型的结构描述库。
  • .bin (Context Binary):针对特定 NPU 硬件优化并序列化后的图模型(这是性能最高的形态)。

2. 生成模型动态库 (.so)

使用 qnn-onnx-converter 将 ONNX 转为 C++ 代码,再通过 qnn-model-lib-generator 编译 。

qnn-model-lib-generator \ -c qwen_model.cpp \ -b qwen_model.bin \ -o ./model_libs \ -t aarch64-android # 指定目标平台为 Android ARM64
  • 输出结果:在 ./model_libs/aarch64-android/ 目录下,你会得到一个 libqwen_model.so
  • 用途:这个文件包含了模型的拓扑结构,可以被高通的推理引擎加载。

3. 生成上下文二进制文件 (.bin) —— 性能核心

为了实现“秒开”和极致加速,必须生成针对 HTP(Hexagon Tensor Processor)优化的 Context Binary 。

qnn-context-binary-generator \ --model ./model_libs/aarch64-android/libqwen_model.so \ --backend libQnnHtp.so \ --output_dir ./context_out \ --binary_file qwen_htp_context 
  • --backend libQnnHtp.so:这步至关重要,它指定使用 HTP (Hexagon Tensor Processor) 后端,即真正的 NPU 加速。
  • 输出结果qwen_htp_context.bin
注意:此步骤通常建议在连接了真机的情况下运行(通过 adb),或者使用高通提供的模拟器,因为生成 context 需要针对具体的芯片架构(如 v73, v75)。

六、 手机端集成与验证

在 Android 项目中,通过 C++/JNI 调用 QNN API 加载 qwen_htp_context.bin 即可执行推理 。

现在你手里有了:

  1. 模型资产:qwen_htp_context.bin。
  2. 推理引擎库:从 QNN SDK 中提取的 libQnnHtp.so, libQnnSystem.so 等。

快速验证:
在写 App 前,先用 qnn-net-run 工具在手机 shell 中测试 :

[cite_start]./qnn-net-run --container qwen_htp_context.bin --backend libQnnHtp.so --input_list input_data.txt [cite: 198, 199, 200]

若能正常输出 Tensor 结果,说明模型已成功跑在 NPU 上!

推理代码核心逻辑(C++/JNI):
在 Android 的 C++ 层,你需要调用 QNN API 来加载这个 .bin 文件:

// 1. 初始化 QNN 实例 Qnn_BackendHandle_t backendHandle; QnnBackend_initialize(..., &backendHandle); // 2. 加载之前生成的 Context Binary Qnn_ContextHandle_t contextHandle; // 通过读取 qwen_htp_context.bin 的 buffer 传入 QnnContext_createFromBinary(backendHandle, deviceHandle, ..., binaryBuffer, binarySize, &contextHandle, ...); // 3. 准备 Tensor 数据并执行推理 QnnGraph_execute(graphHandle, inputTensors, numInputs, outputTensors, numOutputs, ...); 

🛠 避坑总结

  • 版本一致性: 编译 .so 的 NDK 版本必须与 Android 项目一致 。
  • 内存溢出: 若 Context Length 设得太大,NPU 内存会溢出,建议从 512 或 1024 测起 。
  • 算子支持: 若生成 Binary 报错,需回到 ONNX 阶段进行算子融合或替换 。

希望这篇指南能帮你顺利把大模型装进兜里!如果有问题,欢迎在评论区交流。

如果你觉得有用,欢迎点赞、收藏、关注!

Read more

DeepSeek-R1-Distill-Llama-8B惊艳效果展示:高精度数学推导与多步逻辑生成案例

DeepSeek-R1-Distill-Llama-8B惊艳效果展示:高精度数学推导与多步逻辑生成案例 如果你正在寻找一个能在复杂数学题和逻辑推理上表现出色的开源模型,DeepSeek-R1-Distill-Llama-8B绝对值得你关注。这个只有80亿参数的模型,在数学推理能力上却能达到接近甚至超越某些更大模型的水平。 今天我就带你看看这个模型到底有多强,通过几个真实的案例展示它在数学推导、逻辑推理和多步问题解决上的惊艳表现。你会发现,有时候模型大小并不是决定能力的唯一因素。 1. 模型能力概览:小身材大智慧 DeepSeek-R1-Distill-Llama-8B虽然参数规模不大,但在推理任务上的表现却让人眼前一亮。它继承了DeepSeek-R1系列强大的推理能力,经过精心蒸馏后,在保持高性能的同时大幅减小了模型体积。 1.1 核心能力特点 这个模型最吸引人的地方在于它的多步推理能力。不像很多模型只能给出最终答案,DeepSeek-R1-Distill-Llama-8B会像人类解题一样,一步步展示思考过程: * 逐步推导:把复杂问题拆解成多个简单步骤 * 逻辑清

Meta-Llama-3-8B-Instruct避坑指南:从部署到对话全流程解析

Meta-Llama-3-8B-Instruct避坑指南:从部署到对话全流程解析 1. 引言 随着大模型技术的快速发展,Meta于2024年4月发布了Llama 3系列中的中等规模版本——Meta-Llama-3-8B-Instruct。该模型在指令遵循、多任务处理和对话能力方面表现出色,尤其适合单卡部署场景。得益于其GPTQ-INT4量化版本仅需约4GB显存,RTX 3060及以上消费级GPU即可流畅运行,成为个人开发者与中小企业构建AI对话应用的理想选择。 本文基于vllm + open-webui技术栈,结合实际部署经验,系统梳理从环境配置、模型加载到Web界面集成的完整流程,并重点剖析常见问题及其解决方案,帮助读者高效搭建稳定可用的本地化对话系统。 2. 技术选型与核心优势 2.1 模型特性概览 Meta-Llama-3-8B-Instruct 是一个经过指令微调的80亿参数密集模型,具备以下关键优势: * 高性能低门槛:FP16精度下占用约16GB显存,GPTQ-INT4量化后可压缩至4GB以内,支持RTX 3060/4060等主流消费级显卡。 * 长上

Windows 环境下 llama.cpp 编译 + Qwen 模型本地部署全指南

在大模型落地场景中,本地轻量化部署因低延迟、高隐私性、无需依赖云端算力等优势,成为开发者与 AI 爱好者的热门需求。本文聚焦 Windows 10/11(64 位)环境,详细拆解 llama.cpp 工具的编译流程(支持 CPU/GPU 双模式,GPU 加速需依赖 NVIDIA CUDA),并指导如何通过 modelscope 下载 GGUF 格式的 Qwen-7B-Chat 模型,最终实现模型本地启动与 API 服务搭建。 1.打开管理员权限的 PowerShell/CMD,执行以下命令克隆代码: git clone https://github.com/ggml-org/llama.cpp mkdir

VHDL数字时钟在FPGA上的系统学习路径

从零开始打造一个VHDL数字时钟:FPGA上的系统性学习实践 你有没有试过,在FPGA开发板上点亮第一个LED的那一刻,心里涌起一股“我正在操控硬件”的兴奋?但很快就会发现——让灯亮只是起点。真正让人着迷的是: 如何用代码‘画’出电路,让时间在芯片里流淌 。 今天我们就来干一件“小而完整”的事: 用VHDL语言,在FPGA上从头构建一个数字时钟 。它不只是“显示时间”这么简单,而是一个涵盖时序逻辑、状态控制、人机交互和物理驱动的微型系统工程。通过这个项目,你会真正理解什么叫“写代码就是在设计电路”。 为什么选“数字时钟”作为入门项目? 很多初学者一上来就想做图像处理、通信协议或者神经网络加速器,结果被复杂的接口和算法压得喘不过气。其实,最好的入门项目是那种“看得见、摸得着、改了立刻有反馈”的系统。 数字时钟恰恰满足这一点: * 它有明确的时间行为(每秒走一次) * 有人机交互(按键调时间) * 有输出设备(数码管闪烁可见) * 所有模块都可以逐步搭建、单独验证 更重要的是,