从 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

Flutter for OpenHarmony: Flutter 三方库 intersperse 优雅在鸿蒙列表项间插入间隔或装饰(UI 细节处理助手)

Flutter for OpenHarmony: Flutter 三方库 intersperse 优雅在鸿蒙列表项间插入间隔或装饰(UI 细节处理助手)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在 OpenHarmony 应用的 UI 设计中,我们经常需要在列表(List)或一排组件(Column/Row)之间插入特定的元素,例如: 1. 在一排按钮中间插入分隔线。 2. 在列表数据项之间插入间隙(Spacing)。 3. 为每个组件之间添加逗号或其他符号。 常见的做法是手写 for 循环并通过索引判断。但这种方式不仅代码丑陋,且在处理动态列表时极其容易出错(例如忘记最后一个元素不加分隔符)。 intersperse 是一个极简的扩展库。它通过为 Iterable 增加一个极其直观的方法,彻底解决了“元素间插入”这一烦人的小问题。 一、核心操作图解 intersperse 提供了一种“无感插入”的流式处理方式。 [A, B, C] (原始数据) intersperse(

By Ne0inhk
鸿蒙电商购物全栈项目——数据安全与合规

鸿蒙电商购物全栈项目——数据安全与合规

《鸿蒙APP开发从入门到精通》第39篇:鸿蒙电商购物全栈项目——数据安全与合规 🛡️📝📊 内容承接与核心价值 这是《鸿蒙APP开发从入门到精通》的第39篇——数据安全与合规篇,100%承接第38篇的数据分析与商业洞察场景,并基于电商购物场景的数据安全与合规要求,设计并实现鸿蒙电商购物全栈项目的数据安全与合规功能。 学习目标: * 掌握鸿蒙应用数据安全的核心设计与实现; * 实现数据加密、数据脱敏、数据备份; * 理解数据合规的战略设计与实现; * 实现GDPR合规、用户数据权益保护、数据审计; * 掌握数据安全与合规的协同管理策略; * 优化电商购物项目的数据安全与合规水平。 学习重点: * 鸿蒙应用数据安全的全流程设计原则; * 数据合规的战略规划与技术落地; * 数据安全与合规的协同管理策略。 一、 数据安全基础 🛡️ 1.1 数据安全定义 数据安全是指保护电商购物项目中的数据安全,主要包括以下方面: * 数据加密:加密数据; * 数据脱敏:脱敏数据; * 数据备份:备份数据。 1.2 数据安全架构 数据安全采用分层架构,

By Ne0inhk

Flutter 三方库 holiday_jp 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全维度的日本法定节假日(公休日)查询与日历调度引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 holiday_jp 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全维度的日本法定节假日(公休日)查询与日历调度引擎 在鸿蒙(OpenHarmony)系统的全球化(Globalization)出海应用、针对日本市场的日程管理、财务结算系统(需考虑日本银行休假)或带有国际化特色的鸿蒙版日历组件中,如何瞬间获取任意年份日本的法定节假日、判定当前是否为公休日?holiday_jp 为开发者提供了一套工业级的、基于官方精细化数据集的日本节假日处理方案。本文将深入实战其在鸿蒙出海应用逻辑层中的应用。 前言 什么是 Holiday JP?它是一个专注于提供日本法定假期(祝日)数据的专业库。它涵盖了从传统的“元日”到现代的“体育之日”等所有官方假期,并能自动处理由于由于由于由于“振替休日(补休)”产生的动态调休逻辑。在 Flutter

By Ne0inhk
Flutter 组件 fletch 的适配 鸿蒙Harmony 实战 - 驾驭高性能网络爬虫、实现鸿蒙端多并发与自定义拦截器的资产自动化抓取方案

Flutter 组件 fletch 的适配 鸿蒙Harmony 实战 - 驾驭高性能网络爬虫、实现鸿蒙端多并发与自定义拦截器的资产自动化抓取方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 fletch 的适配 鸿蒙Harmony 实战 - 驾驭高性能网络爬虫、实现鸿蒙端多并发与自定义拦截器的资产自动化抓取方案 前言 在数据驱动的鸿蒙(OpenHarmony)应用开发中,很多时候我们需要从外部网络环境大规模采集实时资讯、获取海量资源路径或者是进行自动化的接口探测。传统的 http 库虽然简单,但在面对数十路并发下载、复杂的 Cookie 状态维持以及多级的请求拦截(Interceptor)时,往往显得捉襟见肘。 fletch 正是一款专为高性能、工业级抓取任务设计的 Dart 网络增强库。它不仅支持极致的并发限流,更提供了一套类似拦截器管线的强大插件化能力。 适配到鸿蒙系统后,配合鸿蒙底层的网络切片和能效策略,fletch 能让你的数据采集应用在保持低功耗的同时,展现出前所未有的吞吐力。本文将为你深入剖析 fletch 在鸿蒙实战环境下的深度集成与优化。 一、原理解析 / 概念介绍 1.1

By Ne0inhk