当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > LoRA 适配器怎样与基础模型分离加载

LoRA 适配器怎样与基础模型分离加载

来源:17golang原创 2026-11-07 23:31:18 0浏览 收藏

我第一次把 LoRA 用到推理服务时,最容易混淆的是“加载适配器”和“加载一个新模型”。LoRA 目录通常只保存相对基础模型的增量参数,正确的做法是先加载兼容的基础模型,再把适配器挂到这个模型上。这样基础模型可以复用,适配器也能按任务切换;只有在准备做单体部署时,才考虑把两者合并。

官方地址:https://huggingface.co/docs/peft/en/package_reference/lora

下面的示例以 Transformers 和 PEFT 的文本模型为主,路径和模型名使用占位值,重点是加载顺序与生命周期,不把静态示意当成已经运行的输出。

先分清基础模型和 LoRA 权重

基础模型提供完整的网络结构和原始参数,LoRA 适配器只保存要插入目标层的低秩增量。适配器目录至少要能让加载器找到配置与权重,例如 adapter_config.json 和适配器权重文件。它不能脱离匹配的基础模型独立变成一个完整的语言模型。

这也是“分离加载”的核心:模型对象负责承载基础参数,适配器对象负责额外的可切换参数。两者分开存储并不代表推理时完全分成两个互不相干的网络,而是由 PEFT 在目标层建立组合关系。

基础模型权重与 LoRA 适配器通过推理组合层连接的静态结构图
图1:基础模型、LoRA 适配器与推理组合层的关系说明图,不是运行截图。

用 PeftModel 把适配器挂到已有模型

如果基础模型已经由 Transformers 加载,PEFT 的显式写法最直观:先得到 base_model,再调用 PeftModel.from_pretrained。这一步不会把基础模型目录改写成适配器目录,适配器仍然可以单独替换。

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

# 先加载完整基础模型;它决定网络结构和词表兼容性
base_model_id = "your-org/your-base-model"
base_model = AutoModelForCausalLM.from_pretrained(
    base_model_id,
    device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(base_model_id)

# 再加载 LoRA 增量权重;这里的目录不是完整基础模型
adapter_path = "./adapters/customer-service"
model = PeftModel.from_pretrained(
    base_model,
    adapter_path,
    adapter_name="customer_service",
)

# 明确指定推理时启用的适配器,避免依赖隐含状态
model.set_adapter("customer_service")
model.eval()

这里的关键不是某个模型名,而是顺序:基础模型先存在,适配器再附着。device_map="auto" 只是大模型常见的设备分配选项;如果你的设备策略不同,应按部署环境调整。

也可以直接在 Transformers 模型上加载

较新的 Transformers 集成了适配器管理能力。若你不需要单独包装成 PeftModel,可以在已有的 Transformers 模型上直接调用 load_adapter。仓库或本地目录仍然需要包含适配器配置与权重。

from transformers import AutoModelForCausalLM

# 基础模型先加载,适配器随后附加到同一个模型对象
model = AutoModelForCausalLM.from_pretrained("your-org/your-base-model")
model.load_adapter(
    "./adapters/customer-service",
    adapter_name="customer_service",
)

# 只启用指定适配器;其它已加载适配器保持未激活
model.set_adapter("customer_service")

如果适配器的 adapter_config.json 中记录了基础模型信息,也可以使用支持自动检测的加载方式。但在服务端显式先加载基础模型更容易控制缓存、设备和多个适配器的生命周期。

多个 LoRA 适配器怎样切换

我在一个进程里同时放置“客服语气”和“代码解释”两个适配器时,最重要的经验是给它们稳定的名字。加载第二个适配器不会自动把第一个替换掉;真正改变当前推理行为的是 set_adapter。

# 两个适配器共用同一个基础模型,但保留各自的目录和名字
model.load_adapter("./adapters/customer-service", adapter_name="customer_service")
model.load_adapter("./adapters/code-explainer", adapter_name="code_explainer")

# 按请求或路由选择当前适配器;名称必须与加载时一致
model.set_adapter("code_explainer")

# 不需要适配器时关闭适配器,回到基础模型的行为
model.disable_adapters()

真实服务中不要把“当前适配器”藏在全局可变变量里再并发修改。可以按请求路由建立隔离的模型实例,或者在明确的串行临界区内切换;PEFT 的适配器名只解决权重选择,不自动解决你的并发状态管理。

卸载和删除不是同一件事

只想暂时去掉 LoRA 模块时,可以使用 unload();如果适配器以后不再需要,可以使用 delete_adapter 释放对应的适配器状态。unload() 返回新的模型对象,不能假设它会原地改变原变量。

# unload 返回卸载后的模型,必须接住返回值
base_like_model = model.unload()

# 如果只是不再需要某个命名适配器,可以删除它
# model.delete_adapter("customer_service")

# 后续如果还要使用另一个适配器,重新明确激活它
# model.set_adapter("code_explainer")

这里不要把 unload() 和“删除基础模型”混为一谈:基础模型仍然是模型主体,卸载的是附加的 LoRA 模块。对长期服务进程,还要结合显存引用、缓存和请求生命周期处理对象回收。

LoRA 适配器保持分离、切换、卸载与合并部署的生命周期对比图
图2:适配器切换、卸载与合并部署的关系说明图,不是运行截图。

什么时候保持分离,什么时候合并

保持分离适合多个任务共享一个基础模型、按请求切换风格或任务、以及仍在试验不同适配器的场景。它的代价是加载和管理路径更复杂,服务需要明确当前适配器及其设备位置。

如果模型已经定型、服务只需要一套固定行为,可以考虑 merge_and_unload(),把 LoRA 权重合入基础模型并返回一个不再携带适配器模块的模型。合并后切换适配器的灵活性会消失,因此不要在实验阶段过早合并。

# 只在确定要做固定单体部署时合并
merged_model = model.merge_and_unload()

# 合并后的模型可以按普通 Transformers 模型保存
merged_model.save_pretrained("./export/merged-model")
tokenizer.save_pretrained("./export/merged-model")

PEFT 文档还提供了在不合并的情况下加载不同适配器、设置活动适配器的方式;Diffusers 等其他模型管线也有自己的 load_lora_weights 和 set_adapters 接口,不能把文本模型的 API 原样套到图像管线。

排查分离加载失败的三个方向

现象优先检查处理思路
找不到适配器配置目录是否包含 adapter_config.json 和权重确认传入的是适配器目录,而不是训练缓存的上级目录
加载后尺寸或层不匹配基础模型、任务类型和 target modules换回训练该适配器时使用的兼容基础模型
切换后输出没有变化adapter_name、set_adapter 和 disable 状态先确认活动适配器,再排查权重是否确实属于当前基础模型

从经验上看,最稳妥的排查顺序是先确认“目录结构”,再确认“基础模型身份”,最后确认“当前激活状态”。不要一遇到输出异常就把 LoRA 合并;合并会让定位和回退都更麻烦。

结论:把基础模型当底座,把适配器当可替换策略

LoRA 分离加载可以归纳成一句话:基础模型先加载,适配器后附加,推理前显式选择,生命周期结束时再卸载或删除。需要多任务切换时保持分离,需要固定单体部署时再合并。这样既能复用基础模型,又能把适配器的兼容性、激活状态和部署取舍说清楚。

相关问题

  • LoRA 适配器能脱离基础模型单独推理吗?不能把它当完整模型使用,必须找到训练时兼容的基础模型。
  • 加载两个适配器会自动叠加吗?不会。先用唯一名称加载,再按 API 明确设置当前适配器或组合策略。
  • 什么时候使用 merge_and_unload?固定模型行为、减少运行时适配器管理时使用;需要频繁切换时保持分离更合适。
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Hugging Face Transformers 怎样只输出生成结果而不带输入提示词Hugging Face Transformers 怎样只输出生成结果而不带输入提示词
上一篇
Hugging Face Transformers 怎样只输出生成结果而不带输入提示词
Tokenizer 怎样处理超长输入的截断策略
下一篇
Tokenizer 怎样处理超长输入的截断策略
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    932次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    937次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1046次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1016次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    844次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码