Transformers documentation
Regras de estrutura do modelo
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 ruleA 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 = AcmeConfigTRF002
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 xTRF007
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 = TrueTRF016
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: Gemma4ImageProcessorKwargsTRF020
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 = 24TRF024
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_sizeTRF030
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] = NoneTRF032
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_sizeTRF034
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 PreTrainedModelTRF036
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.pyTRF039
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 ImageTRF040
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 removedTRF042
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 = TrueTRF043
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: Gemma4VisionConfigTRF056
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"]