# Contribuição de modelo legado

> [!TIP]
> Tente primeiro adicionar novos modelos com uma abordagem mais [modular](./modular_transformers). Isso torna muito mais fácil contribuir com um modelo para o Transformers!

Muitos dos modelos em Transformers são contribuídos por desenvolvedores e pesquisadores. Como um projeto open-source em primeiro lugar, estamos empenhados em capacitar a comunidade a adicionar mais modelos de forma ativa e independente.

Ao adicionar um modelo ao Transformers, você aprenderá:

- mais sobre as melhores práticas de código aberto
- sobre a arquitetura de um modelo
- sobre os princípios de design do Transformers
- como testar modelos grandes de forma eficiente
- como usar utilitários do Python, como [Black](https://black.readthedocs.io/en/stable/) e [Ruff](https://docs.astral.sh/ruff/), para criar código limpo e legível

É um processo desafiador, porém recompensador.

Este guia mostrará como adicionar um modelo PyTorch de exemplo BrandNewLlama ao Transformers. Antes de começar, é uma boa ideia familiarizar-se com a biblioteca.

## Visão geral do Transformers

Transformers é uma biblioteca com opiniões firmes, possuindo sua própria filosofia e escolhas de design únicas. Essas escolhas nos ajudam a escalar e manter o Transformers de forma sustentável.

> [!TIP]
> Saiba mais sobre nossos princípios de design no documento [Philosophy](./philosophy).

Algumas dessas escolhas de design são:

- composição > sobreabstração
- código duplicado nem sempre é ruim, se ele melhorar significativamente a legibilidade e a acessibilidade
- os arquivos do modelo são autocontidos e todo o código necessário do modelo é encontrado no arquivo `modeling_mymodel.py`

Essas escolhas de design são importantes *para todos* que interagem com o modelo. É mais fácil de ler, entender e modificar.

Esta seção descreve como as classes de modelo e configuração interagem e o estilo de código do Transformers.

### Modelo e configuração

Todos os modelos do Transformers herdam de uma classe base [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel) e [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig). A configuração é o plano dos modelos.

Nunca há mais de dois níveis de abstração para qualquer modelo, a fim de manter o código legível. O modelo de exemplo aqui, BrandNewLlama, herda de `BrandNewLlamaPreTrainedModel` e [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel). É importante que um novo modelo dependa apenas de [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel) para que possa usar os métodos [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) e [save_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.save_pretrained).

Outras funções importantes, como o método forward, são definidas no arquivo `modeling.py`.

Cabeças de modelo específicas (por exemplo, classificação de sequência ou modelagem de linguagem) devem chamar o modelo base no caminho de encaminhamento, em vez de herdar dele, para manter a abstração baixa.

Novos modelos exigem uma configuração, por exemplo `BrandNewLlamaConfig`, que é armazenada como um atributo de [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel).

```py
model = BrandNewLlamaModel.from_pretrained("username/brand_new_llama")
model.config
```

[PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig) fornece os métodos [from_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.from_pretrained) e [save_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.save_pretrained).

Ao usar [PreTrainedModel.save_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.save_pretrained), ele chama automaticamente [PreTrainedConfig.save_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.save_pretrained) para que o modelo e a configuração sejam salvos juntos.

Um modelo é salvo em um arquivo `model.safetensors` e uma configuração é salva em um arquivo `config.json`.

### Estilo de código

O Transformers prefere um código limpo e legível a um estilo de código mais abstrato. Algumas das escolhas de estilo de código incluem:

- O código deve ser acessível a usuários que não falam inglês. Escolha nomes de variáveis descritivos e evite abreviações. Por exemplo, "activation" é preferível a "act". Nomes de variáveis com uma única letra são fortemente desencorajados, a menos que se trate de um índice em um laço for.

- Código explícito é preferível — mesmo que seja mais longo — a código mais curto.

- Evite criar subclasses de [nn.Sequential](https://pytorch.org/docs/stable/generated/torch.nn.Sequential.html). Em vez disso, crie subclasses de [nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module) para que o código possa ser depurado rapidamente com declarações de impressão ou pontos de interrupção.

- As assinaturas de funções devem ser anotadas com tipos. Caso contrário, use nomes de variáveis claros para que sejam mais compreensíveis.

## Problema na adição de novo modelo

Abra uma issue de [Adição de novo modelo](https://github.com/huggingface/transformers/issues/new?assignees=&labels=New+model&template=new-model-addition.yml) para adicionar um modelo específico.

> [!TIP]
> Filtre pelo rótulo [New model](https://github.com/huggingface/transformers/labels/New%20model) no GitHub para visualizar e adicionar solicitações de modelos existentes.

Agora é um bom momento para se familiarizar com o BrandNewLlama. É útil ler o paper de pesquisa de um modelo para entender seu design técnico e implementação. Você não precisa se preocupar muito com os detalhes teóricos. Em vez disso, foque nos detalhes práticos. Use as perguntas abaixo para orientar sua leitura.

- Que tipo de modelo é o BrandNewLlama? É um modelo encoder, decoder ou encoder-decoder?
- Para quais tarefas o BrandNewLlama pode ser utilizado?
- O que torna o BrandNewLlama diferente de outros modelos?
- Quais modelos em Transformers são mais semelhantes ao BrandNewLlama?
- Qual tokenizer o BrandNewLlama usa?

Além de aprender mais sobre o seu modelo, use as dicas abaixo para ajudá-lo a adicionar um modelo mais rapidamente.

> [!TIP]
> Cada contribuidor tem um estilo e um fluxo de trabalho únicos para adicionar modelos ao Transformers. Como exemplo, veja como o [Gemma](https://github.com/huggingface/transformers/pull/29167) foi adicionado.

- Não reinvente a roda! Tire um tempo para explorar modelos e tokenizadores existentes para ver o que você pode copiar e reutilizar. [Grep](https://www.gnu.org/software/grep/) e [ripgrep](https://github.com/BurntSushi/ripgrep) são ótimas ferramentas para isso.
- Isso é mais um desafio de engenharia do que de ciência. Foque nos aspectos mais práticos (por exemplo, configurar um ambiente de depuração eficiente) em vez dos aspectos teóricos do modelo.
- Não tenha vergonha de pedir ajuda! Estamos aqui para te apoiar. 🤗

## Ambiente de desenvolvimento

Clique no botão **Fork** no repositório [Transformers](https://github.com/huggingface/transformers) para criar sua própria cópia para trabalhar. Clone o repositório para o seu disco local e adicione o repositório base como remoto.

```bash
git clone https://github.com/[your Github handle]/transformers.git
cd transformers
git remote add upstream https://github.com/huggingface/transformers.git
```

Crie um ambiente virtual e execute uma [instalação editável](./installation#editable-install) da biblioteca com as dependências "dev" ou de desenvolvimento.

```bash
python -m venv .env
source .env/bin/activate
pip install -e ".[dev]"
```

Devido ao número de dependências opcionais à medida que o Transformers cresce, esse comando pode falhar. Nesse caso, instale as dependências "quality". Certifique-se também de ter um framework de deep learning instalado.

```bash
pip install -e ".[quality]"
```

Volte para o diretório pai e clone e instale o repositório original BrandNewLlama.

```bash
git clone https://github.com/org_that_created_brand_new_llama_org/brand_new_llama.git
cd brand_new_bert
pip install -e .
```

Volte para o seu clone do Transformers para começar a portar o BrandNewLlama.

```bash
cd transformers
```

Existem dois ambientes de depuração possíveis para executar o modelo original: um notebook ([Google Colab](https://colab.research.google.com/notebooks/intro.ipynb) ou [Jupyter](https://jupyter.org/)) ou um script Python local.

> [!WARNING]
> Não recomendamos configurar um ambiente de GPU para executar o modelo original, pois isso pode ser caro. Em vez disso, trabalhe primeiro em um ambiente de CPU para verificar se o modelo funciona no Transformers. Depois que ele funcionar, você pode verificá-lo em uma GPU.

Notebooks são ótimos para executar código célula por célula, o que pode ajudar a separar componentes lógicos uns dos outros. Também podem acelerar os ciclos de depuração, pois os resultados intermediários podem ser armazenados. Você também pode compartilhar notebooks ao trabalhar com outros colaboradores.

A desvantagem é que, se você não está acostumado a eles, pode levar algum tempo para se adaptar.

> [!TIP]
> Se a arquitetura do modelo for idêntica à de um modelo existente, pule para [converter o checkpoint](#convert-checkpoints-to-transformers), pois você pode reutilizar a arquitetura do modelo existente.

Execute o comando abaixo para iniciar e concluir o questionário com algumas informações básicas sobre o novo modelo. Este comando agiliza o processo ao gerar automaticamente parte do código do modelo que você precisará adaptar.

```bash
transformers add-new-model-like
```

## Crie um pull request

Antes de começar a adaptar o código, crie um pull request para acompanhar seu progresso e receber feedback da equipe do Transformers. Dê ao seu pull request o título **[WIP] Add BrandNewLlama** para deixar claro que se trata de um trabalho em andamento.

Crie um branch com um nome descritivo a partir do seu branch principal.

```bash
git checkout -b add_brand_new_bert
```

Commita o código e, em seguida, faça o fetch e o rebase na branch principal.

```bash
git add .
git commit
git fetch upstream
git rebase upstream/main
```

Envie as alterações para o seu branch e clique em **Compare & pull request** para abrir um pull request no GitHub. Abra o pull request como *draft* para indicar que está em andamento.

```bash
git push -u origin a-descriptive-name-for-my-changes
```

Inclua os membros relevantes da equipe do Hugging Face adicionando seus handles do GitHub na pull request para perguntas, feedback, comentários e revisões. Direcione os membros da equipe para partes específicas do código que você deseja ao clicar na aba **Files changed** e, em seguida, clicar em **+** à esquerda do número da linha para adicionar um comentário. Quando uma pergunta ou problema for resolvido, clique em **Resolve** para indicar que a questão foi resolvida. Isso mantém a conversa organizada e limpa.

Lembre-se de fazer commit e push do seu trabalho periodicamente e de atualizá-lo com a branch main atual.

```bash
git fetch upstream
git merge upstream/main
```

## Checkpoint original

Tome um tempo para trabalhar na implementação original do modelo primeiro, a fim de entender como ele funciona.

Isso pode ser difícil se o repositório original do modelo estiver com documentação insuficiente ou se a base de código for complexa. Mas você deve usar isso como motivação para implementar o modelo no Transformers. Sua contribuição torna o modelo mais acessível e fácil de usar para todos!

Oriente-se pelo repositório original executando as seguintes etapas.

- Localize os pesos pré-treinados.
- Descubra como carregar pesos pré-treinados no modelo.
- Descubra como executar o tokenizer de forma independente do modelo.
- Faça o rastreamento de uma passagem para frente para entender quais classes e funções são necessárias. Provavelmente, estas são as únicas classes e funções que você terá que implementar.
- Localize todos os componentes importantes (classe do modelo, subclasses do modelo, camada de autoatenção, etc.) do modelo.
- Descubra como depurar o modelo no repositório original. Adicione declarações de impressão, use depuradores interativos como [ipdb](https://github.com/gotcha/ipdb) ou um ambiente de desenvolvimento integrado (IDE) eficiente como [PyCharm](https://www.jetbrains.com/pycharm/).

O último ponto é especialmente importante, pois você precisará de um entendimento aprofundado do que está acontecendo dentro do modelo original antes de poder reimplementá-lo no Transformers. Sinta-se à vontade para abrir issues e pull requests no repositório original caso encontre algum problema.

Um bom primeiro passo é carregar um checkpoint pré-treinado *pequeno* e tentar reproduzir uma única passagem direta com um vetor de exemplo de entradas inteiras. Por exemplo, em pseudocódigo, isso poderia se parecer com o seguinte.

```py
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
input_ids = [0, 4, 5, 2, 3, 7, 9]  # vector of input ids
original_output = model.generate(input_ids)
```

### Depuração

Se você encontrar problemas, precisará escolher uma das seguintes estratégias de depuração, dependendo da base de código dos modelos originais.

Essa estratégia se baseia em dividir o modelo original em subcomponentes menores, como quando o código pode ser executado facilmente em modo eager. Embora seja mais difícil, essa abordagem apresenta algumas vantagens.

1. É mais fácil, depois, comparar o modelo original com a sua implementação. Você pode verificar automaticamente se cada componente individual corresponde ao seu componente correspondente na implementação do Transformers. Isso é melhor do que depender de uma comparação visual baseada em declarações de impressão.
2. É mais fácil portar componentes individuais em vez do modelo inteiro.
3. É mais fácil entender como um modelo funciona ao dividi-lo em partes menores.
4. É mais fácil prevenir regressões em uma etapa posterior, ao modificar seu código, graças aos testes por componente.

> [!TIP]
> Consulte as [verificações de integração](https://gist.github.com/LysandreJik/db4c948f6b4483960de5cbac598ad4ed) do ELECTRA para um bom exemplo de como decompor um modelo em componentes menores.

Essa estratégia é viável quando a base de código original é muito complexa, permite apenas que componentes intermediários sejam executados em modo compilado, ou quando separar o modelo em subcomponentes menores é muito demorado (ou até mesmo impossível).

Por exemplo, a implementação do [T5](https://github.com/tensorflow/mesh/tree/master/mesh_tensorflow) no MeshTensorFlow é complexa demais e não oferece uma maneira simples de decompor o modelo em seus subcomponentes. Nessa situação, você terá que recorrer à verificação de declarações de impressão.

Independentemente da estratégia escolhida, recomenda-se depurar primeiro as camadas iniciais e por último as camadas finais. Obtenha a saída, seja por meio de instruções de impressão ou de funções de subcomponentes, das seguintes camadas, nesta ordem.

1. ids de entrada passados para o modelo
2. embeddings de palavras
3. entrada da primeira camada do Transformer
4. saída da primeira camada do Transformer
5. saída das seguintes n-1 camadas do Transformer
6. saída do modelo inteiro

Os ids de entrada devem ser apenas um array de inteiros, como `input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19]`.

As saídas de camadas geralmente consistem em arrays de ponto flutuante multidimensionais.

```py
[[
 [-0.1465, -0.6501,  0.1993,  ...,  0.1451,  0.3430,  0.6024],
 [-0.4417, -0.5920,  0.3450,  ..., -0.3062,  0.6182,  0.7132],
 [-0.5009, -0.7122,  0.4548,  ..., -0.3662,  0.6091,  0.7648],
 ...,
 [-0.5613, -0.6332,  0.4324,  ..., -0.3792,  0.7372,  0.9288],
 [-0.5416, -0.6345,  0.4180,  ..., -0.3564,  0.6992,  0.9191],
 [-0.5334, -0.6403,  0.4271,  ..., -0.3339,  0.6533,  0.8694]]],
```

A saída de cada modelo do Transformers deve ter uma precisão ou tolerância de erro de *1e-3*. Isso leva em conta as diferenças de saída que surgem do uso de um framework de biblioteca diferente. Compare as saídas intermediárias do modelo original com a implementação do Transformers para garantir que sejam praticamente idênticas. Ter um ambiente de depuração *eficiente* é crucial para esta etapa.

Aqui estão algumas dicas para um ambiente de depuração eficiente.

- Para depurar resultados intermediários, depende do framework de machine learning que o repositório original do modelo está usando. Para PyTorch, você deve escrever um script para decompor o modelo original em subcomponentes menores para recuperar os valores intermediários.

- É mais rápido depurar com um checkpoint pré-treinado menor do que com um checkpoint maior, no qual a passagem para frente leva mais de 10 segundos. Se apenas checkpoints grandes estiverem disponíveis, crie um modelo fictício com pesos inicializados aleatoriamente e salve esses pesos para comparar com a implementação do Transformers.

- Encontre a maneira mais simples de chamar a passagem para frente do modelo. Idealmente, essa função (que pode ser chamada de `predict`, `evaluate`, `forward` ou `__call__`) deve chamar a passagem para frente apenas *uma vez*. É mais difícil depurar uma função que chama a passagem para frente várias vezes.

- Separe a tokenização do passo de propagação direta. Localize onde a entrada em string é convertida em ids de entrada no passo de propagação direta e comece por aqui. Você pode precisar criar um script pequeno ou modificar o código original para inserir diretamente os ids de entrada em vez de uma string de entrada.

- Certifique-se de que o modelo *não* esteja em modo de treinamento. Isso pode gerar saídas aleatórias devido a múltiplas camadas de dropout no modelo. A passagem direta no seu ambiente de depuração deve ser *determinística* para que as camadas de dropout não sejam utilizadas.

Quando você já consegue executar o checkpoint original, está pronto para começar a adaptar o código do modelo para o Transformers.

## Adapte o código do modelo

O comando `transformers add-new-model-like` deve ter gerado um arquivo de modelo e configuração.

- `src/transformers/models/brand_new_llama/modeling_brand_new_llama.py`
- `src/transformers/models/brand_new_llama/configuration_brand_new_llama.py`

O código gerado automaticamente no arquivo `modeling.py` tem a mesma arquitetura do Llama se você respondeu que é um modelo apenas de decodificador, ou terá a mesma arquitetura do BART se você respondeu que é um modelo codificador-decodificador. O código gerado é apenas um ponto de partida. Com base na sua pesquisa sobre o novo modelo, você precisará implementar essas mudanças específicas adaptando o código gerado. Isso pode envolver alterações na camada de autoatenção, na ordem da camada de normalização, entre outras.

### Inicialização do modelo

Neste ponto, seu código não precisa estar limpo ou até mesmo totalmente correto. É mais eficiente criar rapidamente um primeiro rascunho e, em seguida, melhorá-lo de forma iterativa. O mais importante é que seu modelo possa ser instanciado a partir do Transformers. O comando abaixo cria um modelo a partir da configuração com pesos aleatórios, verificando se o método `__init__` funciona.

```py
from transformers import BrandNewLlama, BrandNewLlamaConfig
model = BrandNewLlama(BrandNewLlamaConfig())
```

A inicialização aleatória ocorre no método `_init_weights` de `BrandNewLlamaPreTrainedModel`. Todos os módulos folha são inicializados com base nas variáveis da configuração. Use os auxiliares do módulo `transformers.initialization` para definir os valores, em vez de chamar operações in-place diretamente em um peso ou em seu `.data`.

```py
from transformers import initialization as init

def _init_weights(self, module):
    """Initialize the weights"""
    if isinstance(module, nn.Linear):
        init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
        if module.bias is not None:
            init.zeros_(module.bias)
    elif isinstance(module, nn.Embedding):
        init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
        if module.padding_idx is not None:
            init.zeros_(module.weight[module.padding_idx])
    elif isinstance(module, nn.LayerNorm):
        init.zeros_(module.bias)
        init.ones_(module.weight)
```

Sempre inicialize os pesos por meio dos auxiliares de `transformers.initialization`. Operações in-place, como `module.bias.zero_()` ou qualquer coisa que toque em `module.weight.data`, ignoram o `_is_hf_initialized`, que sinaliza quais parâmetros já foram carregados. O [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) executa o `_init_weights` após carregar o checkpoint, de modo que operações in-place sobrescrevem silenciosamente os pesos carregados com valores aleatórios. Isso é imposto para modelos do Transformers pela regra [TRF012](./modeling_rules#trf012).

> [!WARNING]
> Durante o [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained), os modelos geralmente são inicializados no dispositivo `meta`. O loader recria os buffers não persistentes como tensores vazios, de modo que os valores atribuídos em `__init__` não são preservados. Inicialize esses buffers em `_init_weights` para que tenham os valores corretos após o carregamento. Para um exemplo, veja como o BERT inicializa seus IDs de posição e IDs de tipo de token.

O esquema de inicialização pode ter um aspecto diferente se você precisar adaptá-lo ao seu modelo. Um submódulo com seu próprio método `reset_parameters` pode chamá-lo diretamente. Por exemplo, [Wav2Vec2ForPreTraining](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2ForPreTraining) inicializa [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html) em suas duas últimas camadas lineares. A chamada é segura porque [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) aplica patches nas funções subjacentes de `torch.nn.init` para respeitar a flag `_is_hf_initialized` enquanto executa `_init_weights`, de modo que os pesos carregados não sejam sobrescritos.

```py
def _init_weights(self, module):
    """Initialize the weights"""
    if isinstance(module, Wav2Vec2ForPreTraining):
        module.project_hid.reset_parameters()
        module.project_q.reset_parameters()
```

### Converter checkpoints para Transformers

O checkpoint original deve ser convertido para um checkpoint compatível com o Transformers.

> [!TIP]
> Tente procurar por um script de conversão existente para copiar, adaptar e reutilizar para o seu modelo!
>
> - Se você está portando um modelo do TensorFlow para o PyTorch, um bom ponto de partida pode ser o [script de conversão](https://github.com/huggingface/transformers/blob/7acfa95afb8194f8f9c1f4d2c6028224dbed35a2/src/transformers/models/bert/modeling_bert.py#L91) do BERT. - Se você está portando um modelo do PyTorch para o PyTorch, um bom ponto de partida pode ser o [script de conversão](https://github.com/huggingface/transformers/blob/main/src/transformers/models/bart/convert_bart_original_pytorch_checkpoint_to_pytorch.py) do BART.

Verifique se **todos** os pesos necessários foram inicializados e imprima todos os pesos do checkpoint que não foram usados na inicialização, para garantir que o modelo foi convertido corretamente.

Você pode encontrar declarações de forma incorretas ou atribuições de nomes erradas durante a conversão. Isso provavelmente se deve a parâmetros incorretos em `BrandNewLlamaConfig`, à arquitetura errada, a um bug no método `init` da sua implementação, ou à necessidade de transpor um dos pesos do checkpoint.

Continue iterando na seção [Adaptar o código do modelo](#adapt-the-model-code) até que todos os pesos do checkpoint sejam carregados corretamente. Assim que você conseguir carregar um checkpoint no seu modelo, salve-o em uma pasta. Essa pasta deve conter um arquivo `model.safetensors` e um arquivo `config.json`.

```py
model.save_pretrained("/path/to/converted/checkpoint/folder")
```

Para auxiliar na conversão, a próxima seção descreve brevemente como os modelos do PyTorch armazenam e definem os pesos e os nomes das camadas.

#### Pesos e nomes das camadas do PyTorch

É útil criar um modelo básico do PyTorch para entender como os nomes das camadas são definidos e como os pesos são inicializados.

```py
from torch import nn

class SimpleModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.dense = nn.Linear(10, 10)
        self.intermediate = nn.Linear(10, 10)
        self.layer_norm = nn.LayerNorm(10)
```

Os nomes das camadas do PyTorch são definidos pelo nome do atributo da classe da camada (`dense`, `intermediate`, `layer_norm`). Crie uma instância de `SimpleModel` para preencher todas as camadas com pesos aleatórios.

```py
model = SimpleModel()
print(model)
SimpleModel(
  (dense): Linear(in_features=10, out_features=10, bias=True)
  (intermediate): Linear(in_features=10, out_features=10, bias=True)
  (layer_norm): LayerNorm((10,), eps=1e-05, elementwise_affine=True)
)
```

Os valores de peso de uma camada específica são inicializados aleatoriamente.

```py
print(model.dense.weight.data)
tensor([[-0.0818,  0.2207, -0.0749, -0.0030,  0.0045, -0.1569, -0.1598,  0.0212,
         -0.2077,  0.2157],
        [ 0.1044,  0.0201,  0.0990,  0.2482,  0.3116,  0.2509,  0.2866, -0.2190,
          0.2166, -0.0212],
        [-0.2000,  0.1107, -0.1999, -0.3119,  0.1559,  0.0993,  0.1776, -0.1950,
         -0.1023, -0.0447],
        [-0.0888, -0.1092,  0.2281,  0.0336,  0.1817, -0.0115,  0.2096,  0.1415,
         -0.1876, -0.2467],
        [ 0.2208, -0.2352, -0.1426, -0.2636, -0.2889, -0.2061, -0.2849, -0.0465,
          0.2577,  0.0402],
        [ 0.1502,  0.2465,  0.2566,  0.0693,  0.2352, -0.0530,  0.1859, -0.0604,
          0.2132,  0.1680],
        [ 0.1733, -0.2407, -0.1721,  0.1484,  0.0358, -0.0633, -0.0721, -0.0090,
          0.2707, -0.2509],
        [-0.1173,  0.1561,  0.2945,  0.0595, -0.1996,  0.2988, -0.0802,  0.0407,
          0.1829, -0.1568],
        [-0.1164, -0.2228, -0.0403,  0.0428,  0.1339,  0.0047,  0.1967,  0.2923,
          0.0333, -0.0536],
        [-0.1492, -0.1616,  0.1057,  0.1950, -0.2807, -0.2710, -0.1586,  0.0739,
          0.2220,  0.2358]]).
```

No script de conversão, os pesos aleatórios devem ser substituídos pelos pesos exatos da camada correspondente no checkpoint original.

```py
# retrieve matching layer weights with recursive algorithm
layer_name = "dense"
pretrained_weight = array_of_dense_layer

model_pointer = getattr(model, "dense")
model_pointer.weight.data = torch.from_numpy(pretrained_weight)
```

Verifique se os pesos inicializados aleatoriamente e os pesos do checkpoint pré-treinado correspondente têm a mesma **forma** e o mesmo **nome**. Adicione declarações assert para a forma e imprima os nomes dos pesos do checkpoint.

```py
assert (
    model_pointer.weight.shape == pretrained_weight.shape
), f"Pointer shape of random weight {model_pointer.shape} and array shape of checkpoint weight {pretrained_weight.shape} mismatched"

logger.info(f"Initialize PyTorch weight {layer_name} from {pretrained_weight.name}")
```

Quando a forma ou o nome não correspondem, é possível que você tenha atribuído o peso de checkpoint incorreto a uma camada inicializada aleatoriamente. Uma forma incorreta pode ocorrer porque os parâmetros do `BrandNewLlama` não correspondem exatamente aos parâmetros dos modelos originais. Mas também pode ser que a implementação da camada do PyTorch exija que os pesos sejam transpostos primeiro.

### Implemente a passagem direta

O passo de propagação para frente (forward pass) deve ser implementado em seguida, caso o modelo seja carregado corretamente. Ele recebe algumas entradas e retorna a saída do modelo.

```py
model = BrandNewLlamaModel.from_pretrained("/path/to/converted/checkpoint/folder")
input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19]
output = model.generate(input_ids).last_hidden_states
```

Não se desanime se o seu forward pass não for idêntico à saída do modelo original ou se retornar um erro. Verifique se o forward pass não lança nenhum erro. Isso geralmente ocorre porque as dimensões estão incorretas ou porque o tipo de dados errado é usado ([torch.long](https://pytorch.org/docs/stable/generated/torch.Tensor.long.html) em vez de [torch.float32](https://pytorch.org/docs/stable/tensors.html)).

A saída deve ter uma precisão de *1e-3*. Certifique-se de que as formas da saída e os valores de saída sejam idênticos. Razões comuns para as saídas não serem idênticas incluem:

- Algumas camadas não foram adicionadas (camada de ativação ou conexão residual).
- A matriz de incorporação de palavras não está vinculada.
- Os embeddings posicionais incorretos são usados porque a implementação original inclui um deslocamento.
- O Dropout é aplicado durante a passagem direta. Corrija esse erro garantindo que `model.training` seja `False` e passando `self.training` para [torch.nn.functional.dropout](https://pytorch.org/docs/stable/nn.functional.html?highlight=dropout#torch.nn.functional.dropout).

Compare o forward pass do modelo original com a sua implementação para verificar se há alguma diferença. Idealmente, depure e imprima as saídas intermediárias de ambas as implementações do forward pass para identificar onde a implementação original difere da sua.

1. Certifique-se de que o `input_ids` codificado em ambos os implementações sejam idênticos.
2. Verifique se as saídas da primeira transformação de `input_ids` (geralmente os embeddings de palavras) são idênticas e prossiga até a última camada.

Qualquer diferença entre as duas implementações deve indicar um bug na sua implementação.

Uma das melhores estratégias é adicionar muitos comandos de impressão nas mesmas posições em ambas as implementações e, em seguida, removê-los sucessivamente quando eles exibirem valores idênticos para as saídas intermediárias.

Quando ambas as implementações produzem a mesma saída, verifique se as saídas estão dentro de uma precisão de *1e-3*.

```py
torch.allclose(original_output, output, atol=1e-3)
```

Esta é, em geral, a parte mais difícil do processo. Parabéns se você chegou até aqui!

E, se você estiver travado ou com dificuldade nessa etapa, não hesite em pedir ajuda no seu pull request.

### Adicionar testes de modelo

Enquanto o modelo funciona, você ainda precisa adicionar testes para garantir que ele seja compatível com o Transformers. Os testes são importantes porque ajudam os usuários a entender seu trabalho ao examinar testes específicos e porque impedem que seu modelo quebre no futuro caso sejam feitas alterações.

O [Cookiecutter](https://cookiecutter.readthedocs.io/en/stable/) deve ter adicionado um arquivo de teste para o seu modelo. Execute o arquivo de teste abaixo para garantir que todos os testes comuns sejam aprovados.

```bash
pytest tests/models/brand_new_llama/test_modeling_brand_new_llama.py
```

Os testes de integração devem ser adicionados primeiro, pois cumprem a mesma função dos scripts de depuração que você usou anteriormente para implementar o novo modelo no Transformers. Um modelo para esses testes de modelo, `BrandNewLlamaModelIntegrationTests`, foi adicionado pelo Cookiecutter e deve ser preenchido. Para garantir que ele seja aprovado, execute o seguinte comando.

```bash
RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
```

```bash
SET RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
```

Todos os recursos exclusivos do BrandNewLlama devem ser testados em um teste separado sob `BrandNewLlamaModelTester/BrandNewLlamaModelTest`. Esse teste costuma ser negligenciado, mas é extremamente importante porque:

- ajuda a transferir para a comunidade o conhecimento adquirido durante o processo, demonstrando como os recursos inovadores do modelo funcionam
- contribuidores futuros podem testar rapidamente as alterações no modelo executando esses testes especiais

## Implementar tokenizer

> [!TIP]
> Recomendamos adicionar um tokenizer rápido ([PreTrainedTokenizerFast](/docs/transformers/main/pt/main_classes/tokenizer#transformers.TokenizersBackend)) para oferecer aos usuários o melhor desempenho. Sinta-se à vontade para marcar [@ArthurZucker](https://github.com/ArthurZucker) ou [@itazap](https://github.com/itazap) na sua PR para obter ajuda sobre como adicionar [PreTrainedTokenizerFast](/docs/transformers/main/pt/main_classes/tokenizer#transformers.TokenizersBackend).

Com o modelo resolvido, é hora de focar no tokenizer. O tokenizer deve ser idêntico ou muito semelhante a um tokenizer existente em Transformers.

Encontre e carregue o arquivo original do tokenizer na sua implementação. Crie um script no repositório original que recebe uma string e retorna os `input_ids`. O pseudocódigo deve ser semelhante ao código abaixo.

```py
input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
input_ids = model.tokenize(input_str)
```

Você pode precisar procurar no repositório original para encontrar a função de tokenizer correta ou modificar o tokenizer existente em seu clone do repositório original para que ele retorne apenas `input_ids`. O script para o seu tokenizer deve se parecer com o seguinte.

```py
from transformers import BrandNewLlamaTokenizer

input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
tokenizer = BrandNewLlamaTokenizer.from_pretrained("/path/to/tokenizer/folder/")
input_ids = tokenizer(input_str).input_ids
```

Quando ambas as implementações possuem o mesmo `input_ids`, adicione um arquivo de teste do tokenizer. Este arquivo é análogo aos arquivos de teste de modelagem. Os arquivos de teste do tokenizer devem conter alguns testes de integração com valores fixos.

## Implementar processador de imagem

> [!TIP]
> Os processadores de imagem agora utilizam uma arquitetura baseada em backends. O backend padrão é o [TorchvisionBackend](/docs/transformers/main/pt/main_classes/image_processor#transformers.TorchvisionBackend), que utiliza a biblioteca [torchvision](https://pytorch.org/vision/stable/index.html) e pode executar o processamento de imagens na GPU. Um backend alternativo PIL/NumPy ([PilBackend](/docs/transformers/main/pt/main_classes/image_processor#transformers.PilBackend)) também é fornecido. Ambos os backends são importados de `image_processing_backends`. Sinta-se à vontade para marcar [@yonigozlan](https://github.com/yonigozlan) para obter ajuda.

Embora este exemplo não inclua um processador de imagens, você pode precisar implementar um se o seu modelo exigir entradas de imagem. O processador de imagens é responsável por converter as imagens em um formato adequado para o seu modelo. Antes de implementar um novo, verifique se um processador de imagens existente na biblioteca Transformers pode ser reutilizado, pois muitos modelos compartilham técnicas semelhantes de processamento de imagens. Observe que você também pode usar [modular](./modular_transformers) para processadores de imagens para reutilizar componentes existentes.

Se você precisar implementar um novo processador de imagem, cada modelo possui dois arquivos de processador:

- `image_processing_<model>.py`: o processador **padrão** baseado em torchvision (`<Model>ImageProcessor`), que herda de [TorchvisionBackend](/docs/transformers/main/pt/main_classes/image_processor#transformers.TorchvisionBackend). Este substitui o antigo processador "fast".
- `image_processing_pil_<model>.py`: o processador alternativo PIL/NumPy (`<Model>ImageProcessorPil`), que herda de [PilBackend](/docs/transformers/main/pt/main_classes/image_processor#transformers.PilBackend). Ele substitui o antigo processador "slow".

O arquivo de backend do torchvision também define qualquer classe de kwargs personalizada que o arquivo PIL importa. Ambos os arquivos usam o decorador `@auto_docstring` — não adicione docstrings de classe manuais. Consulte o [IMAGE_PROCESSOR_REFACTORING_GUIDE.md](https://github.com/huggingface/transformers/blob/main/IMAGE_PROCESSOR_REFACTORING_GUIDE.md) para um passo a passo e exemplos completos.

Adicione testes para o processador de imagens em `tests/models/your_model_name/test_image_processing_your_model_name.py`. Esses testes devem ser semelhantes aos de outros processadores de imagens e devem verificar se o processador de imagens trata corretamente as entradas de imagem. Se o seu processador de imagens incluir recursos ou métodos de processamento exclusivos, certifique-se de adicionar testes específicos para eles também.

## Implementar processador

Se o seu modelo aceita múltiplas modalidades, como texto e imagens, você precisa adicionar um processador. O processador centraliza o pré-processamento das diferentes modalidades antes de passá-las ao modelo.

O processador deve chamar os processadores específicos de cada modalidade dentro da função `__call__` para tratar cada tipo de entrada corretamente. Certifique-se de verificar os processadores existentes na biblioteca para entender sua estrutura esperada. O Transformers usa a seguinte convenção na assinatura da função `__call__`.

```python
def __call__(
    self,
    images: ImageInput = None,
    text: Union[TextInput, PreTokenizedInput, list[TextInput], list[PreTokenizedInput]] = None,
    audio=None,
    videos=None,
    **kwargs: Unpack[YourModelProcessorKwargs],
) -> BatchFeature:
    ...
```

`YourModelProcessorKwargs` é um `TypedDict` que inclui todos os argumentos de processamento típicos e quaisquer argumentos extras que um processador específico possa exigir.

Adicione testes para o processador em `tests/models/your_model_name/test_processor_your_model_name.py`. Esses testes devem ser semelhantes aos de outros processadores e devem verificar se o processador trata corretamente as diferentes modalidades.

## Testes de integração

Agora que você tem um modelo e um tokenizer, adicione testes de integração de ponta a ponta para o modelo e o tokenizer em `tests/models/brand_new_llama/test_modeling_brand_new_llama.py`.

O teste deve fornecer um exemplo significativo de texto-para-texto para demonstrar que o modelo funciona como esperado. Por exemplo, você pode incluir um par de tradução de origem para destino, um par de artigo para resumo ou um par de pergunta para resposta.

Se o checkpoint não foi ajustado em uma tarefa de nível inferior, os testes do modelo são suficientes.

Por fim, tente garantir que seus testes possam ser executados em uma GPU adicionando declarações `.to(self.device)` aos tensores internos dos modelos. Se você não tiver acesso a uma GPU, podemos cuidar disso por você.

## Adicionar documentação

Seu modelo só é útil se os usuários souberem como usá-lo. Por isso, é importante adicionar documentação e docstrings. O Cookiecutter adicionou um arquivo de modelo, `docs/source/model_doc/brand_new_llama.md`, que você pode preencher com informações sobre o seu modelo.

Esta é, em geral, a primeira interação do usuário com um modelo, portanto a documentação deve ser clara e concisa. Frequentemente, é muito útil adicionar exemplos de como o modelo deve ser utilizado.

Certifique-se de que docstrings sejam adicionadas a `src/transformers/models/brand_new_llama/modeling_brand_new_llama.py` e incluam todas as entradas e saídas necessárias. Consulte nosso [guia](https://github.com/huggingface/transformers/tree/main/docs#writing-documentation---specification) para a criação de documentação e docstrings.

## Refatorar

É hora de organizar as coisas e garantir que o estilo do código esteja consistente com o restante da biblioteca. Execute o comando a seguir para corrigir automaticamente estilos incorretos.

```bash
make style
```

Para verificar se o estilo do código passa nos controles de qualidade, execute o comando abaixo.

```bash
make check-repo
```

Pode haver outros testes ou verificações com falha (docstring ausente ou nomenclatura incorreta) no seu pull request devido aos testes de design rigorosos do Transformers. Podemos ajudá-lo com esses problemas, caso você esteja travado.

Depois de garantir que o código é executado corretamente, você pode querer refatorá-lo para torná-lo mais legível ou limpo.

## Enviar para o Hub

Converta e envie todos os checkpoints para o [Hub](https://hf.co/models). Adicione um model card para fornecer mais transparência e contexto sobre o modelo. O model card deve destacar características específicas de um checkpoint, como o modelo foi treinado e exemplos de código de como usá-lo.

> [!TIP]
> Em muitos casos, adicionar um notebook interativo que os usuários podem executar é uma ótima maneira de demonstrar como usar o modelo para inferência ou ajustá-lo para uma tarefa específica. Embora não seja obrigatório, incluir um notebook pode impulsionar a adoção do seu modelo.

Você também deve consultar a equipe do Transformers para decidir um nome adequado para o modelo e obter as permissões de acesso necessárias para fazer o upload do modelo.

Use o método [push_to_hub()](/docs/transformers/main/pt/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub) para enviar o modelo.

```py
brand_new_bert.push_to_hub("brand_new_llama")
```

Consulte o guia [Compartilhamento](./model_sharing) para obter mais informações sobre o envio de modelos para o Hub.

## Mergulhe seu modelo

Você está finalmente pronto para mesclar sua pull request e adicionar oficialmente o modelo ao Transformers! Certifique-se de que todos os testes estão passando e de que todos os comentários e feedbacks foram tratados.

Parabéns por adicionar um novo modelo ao Transformers! 🥳

Esta é uma contribuição muito significativa. Seu trabalho torna o Transformers mais acessível para desenvolvedores e pesquisadores ao redor do mundo. Você deve se orgulhar da sua contribuição e compartilhar sua conquista com a comunidade!

## Veja também

- [Regras de estrutura do modelo](./modeling_rules) — regras estáticas aplicadas a todos os arquivos `modeling_*.py` e `configuration_*.py`. Execute `make typing` para verificá-las antes de abrir um PR.
- [Verificações de pull request](./pr_checks) — referência completa sobre as verificações de CI executadas no seu PR e como aprová-las.

