简介大语言模型部署的核心在于将训练好的模型高效迁移到目标环境而PyTorch权重在线上场景常面临依赖环境复杂、推理性能受限、跨平台移植困难等三大问题。针对这些挑战ONNX Runtime通过算子优化显著提升CPU/GPU推理速度TFLite则凭借轻量化和移动生态支持成为端侧部署的主流方案。本文从Transformer基础架构出发系统讲解Qwen1.5模型从PyTorch权重分别导出为ONNX和TFLite的完整步骤涵盖动态轴配置、量化策略、序列长度固定等关键技术细节并对比两种格式在服务器与移动端的适用场景。无论你是准备将大模型部署到云端服务还是尝试在边缘设备上运行轻量级模型这套流程都能提供可直接复用的工程参考。 训练出模型只是项目的前半程后半程是把它装进目标环境里跑起来。这句话在我准备部署Qwen1.5大语言模型时体会特别深。很多人拿到Qwen1.5的PyTorch权重后习惯直接调AutoModel.from_pretrained本地验证效果自然很快可真要推到服务器、手机或者边缘设备上环境依赖、推理性能、跨平台移植这些问题会像连环套一样涌出来。这次做的小型实战项目核心目标只有一个把Qwen1.5大语言模型完整导出为ONNX和TFLite两种格式并整合出可复用的源码流程教程。ONNX用来解决服务器端和通用推理框架的落地问题TFLite主要面向移动端和边缘设备。文章会按实际操作的顺序展开环境搭建、模型导出、量化处理、推理验证和排错过程都会拆开讲透。如果你之后也要做Transformer结构的大模型导出这套流程的参考价值同样成立。1. 为什么要把Qwen1.5导出成ONNX和TFLite导出这一步看起来只是换了一种模型文件格式本质上解决的却是三个非常实际的部署问题依赖环境、推理性能、跨平台能力。1.1 先认清PyTorch权重在线上环境的三道坎第一道坎是环境依赖。PyTorch权重本身不能脱离框架运行想用Transformers库推理机器上必须完整安装PyTorch、tokenizers、transformers等一整套Python依赖。这些库对版本的要求非常严格Python 3.8、torch 2.0、transformers 4.39一步版本不对就可能跑不起来。到生产环境换一台机器往往就是半天环境问题。第二道坎是推理性能。Transformers库的代码为了兼顾开发灵活性在运行时会有很多动态分支和Python层面的调度开销。单次推理还好一旦做成并发服务Python的GIL会直接限制吞吐延迟曲线也会变得很难看。把模型导出成ONNX后可以用ONNX Runtime的高性能算子执行推理CPU上通常能拿到立竿见影的速度提升GPU上也可以无缝切到CUDA或者TensorRT。第三道坎是跨平台能力。手机端、嵌入式设备上根本跑不了完整的Python环境也不可能装一个PyTorch进去。像安卓设备要用NNAPIiOS要用Core ML这些场景下模型必须是轻量的、能被对应运行时托管的格式。TFLite就是目前移动端支持最广泛、生态最成熟的一类格式。1.2 ONNX与TFLite的定位差异把这一步想清楚后面就不会在格式选择上来回纠结。这两者不是竞争关系而是面向不同目标场景的部署格式。对比项ONNXTFLite主要目标服务器、PC、云端推理移动端、嵌入式、边缘设备推理运行时ONNX Runtime、TensorRT、OpenVINOLiteRTTFLite、NNAPI、Core ML量化支持动态/静态INT8FP16等动态范围量化、INT8全整型、FP16体积比原始PyTorch略小更紧凑适合包体受限场景算子覆盖覆盖面更广LLM相关算子较完整算子相对受限导出时需适配从Transformer架构的角度看Qwen1.5由Embedding、RMS Norm、Self-Attention、MLP、LayerNorm、线性层组成。ONNX对这些基础算子的覆盖已经相当齐全所以把Qwen1.5导出成ONNX整体是顺的。TFLite的算子集相对有限需要做一些适配这也是为什么我在TFLite部分会强调固定序列长度和量化策略这两个都是移动端模型落地的关键。2. 环境与模型选型这步定了后面才省事2.1 硬件与依赖先给一份我自己验证过的硬件配置参考。导出过程本身对算力要求并不极端CPU推理只在验证阶段使用。推荐配置CPUIntel i5/Ryzen 5以上负责ONNX导出与验证内存16GB以上导出7B以上模型建议32GB硬盘预留30GB左右空间模型文件加转换缓存GPU可选NVIDIA CUDA显卡用于FP16导出和TensorRT加速软件依赖pip install torch torchvision transformers optimum onnx onnxruntime pip install ai-edge-torch # TFLite导出用 pip install onnx2tf # ONNX转TFLite备选Qwen1.5系列基于Transformers库的AutoModelForCausalLM接口所以底层依赖与标准HuggingFace生态一致。optimum是用来做ONNX导出的关键库ai-edge-torch是Google维护的PyTorch到TFLite直转工具后面会用到。2.2 选哪个尺寸的Qwen1.5Qwen1.5系列从0.5B到72B都有。导出ONNX这个环节只要内存足够多大都可以导出但TFLite就要特别考虑算力和存储。我的建议很明确ONNX导出Demo选Qwen1.5-1.8B-Chat体积适中CPU跑得动效果也能体现大模型能力。TFLite导出Demo选Qwen1.5-0.5B-Chat量化后500MB左右至少在移动端有安装可行性。只做流程验证选0.5B更合适导出速度快迭代成本低。做线上服务视显存选7B或14B再配合Runtime的并行能力上生产。记住一个原则TFLite导出不等于所有参数都能塞进手机模型尺寸和最终设备算力必须匹配否则导出来也只是一个没法用的静态文件。3. 导出ONNX的完整流程两条路线都亲自走了一遍3.1 用Optimum快速导出一条命令干完核心事Optimum库封装了HuggingFace模型与ONNX Runtime之间的转换对于因果语言模型CausalLM的支持做得相当成熟包括past_key_values的处理和LM头等复杂结构。先加载模型并导出from optimum.onnxruntime import ORTModelForCausalLM from transformers import AutoTokenizer model_id Qwen/Qwen1.5-1.8B-Chat export_dir ./onnx/qwen1.5-1.8b-chat model ORTModelForCausalLM.from_pretrained(model_id, exportTrue) tokenizer AutoTokenizer.from_pretrained(model_id) model.save_pretrained(export_dir) tokenizer.save_pretrained(export_dir)这段代码走完export_dir下会生成model.onnx、model.onnx_data大权重备份和config.json。如果权重超过2GB会拆分成model.onnx_data这是ONNX的标准做法后面推理时ONNX Runtime会自动加载不用手动处理。这里重点说一下ORTModelForCausalLM和普通AutoModel的区别后者返回的是PyTorch模型前者是ONNX Runtime封装后的模型导出后直接就能用generate发起推理不用自己写采样循环。这也是实际项目里更推荐的方式。验证一次完整生成from optimum.onnxruntime import ORTModelForCausalLM from transformers import AutoTokenizer model_dir ./onnx/qwen1.5-1.8b-chat tokenizer AutoTokenizer.from_pretrained(model_dir) model ORTModelForCausalLM.from_pretrained(model_dir) prompt 请用一句话介绍你自己 inputs tokenizer(prompt, return_tensorspt) outputs model.generate(**inputs, max_new_tokens64, do_sampleTrue) print(tokenizer.decode(outputs[0], skip_special_tokensTrue))用Optimum导出有个隐形好处它会同时导出带past_key_values输入的版本生成时能走KV Cache路径对话场景下推理效率比每步全量重算高一个量级。这个细节在纯手工导出时容易被忽略。3.2 手动导出torch.onnx.export与dynamic_axes配置有些场景中Optimum不支持某个模型结构或者你想精确控制输入输出的名字和形状就必须手动走了。手动导出的套路其实也很固定。import torch from transformers import AutoModelForCausalLM, AutoTokenizer model_id Qwen/Qwen1.5-1.8B-Chat model AutoModelForCausalLM.from_pretrained(model_id, torch_dtypetorch.float32).eval() tokenizer AutoTokenizer.from_pretrained(model_id) dummy_input tokenizer(你好请做一下自我介绍, return_tensorspt) with torch.no_grad(): torch.onnx.export( model, (dummy_input[input_ids], dummy_input[attention_mask]), qwen1.5-1.8b-chat.onnx, opset_version17, input_names[input_ids, attention_mask], output_names[logits], dynamic_axes{ input_ids: {0: batch, 1: seq_len}, attention_mask: {0: batch, 1: seq_len}, logits: {0: batch, 1: seq_len}, }, do_constant_foldingTrue, )这个例子特别注意三点。一torch_dtype必须设为float32不能直接用bfloat16继续导出。ONNX Runtime对多种精度的支持范围不如PyTorch广默认FP32最稳妥。导出后再在推理时通过Runtime的enable_auto_mixed_precision或指定精度来提速比在导出阶段锁死精度灵活。二dynamic_axes配置的是batch维度和序列长度维度。模型允许输入本文还有配套的精品资源点击获取