Transformers documentation

Regras de estrutura do modelo

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Regras de estrutura do modelo

O Transformers impõe um conjunto de regras estáticas a cada arquivo modeling_*.py, modular_*.py e configuration_*.py. O pacote mlinter fornece o mecanismo de verificação, e o repositório mantém seu conjunto de regras ativo em utils/rules.toml. Esse arquivo TOML local nos permite habilitar, desabilitar ou ajustar regras rapidamente, sem esperar por um novo lançamento do transformers-mlinter.

Consulte a documentação do mlinter para a referência completa do verificador e detalhes de uso.

Estas são as convenções de modelo esperadas para adicionar ou alterar o código de modelagem. Elas mantêm a base de código consistente e garantem a compatibilidade com recursos como paralelismo de pipeline, mapas de dispositivo e amarração de pesos.

Executando o verificador

make typing executa o mlinter em conjunto com o verificador de tipos ty por meio do wrapper do repositório, de modo que ele detecta o utils/rules.toml. Execute o mesmo wrapper diretamente com os comandos a seguir.

python utils/check_modeling_structure.py                 # check all modeling files
python utils/check_modeling_structure.py --changed-only  # check only files changed vs origin/main
python utils/check_modeling_structure.py --list-rules    # list all rules and their enabled status
python utils/check_modeling_structure.py --rule TRF001   # show built-in docs for a specific rule

A flag --changed-only é a opção mais rápida durante o desenvolvimento. Ela verifica apenas os arquivos que você modificou em relação ao branch principal. Se você invocar o mlinter diretamente, em vez do wrapper, passe --rules-toml utils/rules.toml para que as substituições locais sejam aplicadas.

Corrigindo uma violação

Quando uma violação de regra é detectada, o erro tem o seguinte formato:

src/transformers/models/acme/modeling_acme.py:18: TRF013: AcmeModel.__init__ does not call self.post_init().

Use o ID da regra para localizar a correção na referência de regras. TRF013 é acionado quando uma subclasse de PreTrainedModel não chama self.post_init(). Esse método executa etapas essenciais de finalização, e omiti-lo causa bugs em tempo de execução.

 class AcmeModel(AcmePreTrainedModel):
     def __init__(self, config):
         super().__init__(config)
         self.layers = nn.ModuleList(
             [AcmeDecoderLayer(config) for _ in range(config.num_hidden_layers)]
         )
+        self.post_init()

Referência de regras

Cada regra abaixo lista o que ela aplica e um diff mostrando a correção. Execute python utils/check_modeling_structure.py --rule TRF001 para ver a documentação embutida de qualquer regra com o conjunto de regras atual do repositório.

TRF001

Verifica se o config_class de <Model>PreTrainedModel é nomeado <Model>Config. Uma incompatibilidade pode quebrar o carregamento, as classes automáticas e as expectativas dos desenvolvedores.

class AcmePreTrainedModel(PreTrainedModel):
-    config_class = WileConfig
+    config_class = AcmeConfig

TRF002

Verifica se base_model_prefix é uma string literal não vazia e sem espaços em branco. Prefixos inválidos podem quebrar o mapeamento de chaves para carregamento de pesos e o acesso ao modelo base.

class AcmePreTrainedModel(PreTrainedModel):
-    base_model_prefix = ""
+    base_model_prefix = "model"

TRF003

Sinaliza o padrão antigo if not return_dict: return (x,) em forward. A ramificação manual de return_dict é verbosa e fácil de errar. Deixe que @capture_output ou @can_return_tuple façam isso.

-def forward(self, x, return_dict=None):
-    if not return_dict:
-        return (x,)
-    return AcmeModelOutput(last_hidden_state=x)
+@can_return_tuple
+def forward(self, x):
+    return AcmeModelOutput(last_hidden_state=x)

TRF004

Verifica que nenhuma classe de modelo define um método tie_weights. Sobrescrever tie_weights quebra o carregamento, o cálculo de device_map e o salvamento. Declare pesos vinculados no atributo de classe _tied_weights_keys.

-def tie_weights(self):
-    self.lm_head.weight = self.emb.weight
+class AcmeForCausalLM(AcmePreTrainedModel):
+    _tied_weights_keys = ["lm_head.weight"]

TRF005

Verifica a forma de _no_split_modules quando presente. Valores malformados podem quebrar a particionamento e o sharding do device-map.

-_no_split_modules = [SomeLayerClass, ""]
+_no_split_modules = ["AcmeDecoderLayer", "AcmeAttention"]

TRF006

Verifica se os argumentos de cache na assinatura de um método forward são utilizados no corpo do método. Um argumento de cache não utilizado sugere suporte incompleto a cache e comportamento de API inconsistente.

def forward(self, x, past_key_values=None, use_cache=False):
+    if use_cache:
+        ...
     return x

TRF007

Verifica atribuições ao atributo self após self.post_init() em init. Modificar a estrutura do modelo após post_init ignora o trabalho de inicialização e finalização.

def __init__(self, config):
     ...
-    self.post_init()
-    self.proj = nn.Linear(...)
+    self.proj = nn.Linear(...)
+    self.post_init()

TRF008

Verifica que add_start_docstrings em uma classe de modelo recebe um argumento não vazio. Um argumento vazio gera documentação de API de baixa qualidade e pouco clara.

-@add_start_docstrings("")
+@add_start_docstrings("The Acme model.")
 class AcmeModel(AcmePreTrainedModel):
     ...

TRF009

Flags imports into another model’s package from a model’s shipped implementation files: modeling*, configuration, processing_, imageprocessing, videoprocessing, featureextraction, tokenization_ and generation*.py. Three forms count: package path (from transformers.models.other.modeling_other import X), relative path (from ..other.configuration_other import X) and public API (from transformers import OtherModel) — for the last the owning directory is inferred from the class name and confirmed against the classes it defines, so an unresolvable name is left alone. Out of scope: `modular.py(building on another model is its purpose, and the converter flattens those imports away),convert_.py,init.pyand files underauto. Allowed targets: the model's own directory,autoandtimm_wrapper`. One model, one definition: model A’s behavior lives in its own files, and a change to model B must not silently change model A — for every file kind, not just modeling. Reach sub-configs through AutoConfig and CONFIG_MAPPING, and use a modular file to build on another model’s code.

-from transformers.models.llama.modeling_llama import LlamaAttention
-from transformers import CLIPTextModelWithProjection
+# Keep implementation local to this model's own files.
+# To build on another model, write modular_acme.py; to reuse a snippet,
+# copy it with a # Copied from comment.

TRF010

Verifica que os subclasse diretos de PreTrainedConfig/PretrainedConfig em configuration*.py e modular*.py possuem @strict(accept_kwargs=True). Sem isso, um novo config perde o contrato de validação de tipo em tempo de execução do repositório e se afasta do padrão de config baseado em dataclass.

+@strict(accept_kwargs=True)
 class AcmeConfig(PreTrainedConfig):
     ...

TRF011

Em forward() de subclasses de PreTrainedModel, acessos a atributos de submódulos que torch.nn.Identity não teria: em variáveis de laço sobre self.layers, e em self.<submodule>.<attr> onde <attr> não é um atributo padrão de nn.Module. A paralelização por pipeline pode substituir qualquer submódulo por torch.nn.Identity, de modo que ler um atributo personalizado (por exemplo, decoder_layer.attention_type) dele levanta AttributeError em tempo de execução. Leia os metadados por camada de self.config.

def forward(self, ...):
-    for decoder_layer in self.layers:
+    for i, decoder_layer in enumerate(self.layers):
         hidden_states = decoder_layer(
             hidden_states,
-            attention_mask=causal_mask_mapping[decoder_layer.attention_type],
+            attention_mask=causal_mask_mapping[self.config.layer_types[i]],
         )

TRF012

As operações in-place (.normal(), .zero(), …) nos pesos do módulo dentro de _init_weights são sinalizadas. Os parâmetros possuem flags internas que rastreiam se ainda precisam de re-inicialização; as operações in-place as ignoram. Use os primitivos de init.

+from transformers import initialization as init
+
 def _init_weights(self, module):
-    module.weight.normal_(mean=0.0, std=0.02)
+    init.normal_(module.weight, mean=0.0, std=0.02)

TRF013

Verifica que toda subclasse de PreTrainedModel que define init chama self.post_init(). Em arquivos modulares, super().init() é válido, pois propaga o post_init do pai. O post_init realiza finalizações essenciais (inicialização de pesos, configuração de gradient checkpointing, ...); ignorá-lo causa bugs sutis em tempo de execução.

class AcmeModel(AcmePreTrainedModel):
     def __init__(self, config):
         super().__init__(config)
         self.layers = nn.ModuleList(...)
+        self.post_init()

TRF014

Flags trust_remote_code usadas ou passadas (por exemplo, como kwarg) em arquivos de integração de modelos nativos. trust_remote_code carrega código arbitrário, incluindo binários — um recurso poderoso para usuários, mas não algo em que uma integração nativa pode depender, já que o código remoto não pode ser revisado nem mantido no transformers.

class AcmeModel(AcmePreTrainedModel):
     def __init__(self, config):
         super().__init__(config)
-        self.model = AutoModel.from_pretrained(..., trust_remote_code=True)
+        self.model = AutoModel.from_pretrained(...)

TRF015

Quando uma subclasse de PreTrainedModel define _tied_weights_keys não vazio, verifica o arquivo de configuração correspondente em busca de um campo tie_word_embeddings. Sem ele, os usuários não conseguem controlar o vínculo de pesos: o modelo vincula incondicionalmente, quebrando os ciclos de serialização e o ajuste fino com cabeças não vinculadas.

# configuration_foo.py
 @strict(accept_kwargs=True)
 class FooConfig(PreTrainedConfig):
     hidden_size: int = 768
+    tie_word_embeddings: bool = True

TRF016

Quando uma classe de processing.py para imagem ou vídeoprocessing.py declara atributos booleanos do_* (do_resize, do_rescale, do_normalize, do_convert_rgb, …) e sobrescreve preprocess() ou _preprocess(), verifique se cada flag ainda é consumida ali: referenciada diretamente, delegada via super().preprocess/_preprocess(…, **kwargs), ou — apenas em processadores de imagem — encaminhada através de _preprocess_image_like_inputs/_prepare_image_like_inputs. do_sample_frames está isento: o preprocess() base o consome antes de _preprocess() ser executado. Um do_X que a sobrescrita nunca referencia é inativo: definir do_X=False não tem efeito, a operação é executada mesmo assim e as sobrescritas por chamada quebram silenciosamente.

class AcmeVideoProcessor(BaseVideoProcessor):
     do_resize = True
     do_normalize = True

     def _preprocess(
         self,
         videos,
+        do_resize: bool,
+        do_normalize: bool,
         size,
         image_mean,
         image_std,
         **kwargs,
     ):
         for video in videos:
-            video = self.resize(video, size=size)
-            video = self.normalize(video, image_mean, image_std)
+            if do_resize:
+                video = self.resize(video, size=size)
+            if do_normalize:
+                video = self.normalize(video, image_mean, image_std)

TRF017

Em classes que possuem tanto @auto_docstring quanto @dataclass, verifica-se se @auto_docstring vem primeiro. Os decoradores são aplicados de baixo para cima, portanto, @dataclass no topo executa @auto_docstring primeiro, em uma classe que ainda não possui init sintetizado: ele então modifica o init.doc da classe pai, em vez do da subclasse.

-@dataclass
 @auto_docstring(
     custom_intro="""
     Output type of `AcmeForPreTraining`.
     """
 )
+@dataclass
 class AcmeForPreTrainingOutput(ModelOutput):
     ...

TRF018

Verifica que toda subclasse de _init_weights(self, module, ...) que faz override encadeia a chamada via super()._init_weights(...). Arquivos modulares também aceitam os sentinels PreTrainedModel._init_weights(self, module), PreTrainedModel._init_weights(module) e raise AttributeError(...). Para um override completo intencional, suprima com # trf-ignore: TRF018 acima do método. O _init_weights base cobre os tipos padrão de módulos (Linear, Embedding, LayerNorm, RotaryEmbedding, …). Pular essa chamada deixa todos os submódulos que o override não cobre sem inicialização — o que passa nos testes e surge muito depois como um bug sutil de inicialização de pesos (cf. https://github.com/huggingface/transformers/pull/45597).

from ... import initialization as init

 def _init_weights(self, module):
+    super()._init_weights(module)
     if isinstance(module, AcmeCustomLayer):
-        module.gate.data.zero_()
+        init.zeros_(module.gate)

TRF019

Sinaliza um _defaults não vazio em TypedDicts *ProcessorKwargs em processing_*.py. Modelos lançados antes da data limite são isentos. _defaults codificados em linha dispersam a configuração do processador pelo código-fonte Python, são difíceis de sobrescrever a partir da configuração e aumentam o tamanho do código. Em processor_config.json no hub, eles viajam com o checkpoint e podem ser atualizados sem alteração de código.

class Gemma4ProcessorKwargs(ProcessingKwargs, total=False):
-    _defaults = {
-        "text_kwargs": {"padding": False},
-        "images_kwargs": {"return_tensors": "pt"},
-    }
     images_kwargs: Gemma4ImageProcessorKwargs

TRF020

Em diretórios de modelos cuja configuração declara kv_lora_rank (Multi-head Latent Attention), verifica a classe de atenção que possui a projeção de expansão do KV LoRA (kv_b_proj, ou qualquer nn.Linear(config.kv_lora_rank, ...)): a expansão deve estar em um método dedicado (por exemplo, expand_kv) que o forward() chama, e não de forma inline. Em arquivos modulares, um método herdado de uma base importada é considerado válido. Backends externos (vLLM/SGLang) substituem a expansão para consumir diretamente o cache KV comprimido. Se estiver inline no forward(), não há nada para substituir, de modo que o backend precisa materializar o cache completo — perdendo as economias de memória para as quais o MLA existe.

+    def expand_kv(self, k_nope, k_pe):
+        key_shape = (*k_nope.shape[:-1], -1, self.qk_nope_head_dim + self.v_head_dim)
+        k_nope = self.kv_b_proj(k_nope).view(key_shape).transpose(1, 2)
+        k_nope, value_states = torch.split(k_nope, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
+        k_pe = k_pe.expand(*k_nope.shape[:-1], -1)
+        key_states = torch.cat((k_nope, k_pe), dim=-1)
+        return key_states, value_states
+
     def forward(self, hidden_states, ...):
         ...
-        k_nope = self.kv_b_proj(k_pass).view(key_shape).transpose(1, 2)
-        k_nope, value_states = torch.split(k_nope, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
-        k_pe = k_rot.expand(*k_nope.shape[:-1], -1)
-        key_states = torch.cat((k_nope, k_pe), dim=-1)
+        key_states, value_states = self.expand_kv(k_pass, k_rot)

TRF021

Em *.py e modular.py, as flags torch.tensor(<value>, ..., device=<non-cpu>) em que <value> se resolve comprovadamente para um escalar Python — a partir de literais numéricos e aritmética sobre eles, campos de torch.finfo/iinfo, builtins que retornam escalar e chamadas de math., locais vinculados exatamente uma vez, self.<attr> atribuído no corpo da classe e campos de config anotados como int/float/bool no arquivo de configuração correspondente (seguindo attribute_map). Qualquer coisa que também possa ser uma sequência (eos_token_id: int | list[int] | None) ou que não possa ser resolvida é deixada como está. init, _init_weights, post_init e post_init estão isentos: eles nunca são executados dentro de uma região de captura. torch.tensor(<python scalar>, device=<accelerator>) materializa o valor no host e depois o copia para o dispositivo; a captura de grafo CUDA proíbe essa cópia, portanto o modelo não pode ser capturado. torch.full((), <value>, dtype=…, device=…) preenche o mesmo tensor 0-d no dispositivo com um kernel capturável e sem sincronização.

def get_placeholder_mask(self, input_ids, inputs_embeds):
     special_image_mask = (
         inputs_embeds
         == self.get_input_embeddings()(
-            torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
+            torch.full((), self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
         )
     ).all(-1)

TRF022

Verifica se cada string na lista _no_split_modules em modeling*.py ou modular*.py nomeia uma classe definida nesse arquivo, importada nele ou definida por um módulo irmão do mesmo diretório do modelo. Complementa o TRF005, que apenas verifica a forma do valor. O device_map compara essas strings com module.__class__.__name__ em tempo de execução, de modo que um nome desatualizado ou com erro de digitação não corresponde a nada e é ignorado silenciosamente — o módulo que deveria ser mantido junto ainda pode ser dividido entre dispositivos. Exclua as entradas que nomeiam classes de outro modelo em vez de corrigi-las: o post_init já coleta _no_split_modules dos submodelos filhos.

class VideoLlavaPreTrainedModel(PreTrainedModel):
-    _no_split_modules = ["VideoLlavaVisionAttention"]

TRF023

In configuration*.py e modular.py, as flags `Configfields named after an upstream paper's abbreviation instead of the canonical name: d_model/n_embd -> hidden_size, d_ff/d_inner/ffn_dim/ffn_hidden_size/expansion_ratio -> intermediate_size, d_head -> head_dim, n_head/n_heads -> num_attention_heads, n_layer/n_layers/num_blocks -> num_hidden_layers. Fields are read from the class body and from __init__/__post_init__ assignments and defaults. Ambiguous but idiomatic names (num_heads, num_layers, embed_dim, mlp_ratio) are not flagged, and models added before cutoff_date keep theirs. Everything that reads a model's shape -- device_map planning, tensor/pipeline parallel plans, quantization, PEFT, attention-backend selection,attribute_mapconsumers -- looks up the canonical names, so a config spelling the same quantityd_model` silently opts out of all of them. Map the checkpoint’s own spelling in the conversion script.

@strict(accept_kwargs=True)
 class AcmeConfig(PreTrainedConfig):
-    d_model: int = 1024
-    d_ff: int = 4096
-    n_heads: int = 16
-    n_layers: int = 24
+    hidden_size: int = 1024
+    intermediate_size: int = 4096
+    num_attention_heads: int = 16
+    num_hidden_layers: int = 24

TRF024

Em *.py e modular.py, sinaliza um literal inteiro maior que 8 em um argumento de dimensão de um construtor do torch.nn (Linear, Embedding, LayerNorm, RMSNorm, GroupNorm, BatchNorm, InstanceNorm, Convd, ConvTranspose*d, Bilinear, MultiheadAttention), seja posicional ou por palavra-chave (in_features, out_features, in_channels, out_channels, num_embeddings, embedding_dim, embed_dim, normalized_shape, num_channels, hidden_size). Argumentos de forma do operador (kernel_size, stride, padding, num_groups) são ignorados; literais até 8 mantêm limpos os cabeçalhos escalares, classificadores binários e contagens de canais RGB. Modelos adicionados antes de cutoff_date estão isentos. Uma largura fixada em código fixa o módulo em um único tamanho de checkpoint: a mesma arquitetura em outra escala carrega com incompatibilidade de forma, e from_pretrained não pode indicar qual valor está incorreto porque nenhum campo de config aponta para ele. Isso também divide a fonte de verdade, de modo que editar a config não altera mais o modelo que é construído.

class AcmeAtomEmbedding(nn.Module):
     def __init__(self, config):
         super().__init__()
-        self.proj = nn.Linear(768, 3072, bias=False)
-        self.norm = nn.LayerNorm(3072)
+        self.proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
+        self.norm = nn.LayerNorm(config.intermediate_size)

TRF025

Em *.py e modular.py, flags indica chamadas a uma fábrica de máscaras (os pontos de entrada de utilitários de mascaramento create_causal_mask, create_bidirectional_mask, create_sliding_window_causal_mask, create_chunked_causal_mask, create_masks_for_generate, e qualquer create_mask helper) dentro de uma classe que não herda de PreTrainedModel — blocos nn.Module simples, como camadas, módulos de atenção e codificadores. A construção da máscara é um trabalho de complexidade O(quadrado do comprimento da sequência) que não varia por camada, portanto, construí-la na camada faz com que esse custo seja pago uma vez por camada, e cada camada passa a possuir sua própria máscara, impedindo que os backends de atenção recebam uma única máscara preparada. Construa-a uma única vez no modelo e passe-a para baixo.

class AcmeLayer(nn.Module):
     def forward(self, hidden_states, attention_mask=None, **kwargs):
-        attention_mask = create_causal_mask(
-            config=self.config, input_embeds=hidden_states, attention_mask=attention_mask, ...
-        )
         return self.self_attn(hidden_states, attention_mask, **kwargs)

 class AcmeModel(AcmePreTrainedModel):
     def forward(self, input_ids=None, attention_mask=None, **kwargs):
+        causal_mask = create_causal_mask(
+            config=self.config, input_embeds=inputs_embeds, attention_mask=attention_mask, ...
+        )
         for layer in self.layers:
-            hidden_states = layer(hidden_states, attention_mask, **kwargs)
+            hidden_states = layer(hidden_states, causal_mask, **kwargs)

TRF026

Em modeling*.py e modular*.py, sinaliza uma classe que não é PreTrainedModel e que define apenas init e forward, atribui exatamente um self.<attr> em init e cujo corpo de forward é exatamente return self.<attr>(...) para ela (uma docstring inicial é ignorada). Qualquer outro método, atributo extra, instrução antes do return ou chamada de super() em forward significa que a classe realiza trabalho próprio. O wrapper adiciona um nível a cada nome de peso, a _no_split_modules, aos planos de paralelismo e a cada mapeamento de conversão, sem calcular nada — e os leitores precisam abrir mais uma classe para descobrir isso. Subclasses de PreTrainedModel estão isentas: elas existem para from_pretrained e as classes auto, mesmo quando o forward apenas delega.

-class AcmeAtomTransformer(nn.Module):
-    def __init__(self, config):
-        super().__init__()
-        self.encoder = AcmeEncoder(config)
-
-    def forward(self, hidden_states, **kwargs):
-        return self.encoder(hidden_states, **kwargs)
-
 class AcmeModel(AcmePreTrainedModel):
     def __init__(self, config):
         super().__init__(config)
-        self.atom_transformer = AcmeAtomTransformer(config)
+        self.encoder = AcmeEncoder(config)

TRF027

Sinaliza qualquer declaração assert em modeling*.py, modular.py e configuration_.py. python -O remove asserts, portanto, uma verificação de forma ou configuração escrita como um deles desaparece silenciosamente em execuções otimizadas. Um assert também gera um AssertionError genérico, enquanto um ValueError pode nomear o valor problemático e indicar o que fazer a respeito.

def forward(self, hidden_states):
-    assert hidden_states.dim() == 3
+    if hidden_states.dim() != 3:
+        raise ValueError(f"Expected a 3D tensor, got shape {tuple(hidden_states.shape)}.")

TRF028

Verifica as primeiras 25 linhas de modeling*.py, modular.py, configuration_.py, processing*.py, image_processing.py and videoprocessing.py em busca de uma linha Licensed under the <name> License seguida por todas as cláusulas do parágrafo padrão de garantia, desde You may obtain a copy of the License at até limitations under the License.. As linhas são achatadas e convertidas para minúsculas primeiro, de modo que a quebra de linha e o estilo de comentário não importam. O nome da licença e a linha de copyright não são verificados: eles variam por modelo. Um arquivo distribuído sem o cabeçalho deixa sua origem ambígua, e adicioná-lo depois significa modificar um arquivo já lançado. Corresponder apenas a Apache License deixaria passar os defeitos que realmente ocorrem: um parágrafo truncado no meio, um cabeçalho que para após a URL, ou um corrompido por uma substituição incorreta.

+# Copyright 2026 The HuggingFace Team. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# ...
 """PyTorch Acme model."""

TRF029

Em *.py e modular*.py, sinaliza um __init__ que recebe config junto com um argumento cujo nome é inequivocamente um campo de configuração (hidden_size, num_attention_heads, intermediate_size, head_dim, num_hidden_layers, embed_dim, dropout, eps, patch_size, rope_theta, …). Um parâmetro opcional com valor padrão None está isento: isso é uma sobrescrita, não uma segunda fonte de verdade, e é assim que uma classe de MLP atende tanto a largura densa quanto a largura dos especialistas de um modelo MoE. Um valor padrão fixo, como hidden_size: int = 1024, não está isento — ele prevalece sobre a configuração sempre que o chamador não passar nada. O kosmos2 está na lista de permissões: sua página de documentação não é derivável do nome do diretório, portanto o limite não pode isentá-lo. O mesmo número agora tem duas fontes de verdade e o chamador escolhe o vencedor, de modo que editar a configuração não altera mais o modelo que é construído. Isso também empurra o conhecimento da arquitetura para todos os pontos de chamada, onde ele não deveria estar.

class AcmeAttention(nn.Module):
-    def __init__(self, config, embed_dim, num_heads, dropout):
+    def __init__(self, config, layer_idx=None):
         super().__init__()
-        self.embed_dim = embed_dim
-        self.num_heads = num_heads
+        self.embed_dim = config.hidden_size
+        self.num_heads = config.num_attention_heads

 class AcmeMLP(nn.Module):
     # an optional override is fine: omitting it reads the config
     def __init__(self, config, intermediate_size=None):
         super().__init__()
         self.intermediate_size = intermediate_size or config.intermediate_size

TRF030

Em *.py de modelagem e modular*.py, as cadeias de atributos enraizadas em config ou self.config com três ou mais níveis de profundidade são sinalizadas. config.hidden_size (um salto) e config.text_config.hidden_size (dois saltos, o acesso normal a sub-configurações) estão corretos. Uma violação por linha. Um módulo que percorre config.diffusion_config.atom_encoder_config.hidden_size está acoplado a toda a hierarquia de configuração, em vez de ao seu próprio segmento, o que impede sua reutilização, testes ou a atribuição de uma sub-configuração diferente. Passe a sub-configuração relevante para baixo e a cadeia se reduz a um salto.

class AcmeAtomEncoder(nn.Module):
     def __init__(self, config):
         super().__init__()
-        self.norm = AcmeLayerNorm(config.diffusion_config.atom_encoder_config.hidden_size)
+        self.norm = AcmeLayerNorm(config.hidden_size)

TRF031

Em *.py e modular*.py, sinaliza um @dataclass de nível superior cujas bases não incluem nada terminando em Output, a menos que ele tenha dois ou mais campos obrigatórios — esses são bundles de argumentos internos, que o ModelOutput rejeita em tempo de execução. Um dataclass de saída simples não é indexado como uma tupla, não sobrevive a return_dict=False e é invisível para @auto_docstring, de modo que seus campos nunca chegam à documentação da API gerada. O ModelOutput obtém os três gratuitamente.

@auto_docstring
 @dataclass
-class AcmeStructureOutput:
+class AcmeStructureOutput(ModelOutput):
     positions: torch.Tensor
     confidence: Optional[torch.Tensor] = None

TRF032

Em modeling*.py e modular*.py, as flags maskedfill, masked_fill, full, full_like e new_full chamadas com um literal numérico negado de magnitude 1e3 ou maior. Um -1e9 hardcoded transborda para -inf em float16 e está longe de ser o menor valor em float32, de modo que a mesma máscara se comporta de forma diferente para cada dtype e pode gerar NaNs após o softmax. torch.finfo(dtype).min é o menor valor representável no dtype que está sendo executado.

-attention_scores = attention_scores.masked_fill(~mask, -1e9)
+attention_scores = attention_scores.masked_fill(~mask, torch.finfo(attention_scores.dtype).min)

TRF033

Em modeling*.py e modular*.py, os métodos cujo nome começa com set_ são sinalizados, exceto os métodos do contrato de PreTrainedModel: set_input_embeddings, set_output_embeddings, set_decoder, set_encoder, set_attn_implementation e set_default_language. Um setter faz com que o comportamento dependa da ordem das chamadas: o valor não está no config, portanto não é salvo, não é restaurado por from_pretrained e não é visível para o planejamento de device-map ou paralelismo. Os usuários precisam saber que devem chamá-lo, e esquecê-lo é silencioso.

class AcmeTriangleAttention(nn.Module):
-    def set_chunk_size(self, chunk_size):
-        self.chunk_size = chunk_size
+    def __init__(self, config):
+        super().__init__()
+        self.chunk_size = config.chunk_size

TRF034

In modeling*.py and modular.py, flags a locally-defined `Layer/Blockclass instantiated in annn.ModuleList(…)that does not reachGradientCheckpointingLayerthrough its base chain; modular files follow relative imports into sibling models, and unresolved chains are inconclusive. Out of scope: a model that never setssupports_gradient_checkpointing = True, which raises fromgradient_checkpointing_enable()instead of skipping a layer; a layer holdingnn.BatchNorm/nn.InstanceNorm*, whose statistics would be recomputed twice; and a stack that is not the model's token mixer, shown by an attention, modulation, mixer or SSM module assigned asself.x = Y(…).gradient_checkpointing_enable()` wraps a layer only if it is a GradientCheckpointingLayer. A plain nn.Module on the trunk is skipped silently, so training looks checkpointed while still allocating full activations, and the OOM surfaces far from the cause. Elsewhere — a conv backbone, a decode head — the trade is the author’s call, so the rule stays out.

-class AcmeDecoderLayer(nn.Module):
+class AcmeDecoderLayer(GradientCheckpointingLayer):
     def __init__(self, config, layer_idx):
         super().__init__()

TRF035

Sinaliza comentários # noqa, com ou sem códigos, em modeling*.py, modular.py e configuration_.py. Em um arquivo modular, F401, F821 e F822 são aceitos: trata-se de uma fonte de geração que deliberadamente não define todos os nomes que utiliza, de modo que a família de regras de nomes indefinidos do ruff é acionada em código correto — entradas de __all__ preenchidas pelo conversor, classes que residem no modelo pai, imports mantidos para serem reexportados. Um # noqa que nomeia apenas esses códigos é ignorado; um que nomeia qualquer outro é reportado nos códigos que restam. Um # noqa sem código é sempre reportado; em um arquivo modular, a mensagem solicita o código em vez de uma reescrita. Os arquivos de modelo são código comum sujeito às regras de lint do repositório, portanto uma supressão significa que o problema subjacente foi deixado no lugar — e um # noqa sem código também oculta qualquer violação futura naquela linha. Corrija o código em vez disso.

-from ...modeling_utils import PreTrainedModel  # noqa: F401
+from ...modeling_utils import PreTrainedModel

TRF036

Em *.py e modular*.py, sinaliza qualquer construção de nn.Sequential(...). O Sequential nomeia seus filhos por posição, então os pesos ficam em mlp.0.weight e mlp.2.weight: o mapeamento de conversão, _tied_weights_keys e todos os planos de paralelismo passam a referenciar índices, e a inserção de uma camada renomeia tudo o que vem depois. Ele também oculta o forward, de modo que os casts de dtype e os resíduos entre etapas ficam invisíveis no local em que ocorrem.

-        self.mlp = nn.Sequential(
-            nn.Linear(config.hidden_size, config.intermediate_size),
-            nn.GELU(),
-            nn.Linear(config.intermediate_size, config.hidden_size),
-        )
+        self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
+        self.act = ACT2FN[config.hidden_act]
+        self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)

TRF037

Em *.py and modular*.py, as chamadas para einsum são sinalizadas, reportando a equação quando ela é um literal. Desativado por padrão: o einsum é ocasionalmente a forma mais clara de expressar uma contração, portanto, isso é opcional em vez de uma convenção rígida. Uma equação einsum codifica as formas em uma notação que o leitor precisa decodificar, e uma equação construída dinamicamente oculta qual contração é executada. Expanda-a em operações explícitas de matmul/transpose.

-        pair_bias = torch.einsum("bqhc,bkhc->bhqk", query_states, key_states)
+        pair_bias = query_states.permute(0, 2, 1, 3) @ key_states.permute(0, 2, 3, 1)

TRF038

Verifica se cada arquivo modeling*.py, processing.py, imageprocessing.py, videoprocessing.py, featureextraction.py e tokenization*.py possui um arquivo correspondente em tests/models/<model>/test.py (modelingacme.py -> tests/models/acme/test_modeling_acme.py). Isentos: configuration.py, coberto pelo ConfigTester no testemodeling.py correspondente, e tokenization_utils.py, um utilitário coberto por meio de seu tokenizer; tokenization<name>_fast.py é mapeado para o arquivo de teste do seu equivalente lento. Um arquivo modular*.py pode definir várias famílias de uma vez, portanto suas classes são roteadas pelo sufixo do nome — XxxModel/XxxPreTrainedModel/XxxFor<Task> para modeling, XxxImageProcessor(Fast) para image processing, XxxProcessor para processing, XxxVideoProcessor para video processing, XxxFeatureExtractor para feature extraction, XxxTokenizer(Fast) para tokenization, XxxConfig ignorado — e uma violação é reportada para cada arquivo de teste ausente. # trf-ignore: TRF038 não é suportado; use allowlist_models para que uma isenção seja visível na revisão. Um arquivo de origem sem arquivo de teste não tem cobertura de regressão: uma passagem forward quebrada, um mapeamento de conversão incorreto ou um tokenizer que descarta um token especial podem ser incorporados e permanecer quebrados indefinidamente. Uma configuração dummy com pesos aleatórios, ou um vocabulário pequeno escrito manualmente, é suficiente para exercitar qualquer um deles.

src/transformers/models/acme/modeling_acme.py
+tests/models/acme/test_modeling_acme.py
 src/transformers/models/acme/tokenization_acme.py
+tests/models/acme/test_tokenization_acme.py

TRF039

Encontra blocos if is_*_available(): import ... (incluindo combinações como is_vision_available() and is_torch_available()) e sinaliza o import quando o nome não é referenciado em nenhum outro lugar do arquivo, inclusive em type hints de string e all. A verificação de import não utilizado do ruff não remove esses casos: o import é alcançável, então o bloco parece correto por si só. Quando uma refatoração não precisa mais de PIL.Image, torch, etc., o import protegido permanece como peso morto e um sinal enganoso sobre as dependências reais do arquivo.

if is_vision_available():
-    from PIL import Image

TRF040

Em modeling*.py e modular*.py, os métodos decorados com ambos @capture_outputs e @can_return_tuple. Complementa o TRF003, que cobre a ramificação manual de return_dict em forward(). Ambos os decoradores removem return_dict, de modo que apenas o mais externo vê o valor verdadeiro. @capture_outputs já trata a conversão para to_tuple, tornando @can_return_tuple redundante.

-@can_return_tuple
 @merge_with_config_defaults
 @capture_outputs
 @auto_docstring
 def forward(self, x):
     return AcmeModelOutput(last_hidden_state=x)

TRF041

In modeling*.py and modular.py, flags every if/elif and conditional expression whose condition reads a `config.orself.config.attribute without a# CODEPATH:comment, accepted on the branch line or in the contiguous comment block directly above it. Any config attribute counts, not just boolean flags. Exempt by structure:X if X is not None else fallback, where the tested field is itself one of the results --getattr(config, x, default)spelled long, which cannot fork the graph; and a guard, anifwith noelsewhose body only raises or only warns/logs, since one side aborts and nothing diverges past it. Merely mentioning None does not qualify:config.visionconfig is not Nonestill owes a note. Exempt by field: framework plumbing that gates no checkpoint divergence --problem_typeselecting a loss,hidden_actlooking up an activation,num_labels,use_cache,is_decoder, the special token ids, thesummaryhead settings; the full list isDEFAULT_EXEMPT_ATTRIBUTESinmlinter/trf041.py, extended per project byignored_attributes = […]on the rule table. A model exempts one of its own fields file-wide with a module-level# trf-ignore: TRF041 config.scale_embedding, config.auxiliary_lossat column 0 (self.config.x,config.xandxare the same field). It must name at least one field -- a bare# trf-ignore: TRF041keeps its per-line meaning -- and a condition is skipped only when every field it reads is exempt. A config-gated branch is a second architecture in the same file, and the code cannot say whether both halves are still reachable -- which is how dead experimental branches survive for releases. The rule does not forbid the branch: like Rust's// SAFETY:`, it asks for the checkpoints taking each side to be written down next to it. A branch nobody can name one for is a branch to delete.

+        # CODEPATH: ESMC-6B ships pre-normalised embeddings, the 300M/600M checkpoints do not.
         if config.use_embedding_norm:
             hidden_states = self.embedding_norm(hidden_states)

-        if config.msa_encoder_enabled:
-            hidden_states = self.msa_encoder(hidden_states)
+        # no released checkpoint sets msa_encoder_enabled -> branch removed

TRF042

Em tests/models//testtokenization.py, verifica se o arquivo define uma classe de teste coletada que herda de TokenizerTesterMixin. Somente as classes coletadas pelo runner contam — uma base TestCase, ou a convenção de nomenclatura *Test quando a base é uma classe de teste de outro modelo —, portanto, arquivos apenas com helpers são ignorados, e um helper que incorpora a suíte não atende à regra para uma classe de teste real. A herança é rastreada através das bases no mesmo arquivo e para o teste de tokenizer de outro modelo importado por nome; uma base não resolvida nunca conta. O problema é reportado na primeira classe de teste que não executa a suíte. auto está na lista de permissões: test_tokenization_auto.py testa a resolução do AutoTokenizer, não um tokenizer. TokenizerTesterMixin é onde o round-trip de encode/decode, padding e truncamento, o tratamento de tokens especiais, a persistência de tokens adicionados e a equivalência de save/load são efetivamente verificados. Um teste que apenas afirma algumas listas de ids de tokens manuscritas passa enquanto o tokenizer está quebrado em todos eles, e ainda assim parece testado na revisão.

-class AcmeTokenizationTest(unittest.TestCase):
+class AcmeTokenizationTest(TokenizerTesterMixin, unittest.TestCase):
+    tokenizer_class = AcmeTokenizer
+    test_slow_tokenizer = True

TRF043

Sinaliza um parâmetro position_ids declarado na assinatura forward de classes cujo nome termina em Attention. position_ids é consumido a jusante pelo treinamento sem padding do flash-attention e deve fluir através de kwargs. Nomeá-lo na assinatura o consome antes que a interface de atenção possa lê-lo; o padrão llama passa position_embeddings além dekwargs.

class AcmeAttention(nn.Module):
     def forward(
         self,
         hidden_states,
         position_embeddings,
         attention_mask=None,
-        position_ids=None,
         **kwargs: Unpack[TransformersKwargs],
     ):

TRF044

Sinaliza um parâmetro chamado cacheposition em qualquer função em modeling.py e modular_.py. cache_position foi removido de todos os modelos na v5. Reintroduzi-lo (geralmente copiado de fontes anteriores à v5) propaga um argumento obsoleto por todas as camadas; a atualização do cache é past_key_values.update(key_states, value_states, self.layer_idx), sem propagação de posição.

def forward(
     self,
     hidden_states,
     past_key_values=None,
-    cache_position=None,
     **kwargs,
 ):
-    key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx, cache_position)
+    key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)

TRF045

Marca os parâmetros legados attentions, output_hidden_states e return_dict nas assinaturas de forward em modeling.py e modular_.py. Modelos contribuídos antes da data limite estão isentos. A pilha de decoradores controla a saída: @captureoutputs resolve as flags de output* em relação à config e registra os tensors via _can_record_outputs, e @can_return_tuple trata return_dict. Declará-los na assinatura reintroduz o encadeamento manual de flags que diverge dos decoradores.

+@capture_outputs
 def forward(
     self,
     input_ids,
-    output_attentions=None,
-    output_hidden_states=None,
-    return_dict=None,
     **kwargs: Unpack[TransformersKwargs],
 ):

TRF046

Atribuições de flags a atributos de self em métodos forward em modeling*.py e modular*.py. O estado escrito durante o forward quebra o batching, o torch.compile e o raciocínio sobre o módulo. O estado transportado é passado explicitamente (objetos de cache, o loop de generate); valores que dependem apenas do config ou de formas estáticas pertencem ao init.

def forward(self, hidden_states):
-    self.sequence_length = hidden_states.shape[1]
-    embeddings = self.compute_embeddings(self.sequence_length)
+    embeddings = self.compute_embeddings(hidden_states.shape[1])

TRF047

Atribuições de flags a atributos de self em preprocess, preprocess, call e métodos post_process* em image_processing.py e videoprocessing.py. Um processor que carrega estado entre chamadas quebra o loteamento de preprocess-muitas-então-postprocess: o segundo preprocess sobrescreve o estado de que o primeiro postprocess precisa. Retorne o valor ou passe-o pela cadeia de métodos.

def _preprocess(self, images, **kwargs):
-    self.original_sizes = [image.shape[-2:] for image in images]
+    original_sizes = [image.shape[-2:] for image in images]
     ...
+    return BatchFeature(data={"pixel_values": pixel_values, "original_sizes": original_sizes})

TRF048

Sinaliza literais de lista/tupla/conjunto em declarações de nível de classe de _tied_weights_keys. A v5 alterou _tied_weights_keys para um dicionário que mapeia cada parâmetro de destino vinculado à sua origem. O formato de lista não indica mais qual parâmetro é a origem, fazendo com que o vínculo, o cálculo de device_map e o salvamento falhem silenciosamente.

class AcmeForCausalLM(AcmePreTrainedModel):
-    _tied_weights_keys = ["lm_head.weight"]
+    _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}

TRF049

As chamadas de flags em init nos métodos init em modeling*.py e modular.py: primitivas nn.init. / init.* e inicializadores in-place nos próprios parâmetros (self.weight.data.normal_()). Os modelos são instanciados no dispositivo meta, portanto, os valores de tensor gravados em init são descartados antes do carregamento: um parâmetro inicializado apenas ali contém conteúdo aleatório ao fazer fine-tuning do zero ou após um recarregamento do dispositivo meta. Alocar com torch.empty em init e inicializar em _init_weights.

class AcmeEmbeddings(nn.Module):
     def __init__(self, config):
         super().__init__()
         self.position_embedding = nn.Parameter(torch.empty(config.num_positions, config.hidden_size))
-        nn.init.trunc_normal_(self.position_embedding, std=config.initializer_range)

 class AcmePreTrainedModel(PreTrainedModel):
     def _init_weights(self, module):
         super()._init_weights(module)
+        if isinstance(module, AcmeEmbeddings):
+            init.trunc_normal_(module.position_embedding, std=self.config.initializer_range)

TRF050

Define flags para chamadas a uma classe *RotaryEmbedding* no init de classes cujo nome termina em Attention. O Model possui um único rotary_emb, constrói inv_freq uma vez e passa cos/sin para baixo como position_embeddings. Um módulo de rotação por camada de atenção duplica buffers, recalcula frequências por camada e diverge do contrato de que a atenção recebe position_embeddings.

class AcmeAttention(nn.Module):
     def __init__(self, config, layer_idx):
         super().__init__()
-        self.rotary_emb = AcmeRotaryEmbedding(config)

 class AcmeModel(AcmePreTrainedModel):
     def __init__(self, config):
         super().__init__(config)
+        self.rotary_emb = AcmeRotaryEmbedding(config)

TRF051

Comparações de flags em relação a um atributo attn_implementation em modeling.py e modular_.py. O despacho de backends pertence a ALL_ATTENTION_FUNCTIONS.get_interface, e a manipulação condicional de tensors por backend (padding, reshaping) pertence aos wrappers compartilhados em integrations/. A ramificação inline mantém o corpo do modelo ciente do kernel e quebra quando novos backends são registrados.

-if self.config._attn_implementation == "flash_attention_2":
-    attn_output = flash_path(query_states, key_states, value_states)
-else:
-    attn_output = eager_path(query_states, key_states, value_states)
+attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(self.config._attn_implementation, eager_attention_forward)
+attn_output, attn_weights = attention_interface(self, query_states, key_states, value_states, ...)

TRF052

Marca atribuições em nível de módulo para nomes que terminam em ATTENTION_CLASSES em modeling.py e modular_.py. As classes de atenção por backend selecionadas de um dicionário são o idiom pré-interface: classes quase idênticas divergem, e os kernels de atenção do hub registrados em ALL_ATTENTION_FUNCTIONS nunca chegam a elas. Uma única classe de atenção que faz despacho através da interface substitui o dicionário; não a propague de um pai legado.

-ACME_ATTENTION_CLASSES = {
-    "eager": AcmeAttention,
-    "flash_attention_2": AcmeFlashAttention2,
-    "sdpa": AcmeSdpaAttention,
-}
+class AcmeAttention(nn.Module):
+    def forward(self, ...):
+        attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(self.config._attn_implementation, eager_attention_forward)

TRF053

In modeling*.py and modular*.py, flags assignments that build shiftlogits/shift_labels (and shifted variants) by slicing, as in labels[…, 1:]. Receiving already-shifted labels (shift_labels = kwargs.pop(“shift_labels”, labels)) is the correct idiom and is not flagged. self.loss_function shifts labels itself, so pre-shifting in modeling code trains on doubly-shifted targets or forces a bespoke loss path. Decoder-only models pass raw labels and let the loss shift them. Encoder-decoder models are the mirror case: their labels are already shifted by the prepended decoder start token, so they pass shift_labels=labels to stop the loss shifting again.

if labels is not None:
-    shift_logits = logits[..., :-1, :].contiguous()
-    shift_labels = labels[..., 1:].contiguous()
-    loss = nn.functional.cross_entropy(shift_logits.view(-1, self.config.vocab_size), shift_labels.view(-1))
+    # decoder-only: labels are unshifted, the loss shifts them
+    loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size)
+    # encoder-decoder: labels are already shifted, hand them over as shift_labels
+    loss = self.loss_function(logits=logits, labels=labels, shift_labels=labels, vocab_size=self.config.vocab_size)

TRF055

Flags config = SomeConfig como atributo de classe em subclasses de PreTrainedModel em modeling*.py e modular*.py. PreTrainedModel.__init_subclass__ deriva config_class a partir de uma config anotação, via inspect.get_annotations(cls). Uma atribuição cria um atributo de classe órfão que a chamada não relata, de modo que a subclasse mantém silenciosamente o config_class do pai. Uma anotação pura não tem valor em tempo de execução, não cria nenhum atributo e é detectada corretamente.

class Gemma4VisionModel(Gemma4PreTrainedModel):
     """The Gemma 4 Vision Encoder."""
-    config = Gemma4VisionConfig
+    config: Gemma4VisionConfig

TRF056

Em modeling*.py e modular*.py, as chamadas .item() e .tolist() dentro de qualquer forward são sinalizadas. Uma chamada .tolist() que alimenta o argumento de tamanho da divisão de split(...) está isenta: o torch.split precisa de ints do Python. Ambas as chamadas leem um tensor de volta para o host, o que o dynamo não consegue rastrear, portanto o grafo é interrompido.

-        for grid, item in zip(grid_thw.tolist(), split_items):
-            _, height, width = grid
-            merged.append(self.patch_merger(item, size=(height, width)))
+        for grid, item in zip(grid_thw, split_items):
+            merged.append(self.patch_merger(item, size=(grid[1], grid[2])))

TRF057

Verifica @auto_docstring em subclasses públicas de PreTrainedModel (<Model>PreTrainedModel, <Model>Model, <Model>For<Task>, backbones), subclasses de PreTrainedConfig, subclasses de ModelOutput, processadores de imagem e subclasses de ProcessorMixin, bem como em seus métodos públicos forward, get_image_features, get_video_features, get_audio_features, get_text_features, preprocess e __call__. Um modular_*.py é verificado em relação aos arquivos gerados a partir dele. Sem ele, uma classe é distribuída sem introdução nem documentação de parâmetros, e um método sem documentação de argumentos, sem seção Returns e sem exemplo de uso — tudo isso que, então, precisa ser escrito manualmente para cada modelo, em vez de vir do auto_docstring.py.

+@auto_docstring
 @dataclass
 class AcmeModelOutputWithPast(ModelOutput):
     logits: torch.Tensor | None = None

+@auto_docstring
 class AcmeForConditionalGeneration(AcmePreTrainedModel):
+    @auto_docstring
     def forward(self, input_ids, pixel_values=None, **kwargs):
         ...

TRF058

Em *.py e modular*.py, as chamadas register_buffer("<name>", ...) cujo nome do buffer é um literal de string são sinalizadas, em qualquer receptor (self ou outro módulo, como layer.mamba). Um nome calculado — uma variável ou f-string, por exemplo, um buffer por camada dentro de um loop — não tem equivalente por atribuição de atributo e está isento. Como o torch>=2.5, nn.Buffer registra um buffer por meio de atribuição simples de atributo, assim como nn.Parameter. Um buffer criado por uma chamada de método só existe como efeito colateral da execução de __init__, portanto, um arquivo modular que deseja ajustá-lo precisa redefinir todo o __init__. Atribuído como um atributo, ele pode ser herdado e sobrescrito de forma independente.

-        self.register_buffer("inv_freq", inv_freq, persistent=False)
-        self.register_buffer(
-            "position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False
-        )
+        self.inv_freq = nn.Buffer(inv_freq, persistent=False)
+        self.position_ids = nn.Buffer(torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False)

TRF059

Para diretórios de modelos cujo plano de paralelismo de tensores atribui moe_tp_experts, verifica-se que as classes roteadas *Experts recebem os estados ocultos, os índices top-k e os pesos de roteamento top-k como os três primeiros argumentos posicionais de forward. Aliases como selected_experts e routing_weights são aceitos. MoeExpertsParallel aplica uma transformação de gradiente ao argumento posicional 3. Uma assinatura diferente aplica silenciosamente a transformação ao tensor errado ou a ignora.

class AcmeExperts(nn.Module):
-    def forward(self, hidden_states):
+    def forward(self, hidden_states, top_k_index, top_k_weights):
         ...

Suprimindo violações

Se você precisar suprimir uma violação de regra, use uma das duas opções abaixo.

Supressão inline

Adicione um comentário # trf-ignore: RULE_ID na linha que viola a regra. Inclua uma explicação para que os revisores entendam por que a supressão é justificada.

# trf-ignore: TRF011 — mask is derived from self.config, not the layer
hidden_states = layer(hidden_states, attention_mask=mask_from_config)

Não use trf-ignore para silenciar violações que devem ser corrigidas no código.

allowlist_models

Para modelos com código legado que não pode ser corrigido imediatamente, adicione o nome do diretório do modelo à lista allowlist_models da regra correspondente no mlinter rules.toml.

[rules.TRF004]
allowlist_models = ["existing_model", "your_model_name"]
Update on GitHub