PEFT 怎样在合并适配器后恢复基础模型接口
来源:17golang原创
时间:2026-10-29 16:50:12 185浏览 收藏
对于支持合并的普通 LoRA,调用 merged_model = peft_model.merge_and_unload(),并把后续推理、保存都切换到返回的 merged_model,即可使用基础模型架构对应的普通模型接口。这里保留的是合并后的权重,不能把“恢复基础模型接口”理解成“还原微调前的原始权重”。
官方地址:https://huggingface.co/docs/peft/
本文限定为通过 PEFT 包装的 Transformers 模型及可合并 LoRA,讨论一次单适配器导出。已有量化、多适配器或特殊 LoRA 变体时,需要先按对应方法文档确认支持范围。
合并后怎样取得普通模型对象
关键是接住返回值。下面这个赋值表达了两件事:把适配器效果写入基础权重,并取得移除 PEFT 模块后的模型对象。返回对象的架构与原基础模型相同;官方接口文档明确要求后续使用返回对象。不要只调用函数而丢弃结果,也不要用修改类名或删除属性来代替卸载。PEFT Tuner 接口说明
# 已有可合并的PEFT模型时,接住返回对象再交给后续代码 merged_model = peft_model.merge_and_unload() merged_model.eval()
普通接口取决于你原本加载的模型类型。以 AutoModelForCausalLM 加载的因果语言模型为例,合并产物仍可使用该类支持的 forward、generate 和 save_pretrained。合并本身不会给原本不具备生成能力的模型添加 generate。
为什么普通接口不代表原始权重
可以把这里的对象拆成基础权重、LoRA 增量和 PEFT 包装三个概念。合并后的普通模型不再依赖独立的 LoRA 分支,但权重已经包含增量。原始基础模型目录若没有被覆盖,仍能作为重新加载原始权重的来源;内存里的 base 变量却不应视为自动保存的独立备份,因为包装与合并可能作用于共享的底层模块。

正式 merge_and_unload 后,PEFT 专用的适配器管理能力不再属于返回模型的工作契约。不能期待继续以原方式切换、禁用或撤销已合并的适配器。官方检查点文档还提醒,完整模型包含基础权重,存储体积不同于仅保存适配器的小型检查点。PEFT 检查点与完整模型存储
怎样加载、合并并保存同一套产物
下面使用本地路径,避免把某个公开适配器与不匹配的基础模型凑在一起。运行前需准备完整的基础模型目录、基于它训练的普通 LoRA 适配器,以及训练和推理实际使用的分词器目录;安装与项目环境匹配的 torch、transformers 和 peft。代码未在本文环境执行,不提供虚构的类型输出或推理结果。
from pathlib import Path
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
# 替换为本地真实目录:基础模型必须与训练适配器时一致
base_dir = Path("./models/base-model")
adapter_dir = Path("./adapters/task-lora")
tokenizer_dir = Path("./models/task-tokenizer")
output_dir = Path("./exports/task-merged")
# 基础模型、适配器和实际使用的分词器分别加载
base = AutoModelForCausalLM.from_pretrained(base_dir)
tokenizer = AutoTokenizer.from_pretrained(tokenizer_dir)
peft_model = PeftModel.from_pretrained(base, adapter_dir)
peft_model.eval()
# 单个普通LoRA适配器合并后,后续只使用返回对象
merged_model = peft_model.merge_and_unload()
merged_model.eval()
# 保存完整模型及分词器;导出目录独立于基础模型和适配器目录
output_dir.mkdir(parents=True, exist_ok=False)
merged_model.save_pretrained(output_dir)
tokenizer.save_pretrained(output_dir)
# 这里返回的是普通因果语言模型,权重包含已合并的适配器增量
print(type(merged_model).__name__)
输出目录已存在时,exist_ok=False 会停止,便于避免把两次不同导出混在一起。若加载或合并报错,先处理基础模型配置、适配器方法和依赖支持问题,不要捕获所有异常后继续保存一个不明状态的模型。保存过程中断时,保留原始输入,以新的独立目录重新完成导出。
示例假定模型和分词器的词表尺寸已经一致。训练若扩展过词表,还需沿用训练时的词表扩展及相关可训练模块配置;单独保存分词器不能替代模型嵌入层处理。模型配置、实际分词器和权重必须组成同一套可加载产物。
完整导出后,加载侧可以采用普通 Transformers 路径:
from transformers import AutoModelForCausalLM, AutoTokenizer
# 完整合并产物按普通Transformers模型加载,不再叠加原适配器
model = AutoModelForCausalLM.from_pretrained("./exports/task-merged")
tokenizer = AutoTokenizer.from_pretrained("./exports/task-merged")
model.eval()
不要对该合并目录再次加载同一原始 LoRA 适配器作为“恢复功能”的步骤,否则可能在已含增量的模型上再次施加该增量。若要重新训练或比较不同适配器,应从保留的原始基础模型与适配器产物另建对象。
需要撤销时应该选择哪种操作
| 真实目标 | 操作选择 | 需要记住的条件 |
|---|---|---|
| 保留适配器效果,导出普通模型 | merge_and_unload | 使用返回值,失去原PEFT适配器管理能力 |
| 临时合并,之后仍需撤销 | merge_adapter与unmerge_adapter | 保持PEFT结构,属于独立分支 |
| 未合并时移除LoRA模块 | unload | 接住返回值,不把它当合并导出 |
| 已永久合并,又要微调前权重 | 重新加载原始基础模型 | 需要原始模型来源,不能靠改接口逆推出原权重 |
如果从一开始就需要可撤销的合并,应在保留 PEFT 模块的对象上采用下面的独立分支,而不是在永久合并之后继续执行这段代码:
# 这是另一条独立分支,起点仍是尚未merge_and_unload的PEFT模型 peft_model.merge_adapter() # 保留适配器结构的合并可以撤销,再按需要卸载PEFT模块 peft_model.unmerge_adapter() plain_model = peft_model.unload()
这里先显式撤销,再移除模块,避免把不同阶段的对象混用。LoRA 官方说明对临时合并、撤销和卸载给出了各自用途;不应将这些方法当成可以随意互换的同义操作。LoRA 合并与加载说明

接口报错与保存目录怎样判断
合并后set_adapter不可用,是不是合并失败?
不能据此判定失败。返回普通模型不再提供原PEFT专用能力,调用侧也应停止依赖这些方法。如果服务要求按请求切换适配器,就不适合以单个永久合并模型替代原服务对象。
为什么只调用merge_and_unload,原变量看起来仍然不对?
先看后续实际传递的是哪一个对象。让推理服务、保存函数和模型注册表全部引用返回的 merged_model,不要依靠旧包装对象仍能转发某些属性的偶然行为。也不要把“不原地替换返回类型”理解为底层权重完全不变。
量化LoRA能直接照搬这段代码吗?
不能一概照搬。不同PEFT方法和量化设置的合并支持不同,部分组合不允许合并。示例没有添加量化配置,也不承诺合并前后逐位相同;需要保持原始基础模型、适配器配置和依赖信息,按所用方案的支持文档处理。
只看到适配器文件,算完整模型导出吗?
应区分保存对象:在PEFT包装对象上保存通常是适配器产物,在普通合并对象上保存才是完整模型导出路径。加载侧若仍需要从另一处取得基础权重,就不能把适配器目录误称为独立的完整模型。
实际接入时,最容易遗漏的不是合并函数名,而是对象引用和产物归属:明确返回模型被谁使用、哪个目录保存完整权重、哪里保留原始基础模型,以及是否仍需切换适配器,才能选对导出方式。
-
221 收藏
-
249 收藏
-
404 收藏
-
485 收藏
-
科技周边 · 人工智能 | 2星期前 | LoRa PEFT adapter save_pretrained adapter_model.safetensors selected_adapters save_embedding_layers483 收藏
-
483 收藏
-
420 收藏
-
415 收藏
-
224 收藏
-
150 收藏
-
269 收藏
-
372 收藏
-
298 收藏
-
472 收藏
-
350 收藏
-
科技周边 · 人工智能 | 1小时前 | 性能优化 · Hugging Face Datasets IterableDataset flatten_indices indices mapping Arrow222 收藏
-
326 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习