Buckets:

hf-doc-build/doc / transformers /main /pt /kernel_doc /writing_kernels.md
mishig's picture
|
download
raw
8.7 kB
# Escrevendo kernels
Este guia explica como escrever kernels que vão além de uma substituição `forward` sem estado. Ele aborda duas capacidades suportadas pela API estendida `KernelConfig`:
1. Transformação de parâmetros: o kernel espera pesos em um layout diferente do modelo original (por exemplo, parâmetros renomeados ou mesclados).
2. Fusão de módulos: o kernel substitui múltiplos módulos adjacentes por uma única implementação fundida.
Para kernels básicos (substituições de `forward` sem estado, sem alterações de parâmetros), consulte a documentação da biblioteca [kernels](https://github.com/huggingface/kernels).
## Padrão de duas classes
Qualquer kernel que carrega seus próprios parâmetros segue um padrão de duas classes.
- `KernelName`: contém apenas a passagem `forward`. A biblioteca `kernels` usa essa classe para kernelizar o modelo, pois não permite classes de kernel com estado.
- `KernelNameLayout`: um `nn.Module` que armazena os parâmetros e aplica monkey-patching no módulo original antes que o checkpoint seja carregado. Em tempo de execução, `kernelize` substitui seu `forward` pelo `forward` de `KernelName`. Você não precisa definir `forward`. O Transformers injeta um automaticamente com a mesma assinatura de `KernelName.forward`.
> [!IMPORTANT]
> A convenção de nomenclatura é rigorosa. A classe de layout deve ser nomeada `{KernelName}Layout` e definida no mesmo módulo de `KernelName`.
## Transformação de parâmetros
Use este padrão quando o kernel espera pesos com nomes diferentes ou em uma forma diferente da do checkpoint original do modelo.
A classe `KernelNameLayout` possui a mesma assinatura de `__init__` que o módulo que substitui e declara um atributo de classe `conversion_mapping` que informa ao Transformers como remapear as chaves do checkpoint para os novos nomes de parâmetros (veja [Carregamento dinâmico de pesos](../weightconverter) para mais detalhes).
```python
# layers.py
try:
from transformers import Concatenate, WeightConverter
from transformers.conversion_mapping import WeightRenaming
except ImportError:
Concatenate = WeightConverter = WeightRenaming = None
import torch
import torch.nn as nn
class CustomRMSNormLayout(nn.Module):
conversion_mapping = [...] # rules that remap checkpoint keys to the new parameter names
def __init__(self, hidden_size: int, eps: float = 1e-6):
super().__init__()
self.scale = nn.Parameter(torch.ones(hidden_size))
self.variance_epsilon = eps
class CustomRMSNorm(nn.Module):
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
input_dtype = hidden_states.dtype
hidden_states = hidden_states.to(torch.float32)
variance = hidden_states.pow(2).mean(-1, keepdim=True)
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
return self.scale * hidden_states.to(input_dtype)
```
```python
# __init__.py
from . import layers
```
> [!NOTE]
> A biblioteca `kernels` descobre as classes de kernel por meio de um módulo `layers` (seja `layers.py` ou `layers/__init__.py`). Defina as classes de kernel e de layout diretamente em `layers.py` e exponha o módulo `layers` a partir do `__init__.py` do pacote. O Transformers encontra `CustomRMSNormLayout` no mesmo módulo de `CustomRMSNorm`.
>
> Proteja as importações específicas do Transformers (`WeightConverter`, `Concatenate`, `WeightRenaming`) em `layers.py` para que o kernel também possa ser importado em ambientes em que o Transformers não está instalado.
Carregue este kernel passando o repositório e o nome da classe para [KernelConfig](/docs/transformers/main/pt/main_classes/kernels#transformers.KernelConfig). A chave é o nome da classe do módulo original do modelo. O valor aponta para a classe `KernelName` (não para o `Layout`) no repositório.
O valor é uma string `"owner/repo:ClassName"` ou uma tupla `(repo_string, metadata)`. No formato de tupla, passe `version` ou `revision` (pelo menos um) e, opcionalmente, `trust_remote_code`. Use `version` para uma versão principal do kernel ou `revision` para uma tag, branch ou commit. Defina `trust_remote_code=True` para carregar de fora da organização confiável `kernels-community`. Uma string simples tem como padrão `version=1` e `trust_remode_code=False`.
```python
from transformers import AutoModelForCausalLM, KernelConfig
kernel_config = KernelConfig({"RMSNorm": ("owner/my-kernel:CustomRMSNorm", {"trust_remote_code": True, "version": 1})})
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-0.6B",
use_kernels=True,
kernel_config=kernel_config,
device_map="auto",
)
```
Quando o modelo é carregado, o Transformers:
1. Carrega `CustomRMSNorm` do repositório e procura por `CustomRMSNormLayout` no mesmo módulo.
2. Aplica monkey-patch em cada `RMSNorm` do modelo com `CustomRMSNormLayout`.
3. Remapeia os pesos do checkpoint usando `conversion_mapping` para que sejam carregados nos novos nomes de parâmetros.
4. Chama `kernelize`, que substitui `CustomRMSNormLayout.forward` por `CustomRMSNorm.forward`.
## Fusão de módulos
Use este padrão quando um kernel substitui vários módulos adjacentes por uma única implementação fundida. Como o módulo fundido combina parâmetros de vários módulos originais, o `KernelNameLayout.__init__` recebe os módulos filhos instanciados, em vez dos argumentos de seus construtores.
```python
# layers.py
try:
from transformers import Concatenate, WeightConverter
from transformers.conversion_mapping import WeightRenaming
except ImportError:
Concatenate = WeightConverter = WeightRenaming = None
import torch
import torch.nn as nn
class RMSNormMLPLayout(nn.Module):
conversion_mapping = [...] # rules that remap checkpoint keys to the fused parameter names
def __init__(self, norm, mlp):
super().__init__()
self.variance_epsilon = norm.variance_epsilon
self.scale = nn.Parameter(torch.empty_like(norm.weight))
self.gate_up_proj = nn.Linear(
mlp.gate_proj.in_features,
mlp.gate_proj.out_features + mlp.up_proj.out_features,
bias=mlp.gate_proj.bias is not None,
device=mlp.gate_proj.weight.device,
dtype=mlp.gate_proj.weight.dtype,
)
self.down_proj = nn.Linear(
mlp.down_proj.in_features,
mlp.down_proj.out_features,
bias=mlp.down_proj.bias is not None,
device=mlp.down_proj.weight.device,
dtype=mlp.down_proj.weight.dtype,
)
self.act_fn = mlp.act_fn
class RMSNormMLP(nn.Module):
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
input_dtype = hidden_states.dtype
hidden_states = hidden_states.to(torch.float32)
variance = hidden_states.pow(2).mean(-1, keepdim=True)
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
hidden_states = self.scale * hidden_states.to(input_dtype)
gate, up = self.gate_up_proj(hidden_states).chunk(2, dim=-1)
return self.down_proj(self.act_fn(gate) * up)
```
```python
# __init__.py
from . import layers
```
Para fundir módulos, passe uma tupla de pares `(class_name, path_pattern)` como chave em `KernelConfig` em vez de uma string simples. Todos os padrões devem compartilhar o mesmo módulo pai (o Transformers funde os filhos nesse pai). O curinga `*` corresponde a qualquer segmento único de caminho.
```python
from transformers import AutoModelForCausalLM, KernelConfig
kernel_config = KernelConfig(
{
(
("RMSNorm", "model.layers.*.post_attention_layernorm"),
("MLP", "model.layers.*.mlp"),
): ("owner/my-kernel:RMSNormMLP", {"trust_remote_code": True, "version": 1}),
}
)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-0.6B",
use_kernels=True,
kernel_config=kernel_config,
device_map="auto",
)
```
Quando o modelo é carregado, o Transformers:
1. Carrega `RMSNormMLP` do repositório e localiza `RMSNormMLPLayout` no mesmo módulo.
2. Corresponde a cada camada do decoder em `model.layers.*` e constrói uma classe pai fundida cujo `__init__` chama `RMSNormMLPLayout(post_attention_layernorm, mlp)`.
3. Substitui o filho restante (`mlp`) por `nn.Identity()` para preservar a interface do módulo pai.
4. Remapeia os pesos do checkpoint usando `conversion_mapping`.
5. Chama `kernelize`, que substitui `RMSNormMLPLayout.forward` por `RMSNormMLP.forward`.
> [!TIP]
> A ordem dos pares na tupla de fusão determina a ordem dos argumentos passados para `KernelNameLayout.__init__`.

Xet Storage Details

Size:
8.7 kB
·
Xet hash:
0a2e7c0b3346e68aa7d051460fe737ce153d1a64d84d449e24957bf11759a74f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.