025 微调后的模型部署合并LoRA权重与量化导出昨天半夜被一个生产环境告警叫醒——部署的LoRA微调模型推理速度只有8 tokens/s用户反馈“打字都比你快”。查了半天发现是权重合并时精度丢失导致模型反复重算。这种坑踩一次记一辈子。先搞清楚LoRA权重到底要不要合并很多人以为LoRA微调完直接扔两个权重文件base adapter就能部署。天真了。推理框架对LoRA的支持参差不齐vLLM原生支持LoRA但需要额外配置lora_modules和max_loras而且多轮对话场景下显存占用会动态增长TGI对LoRA支持更弱某些版本甚至不支持动态切换TensorRT-LLM必须合并权重才能导出engine我的建议除非你确定推理框架完美支持LoRA热加载否则一律合并。合并后的模型就是一个完整的、无依赖的模型文件部署时少操一万个心。合并LoRA权重的正确姿势含踩坑记录# 别这样写这是网上流传的错误写法frompeftimportPeftModel base_modelAutoModelForCausalLM.from_pretrained(base_model_path)modelPeftModel.from_pretrained(base_model,lora_adapter_path)modelmodel.merge_and_unload()# 这里踩过坑默认float32合并model.save_pretrained(merged_model)上面这段代码的问题在于merge_and_unload()默认用float32精度合并。如果你的base模型是半精度加载的合并时会发生精度转换导致最终模型参数出现微小偏移。推理时可能看不出但一旦做量化导出误差会被放大。正确的做法importtorchfromtransformersimportAutoModelForCausalLM,AutoTokenizerfrompeftimportPeftModel# 加载base模型时明确指定精度base_modelAutoModelForCausalLM.from_pretrained(base_model_path,torch_dtypetorch.bfloat16,# 和训练时保持一致device_mapauto)# 加载LoRA权重modelPeftModel.from_pretrained(base_model,lora_adapter_path)# 关键合并前先确认adapter的scale参数# 这里踩过坑不同训练框架的lora_alpha默认值不同print(fLoRA alpha:{model.peft_config[default].lora_alpha})print(fLoRA r:{model.peft_config[default].r})# 合并并保持精度merged_modelmodel.merge_and_unload()# 注意merge_and_unload后merged_model的dtype应该和base_model一致assertmerged_model.dtypetorch.bfloat16,精度不一致# 保存时也保持精度merged_model.save_pretrained(merged_model,safe_serializationTrue)tokenizer.save_pretrained(merged_model)一个容易被忽略的细节如果你的LoRA训练时用了bnb量化bitsandbytes合并前必须先把base模型转为普通精度。否则merge_and_unload()会报错因为量化后的权重无法直接合并。# 处理bnb量化模型的情况fromtransformersimportBitsAndBytesConfig# 加载时先不量化base_modelAutoModelForCausalLM.from_pretrained(base_model_path,torch_dtypetorch.bfloat16,device_mapauto,quantization_configNone# 别用bnb量化)量化导出从FP16到INT4的实战合并完权重后下一步就是量化。这里我踩过最大的坑是量化后的模型精度下降导致生成内容出现重复片段。方案一GPTQ量化推荐用于GPU部署fromauto_gptqimportAutoGPTQForCausalLM,BaseQuantizeConfig# 这里踩过坑量化数据集必须和训练数据分布一致quantize_configBaseQuantizeConfig(bits4,group_size128,# 别用32显存占用爆炸damp_percent0.01,desc_actFalse,# 设为True会提升精度但降低速度)modelAutoGPTQForCausalLM.from_pretrained(merged_model,quantize_config,torch_dtypetorch.bfloat16)# 校准数据集至少准备128条样本# 别这样写用随机生成的文本做校准calibration_dataload_your_validation_dataset()# 用真实数据model.quantize(calibration_data,use_tritonFalse)# 导出model.save_quantized(quantized_model,use_safetensorsTrue)关键参数解释group_size128这是速度和精度的平衡点。64精度更高但模型更大256反之desc_actFalse关闭后推理速度提升30%但精度下降约0.5%。如果你的任务对精度敏感比如代码生成建议设为True方案二AWQ量化适合低延迟场景AWQ比GPTQ快但量化过程更复杂。我一般只在需要10ms首token延迟时才用。fromawqimportAutoAWQForCausalLM modelAutoAWQForCausalLM.from_pretrained(merged_model)tokenizerAutoTokenizer.from_pretrained(merged_model)# 这里踩过坑AWQ的校准数据需要更长文本calib_data[tokenizer(text,return_tensorspt)fortextinlong_texts]model.quantize(tokenizer,quant_config{zero_point:True,q_group_size:128,w_bit:4},calib_datacalib_data)model.save_quantized(awq_model)方案三GGUF量化CPU部署首选如果你要在CPU上跑或者用llama.cpp部署GGUF是唯一选择。# 先用convert.py把合并后的模型转成gguf格式python convert.py merged_model/--outfilemodel.gguf# 再用quantize工具量化./quantize model.gguf model_q4_k_m.gguf q4_k_mGGUF的量化级别选择q4_k_m通用推荐平衡速度和精度q5_k_m精度更高适合数学推理任务q2_k极端压缩但生成质量明显下降别在生产环境用部署时的性能调优量化完模型后部署时还有几个坑要避开1. 显存碎片问题量化后的模型虽然小了但推理时的KV Cache依然吃显存。我遇到过量化后模型只占4GB但推理时显存飙到12GB的情况。解决方案设置max_new_tokens上限并启用use_cacheTrue默认就是True别手贱关掉。2. 批处理大小量化模型对batch size更敏感。我测试过batch size从1增加到4吞吐量提升3倍但显存只增加50%。别用batch_size1那是浪费。# 部署时的配置示例fromvllmimportLLM,SamplingParams llmLLM(modelquantized_model,dtypebfloat16,max_model_len4096,gpu_memory_utilization0.9,# 别设太高留点余量tensor_parallel_size1,# 单卡部署就别开多卡)sampling_paramsSamplingParams(temperature0.7,top_p0.9,max_tokens512,best_of4,# 这里踩过坑best_of1会显著增加延迟)3. 预热Warm-up量化模型第一次推理特别慢因为要加载和编译CUDA kernel。部署脚本里一定要加预热# 部署前预热for_inrange(5):llm.generate([Hello, how are you?],sampling_params)print(Warm-up done)个人经验总结合并权重时精度一致性是第一位。我见过太多人因为base模型和adapter精度不一致导致合并后模型输出乱码。检查model.dtype和base_model.dtype是否一致这是最低成本的排查手段。量化不是银弹。INT4模型在数学推理、代码生成等任务上精度下降明显。如果你的应用场景是医疗诊断、金融风控建议用INT8甚至保持FP16。别为了省那2GB显存牺牲业务准确性。校准数据决定量化质量。不要用随机文本或通用语料做校准。我踩过最大的坑用维基百科数据校准的模型在客服对话场景下生成质量下降30%。校准数据必须来自你的实际业务场景。部署前做A/B测试。量化后的模型和原始模型在100条测试样本上对比输出。如果差异超过5%说明量化参数需要调整。别信什么“INT4无损量化”的鬼话无损是有前提条件的。留好回滚方案。量化导出后原始合并权重别删。我遇到过量化模型在特定输入下崩溃不得不回退到FP16部署的情况。磁盘不值钱模型文件留着。最后说一句模型部署不是终点是另一个起点。量化后的模型需要持续监控生成质量设置告警阈值。当用户反馈“AI变傻了”的时候第一时间检查量化参数是否被意外修改。