自定义模型

Adapters库提供了一种简单的机制,用于将适配器方法集成到任何可用的Transformers模型中——包括自定义架构。虽然大多数适配器方法都通过此接口支持,但某些功能如Prefix Tuning尚不可用。

预支持模型

部分模型在库中已默认提供接口。对于这些模型,您只需使用适配器初始化模型,无需指定接口:

import adapters
from transformers import AutoModelForMaskedLM 

model = AutoModelForMaskedLM.from_pretrained("answerdotai/ModernBERT-base")  
adapters.init(model)

查看我们的模型概览页面,了解所有开箱即支持的模型。

添加对新模型的支持

如果我们尚未支持您的模型,您可以通过定义AdapterModelInterface的插件接口实例轻松添加适配器支持。以下是Gemma 2的示例:

import adapters
from adapters import AdapterModelInterface
from transformers import AutoModelForCausalLM

plugin_interface = AdapterModelInterface(
    adapter_methods=["lora", "reft"],
    model_embeddings="embed_tokens",
    model_layers="layers",
    layer_self_attn="self_attn",
    layer_cross_attn=None,
    attn_k_proj="k_proj",
    attn_q_proj="q_proj",
    attn_v_proj="v_proj",
    attn_o_proj="o_proj",
    layer_intermediate_proj="mlp.up_proj",
    layer_output_proj="mlp.down_proj",
)

model = AutoModelForCausalLM.from_pretrained("google/gemma-2-2b-it", token="<YOUR_TOKEN>")
adapters.init(model, interface=plugin_interface)

model.add_adapter("my_adapter", config="lora")

print(model.adapter_summary())

贡献接口

我们鼓励您与社区分享您的适配器接口!所有预支持模型的接口都可以在我们的interfaces.py文件中找到。您可以:

  • 提交一个拉取请求来直接添加您的接口

  • 如果您时间紧迫,只需将您的接口提交到GitHub issue,我们会为您添加

使用指南

让我们逐步解析上面示例中发生的事情:

1. 定义要插入模型的适配器方法:
adapter_methods参数是配置模型将支持哪些适配器的核心参数。 在这里,我们启用了所有基于LoRA和ReFT的适配器。 查看AdapterMethod了解此处可指定的有效选项。 访问Adapter Methods获取这些方法的详细说明。

2. 定义层和模块名称:
虽然所有Transformer层共享相似的基本组件,但它们的实现在模块名称等细节上可能有所不同。 因此,AdapterModelInterface需要将特定于模型的模块结构转换为适配器实现可以挂接的通用访问点集。 上述定义中的其余属性就是用于此目的。 它们的属性名称遵循一个通用语法,用于指定它们的位置和用途:

  • 第一个“_”之前的部分定义了应指定名称所基于的基础模块。

  • 第一个“_”之后的部分定义了功能组件。

例如,model_embeddings标识相对于基础模型(位置)的嵌入层(功能组件)。 layer_output_proj标识相对于一个Transformer层的FFN输出投影。 每个属性值可以指定参考模块的直接子模块("embed_token")或以参考模块开头的多级路径("mlp.down_proj")。

3. (可选) 扩展接口属性:
AdapterModelInterface中有一些属性仅对某些适配器方法是必需的。 在上面的LoRA和ReFT示例中我们不需要这些属性,但当同时支持瓶颈适配器时,完整接口将如下所示:

adapter_interface = AdapterModelInterface(
    adapter_types=["bottleneck", "lora", "reft"],
    model_embeddings="embed_tokens",
    model_layers="layers",
    layer_self_attn="self_attn",
    layer_cross_attn=None,
    attn_k_proj="k_proj",
    attn_q_proj="q_proj",
    attn_v_proj="v_proj",
    attn_o_proj="o_proj",
    layer_intermediate_proj="mlp.up_proj",
    layer_output_proj="mlp.down_proj",
    layer_pre_self_attn="input_layernorm",
    layer_pre_cross_attn=None,
    layer_pre_ffn="pre_feedforward_layernorm",
    layer_ln_1="post_attention_layernorm",
    layer_ln_2="post_feedforward_layernorm",
)

4. 在模型中初始化适配器方法: 最后,我们只需要在目标模型中应用定义的适配器集成。 这可以通过常用的adapters.init()方法实现:

adapters.init(model, interface=adapter_interface)

现在,你可以在适配后的模型实例上使用Adapters库的(几乎)所有功能了!

注意

某些模型如GPT-2或ModernBERT将查询层、值层和键层合并到单个张量中。在这种情况下,您必须设置attn_qkv_proj而非分别设置attn_k_projattn_q_projattn_v_proj

局限性

以下Adapters库的功能无法通过插件接口方式实现:

  • 前缀调优适配器

  • 并行组合块

  • XAdapterModel 类

  • 在瓶颈适配器配置中设置 original_ln_after=False(这会影响 AdapterPlusConfig