Transformers documentation
Reglas de la estructura del modelo
Reglas de la estructura del modelo
Transformers aplica un conjunto de reglas estáticas a cada archivo modeling_*.py, modular_*.py y configuration_*.py. El paquete mlinter proporciona el motor de verificación, y el repositorio mantiene su conjunto de reglas activo en utils/rules.toml. Ese archivo TOML local nos permite habilitar, deshabilitar o ajustar reglas rápidamente sin esperar a una nueva versión de transformers-mlinter.
Consulte la documentación de mlinter para obtener la referencia completa del verificador y los detalles de uso.
Estas son las convenciones de modelo esperadas para agregar o modificar el código de modelado. Mantienen la base de código coherente y garantizan la compatibilidad con funciones como la paralelización de pipeline, los mapas de dispositivos y el atado de pesos.
Ejecución del comprobador
make typing ejecuta mlinter junto con el comprobador de tipos ty a través del wrapper del repositorio, de modo que detecta utils/rules.toml. Ejecute el mismo wrapper directamente con los siguientes comandos.
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 ruleLa opción más rápida durante el desarrollo es la bandera --changed-only. Solo comprueba los archivos que has modificado en relación con la rama principal. Si invocas mlinter directamente en lugar del envoltorio, pasa --rules-toml utils/rules.toml para que se apliquen las sobrescripciones locales.
Corregir una violación
Cuando se detecta una violación de una regla, el error tiene este aspecto:
src/transformers/models/acme/modeling_acme.py:18: TRF013: AcmeModel.__init__ does not call self.post_init().Use el ID de la regla para buscar la corrección en la referencia de reglas. TRF013 se activa cuando una subclase de PreTrainedModel no llama a self.post_init(). Ese método realiza pasos de finalización esenciales y omitirlo provoca errores en tiempo de ejecución.
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()Referencia de reglas
Cada regla a continuación detalla lo que aplica y muestra una diferencia (diff) con la corrección. Ejecuta python utils/check_modeling_structure.py --rule TRF001 para ver la documentación integrada de cualquier regla con el conjunto de reglas actual del repositorio.
TRF001
Comprueba que el atributo config_class de <Model>PreTrainedModel se llama <Model>Config. Una discrepancia puede romper la carga, las clases automáticas y las expectativas de los desarrolladores.
class AcmePreTrainedModel(PreTrainedModel):
- config_class = WileConfig
+ config_class = AcmeConfigTRF002
Comprueba que base_model_prefix es una cadena literal no vacía y sin espacios en blanco. Los prefijos no válidos pueden romper el mapeo de claves para la carga de pesos y el acceso al modelo base.
class AcmePreTrainedModel(PreTrainedModel):
- base_model_prefix = ""
+ base_model_prefix = "model"TRF003
Marca el patrón antiguo if not return_dict: return (x,) en forward. La ramificación manual de return_dict es verbosa y fácil de hacer mal. Deja que @capture_output o @can_return_tuple lo hagan.
-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
Comprueba que ninguna clase de modelo defina un método tie_weights. Sobrescribir tie_weights rompe la carga, el cálculo de device_map y el guardado. Declara los pesos vinculados en el atributo de clase _tied_weights_keys.
-def tie_weights(self):
- self.lm_head.weight = self.emb.weight
+class AcmeForCausalLM(AcmePreTrainedModel):
+ _tied_weights_keys = ["lm_head.weight"]TRF005
Comprueba la forma de _no_split_modules cuando está presente. Valores mal formados pueden romper la partición y el sharding del device-map.
-_no_split_modules = [SomeLayerClass, ""]
+_no_split_modules = ["AcmeDecoderLayer", "AcmeAttention"]TRF006
Comprueba que los argumentos de caché en la firma de un método forward se utilicen en el cuerpo. Un argumento de caché sin usar sugiere un soporte de caché incompleto y un comportamiento de API inconsistente.
def forward(self, x, past_key_values=None, use_cache=False):
+ if use_cache:
+ ...
return xTRF007
Comprueba las asignaciones al atributo self después de self.post_init() en init. Modificar la estructura del modelo después de post_init() omite su trabajo de inicialización y finalización.
def __init__(self, config):
...
- self.post_init()
- self.proj = nn.Linear(...)
+ self.proj = nn.Linear(...)
+ self.post_init()TRF008
Comprueba que add_start_docstrings en una clase de modelo recibe un argumento no vacío. Un argumento vacío genera documentación de API de baja calidad y poco 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
Comprueba que las subclases directas de PreTrainedConfig/PretrainedConfig en configuration*.py y modular*.py llevan @strict(accept_kwargs=True). Sin ello, una nueva config carece del contrato de validación de tipos en tiempo de ejecución del repositorio y se desvía del estándar de config basado en dataclass.
+@strict(accept_kwargs=True)
class AcmeConfig(PreTrainedConfig):
...TRF011
En forward() de las subclases de PreTrainedModel, las accesos a atributos de submódulos que torch.nn.Identity no tendría: en variables de bucle sobre self.layers, y en self.<submodule>.<attr> donde <attr> no es un atributo estándar de nn.Module. La paralelización por pipeline puede reemplazar cualquier submódulo con torch.nn.Identity, por lo que leer un atributo personalizado (p. ej. decoder_layer.attention_type) de él provoca un AttributeError en tiempo de ejecución. Lea los metadatos por capa desde 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
Las operaciones in situ (.normal(), .zero(), …) sobre los pesos del módulo dentro de _init_weights. Los parámetros llevan banderas internas que rastrean si aún necesitan reinicialización; las operaciones in situ las omiten. Utilice las primitivas 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
Comprueba que cada subclase de PreTrainedModel que define init llama a self.post_init(). En los archivos modulares, super().init() también cuenta, ya que propaga el post_init del padre. post_init realiza la finalización esencial (inicialización de pesos, configuración de gradient checkpointing, …); omitirlo provoca errores sutiles en tiempo de ejecución.
class AcmeModel(AcmePreTrainedModel):
def __init__(self, config):
super().__init__(config)
self.layers = nn.ModuleList(...)
+ self.post_init()TRF014
Banderas trust_remote_code utilizadas o pasadas (por ejemplo, como un kwarg) en los archivos de integración de modelos nativos. trust_remote_code carga código arbitrario, incluidos binarios: es una función potente para los usuarios, pero no es algo en lo que una integración nativa pueda depender, ya que el código remoto no puede ser revisado ni mantenido en 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
Cuando una subclase de PreTrainedModel establece un _tied_weights_keys no vacío, se comprueba el archivo de configuración asociado en busca de un campo tie_word_embeddings. Sin él, los usuarios no pueden controlar el atado de pesos: el modelo los ata de forma incondicional, lo que rompe los ciclos de serialización y el ajuste fino con cabezas no atadas.
# configuration_foo.py
@strict(accept_kwargs=True)
class FooConfig(PreTrainedConfig):
hidden_size: int = 768
+ tie_word_embeddings: bool = TrueTRF016
Cuando una clase de processing.py o videoprocessing.py declara atributos booleanos do_* (do_resize, do_rescale, do_normalize, do_convert_rgb, …) y sobrescribe preprocess() o _preprocess(), se comprueba que cada bandera siga consumiéndose allí: ya sea referenciada directamente, delegada mediante super().preprocess/_preprocess(…, **kwargs), o —solo en procesadores de imágenes— reenviada a través de _preprocess_image_like_inputs/_prepare_image_like_inputs. do_sample_frames está exenta: el preprocess() base la consume antes de que se ejecute _preprocess(). Un do_X que la sobrescritura nunca referencia está muerto: establecer do_X=False no tiene efecto, la operación se ejecuta de todos modos y las sobrescrituras por llamada se rompen en silencio.
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
En las clases que llevan tanto @auto_docstring como @dataclass, se comprueba que @auto_docstring aparezca primero. Los decoradores se aplican de abajo hacia arriba, por lo que @dataclass en la parte superior ejecuta @auto_docstring primero, sobre una clase que aún no tiene un init sintetizado: en ese caso, modifica el init de la clase padre.doc en lugar del de la subclase.
-@dataclass
@auto_docstring(
custom_intro="""
Output type of `AcmeForPreTraining`.
"""
)
+@dataclass
class AcmeForPreTrainingOutput(ModelOutput):
...TRF018
Comprueba que cada subclase de _init_weights(self, module, ...) que sobrescribe el método encadena la llamada mediante super()._init_weights(...). Los archivos modulares también aceptan los centinelas PreTrainedModel._init_weights(self, module), PreTrainedModel._init_weights(module) y raise AttributeError(...). Para una sobrescripción completa intencional, suprima la advertencia con # trf-ignore: TRF018 por encima del método. El método base _init_weights cubre los tipos de módulo estándar (Linear, Embedding, LayerNorm, RotaryEmbedding, …). Omitirlo deja sin inicializar todos los submódulos que la sobrescripción no cubra, lo cual pasa las pruebas y se manifiesta mucho después como un sutil error de inicialización de pesos (véase 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
Marca un _defaults no vacío en los TypedDict *ProcessorKwargs de processing_*.py. Los modelos publicados antes de la fecha límite quedan exentos. Los _defaults codificados en el origen dispersan la configuración del procesador por el código Python, son incómodos de sobrescribir desde la configuración y hacen crecer el código. En processor_config.json en el hub, viajan con el checkpoint y pueden actualizarse sin modificar el código.
class Gemma4ProcessorKwargs(ProcessingKwargs, total=False):
- _defaults = {
- "text_kwargs": {"padding": False},
- "images_kwargs": {"return_tensors": "pt"},
- }
images_kwargs: Gemma4ImageProcessorKwargsTRF020
En los directorios de modelos cuya configuración declara kv_lora_rank (Multi-head Latent Attention), se comprueba la clase de atención que posee la proyección de expansión de KV LoRA (kv_b_proj, o cualquier nn.Linear(config.kv_lora_rank, ...)): la expansión debe residir en un método dedicado (p. ej. expand_kv) que forward() llame, y no estar en línea. En los archivos modulares, un método heredado de una base importada cuenta. Los backends externos (vLLM/SGLang) sobrescriben la expansión para consumir directamente la caché de KV comprimida. Si se escribe en línea en forward(), no hay nada que sobrescribir, por lo que el backend debe materializar la caché completa, perdiendo los ahorros de memoria para los que existe MLA.
+ 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
En *.py y modular.py, las banderas torch.tensor(<value>, ..., device=<non-cpu>) donde <value> se resuelve de forma demostrable a un escalar de Python —desde literales numéricos y aritmética sobre ellos, campos de torch.finfo/iinfo, llamadas a builtins y math. que devuelven escalares, locales asignados exactamente una vez, self.<attr> asignados en el cuerpo de la clase y campos de config anotados como int/float/bool en el archivo de configuración asociado (siguiendo attribute_map). Se deja sin cambios todo lo que también podría ser una secuencia (eos_token_id: int | list[int] | None) o lo que no se pueda resolver. init, _init_weights, post_init y post_init están exentos: nunca se ejecutan dentro de una región de captura. torch.tensor(<python scalar>, device=<accelerator>) materializa el valor en el host y luego lo copia al dispositivo; la captura de gráficos de CUDA prohíbe esa copia, por lo que el modelo no puede ser capturado. torch.full((), <value>, dtype=…, device=…) rellena el mismo tensor de 0 dimensiones en el dispositivo con un kernel capturable y sin sincronización.
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
Comprueba que cada cadena de la lista _no_split_modules en modeling*.py o modular*.py nombre una clase definida en ese archivo, importada en él o definida por un módulo hermano del mismo directorio de modelo. Complementa a TRF005, que solo comprueba la forma del valor. device_map compara estas cadenas con module.__class__.__name__ en tiempo de ejecución, por lo que un nombre obsoleto o con un error de escritura no coincide con nada y se ignora silenciosamente: el módulo que debería mantenerse unido aún puede dividirse entre dispositivos. Elimina las entradas que nombren clases de otro modelo en lugar de corregirlas: post_init ya recopila _no_split_modules de los submodelos hijos.
class VideoLlavaPreTrainedModel(PreTrainedModel):
- _no_split_modules = ["VideoLlavaVisionAttention"]TRF023
In configuration*.py and modular.py, 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
En *.py y modular.py, se marca un literal entero mayor que 8 en un argumento de dimensión de un constructor de torch.nn (Linear, Embedding, LayerNorm, RMSNorm, GroupNorm, BatchNorm, InstanceNorm, Convd, ConvTranspose*d, Bilinear, MultiheadAttention), ya sea posicional o por palabra clave (in_features, out_features, in_channels, out_channels, num_embeddings, embedding_dim, embed_dim, normalized_shape, num_channels, hidden_size). Se ignoran los argumentos de forma del operador (kernel_size, stride, padding, num_groups); los literales de hasta 8 mantienen limpios los cabezales escalares, los clasificadores binarios y las cantidades de canales RGB. Los modelos añadidos antes de cutoff_date están exentos. Un ancho codificado fija el módulo a un tamaño de checkpoint: la misma arquitectura a otra escala se carga con una discrepancia de forma, y from_pretrained no puede indicar qué valor es incorrecto porque ningún campo de config apunta a él. Además, divide la fuente de verdad, de modo que editar la config ya no cambia el modelo que se construye.
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
En *.py y modular.py, las banderas detectan llamadas a una fábrica de máscaras (los puntos de entrada de utils: create_causal_mask, create_bidirectional_mask, create_sliding_window_causal_mask, create_chunked_causal_mask, create_masks_for_generate, y cualquier helper create_mask) dentro de una clase que no hereda de PreTrainedModel: bloques nn.Module simples como capas, módulos de atención y codificadores. La construcción de la máscara es un trabajo de complejidad O(longitud de la secuencia al cuadrado) que no varía por capa, por lo que construirla en la capa incurre en ese costo una vez por capa, y cada capa termina poseyendo su propia máscara, de modo que los backends de atención ya no pueden recibir una única máscara preparada. Constrúyala una sola vez en el modelo y pásela hacia abajo.
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
En *.py y modular*.py, se marca una clase que no es PreTrainedModel y que solo define init y forward, asigna exactamente un self.<attr> en init y cuyo cuerpo de forward es exactamente return self.<attr>(...) para ella (se ignora una docstring inicial). Cualquier otro método, atributo adicional, instrucción antes del return o llamada a super() en forward significa que la clase realiza su propio trabajo. El envoltorio añade un nivel a cada nombre de peso, a _no_split_modules, a los planes de paralelismo y a cada mapeo de conversión, sin calcular nada, y los lectores tienen que abrir una clase más para descubrirlo. Las subclases de PreTrainedModel están exentas: existen para from_pretrained y las clases auto incluso cuando forward solo 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
Marca cualquier declaración assert en modeling*.py, modular.py y configuration_.py. python -O elimina los asserts, por lo que una comprobación de forma o de configuración escrita como uno desaparece silenciosamente en ejecuciones optimizadas. Un assert también produce un AssertionError genérico, mientras que un ValueError puede indicar el valor problemático y qué hacer al respecto.
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
Comprueba las primeras 25 líneas de modeling*.py, modular.py, configuration_.py, processing*.py, image_processing.py and videoprocessing.py en busca de una línea Licensed under the <name> License seguida de cada cláusula del párrafo estándar de garantía, desde You may obtain a copy of the License at hasta limitations under the License.. Las líneas se aplanan y se convierten a minúsculas primero, por lo que el ajuste de línea y el estilo de los comentarios no importan. El nombre de la licencia y la línea de copyright no se comprueban: varían según el modelo. Un archivo distribuido sin el encabezado deja su procedencia ambigua, y añadirlo más tarde implica modificar un archivo ya publicado. Si solo se coincidiera con Apache License, se dejarían pasar los defectos que realmente ocurren: un párrafo truncado a mitad, un encabezado que se detiene después de la URL, o uno malformado por una búsqueda y reemplazo incorrecta.
+# Copyright 2026 The HuggingFace Team. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# ...
"""PyTorch Acme model."""TRF029
En *.py de modeling y modular*.py, se marca un __init__ que recibe config junto con un argumento cuyo nombre es inequívocamente un campo de la configuración (hidden_size, num_attention_heads, intermediate_size, head_dim, num_hidden_layers, embed_dim, dropout, eps, patch_size, rope_theta, …). Un parámetro opcional con un valor predeterminado de None queda exento: se trata de una sobrescritura, no de una segunda fuente de verdad, y es la forma en que una clase MLP sirve tanto para el ancho denso como para el ancho de experto de un modelo MoE. Un valor predeterminado codificado, como hidden_size: int = 1024, no lo está: prevalece sobre la configuración siempre que el llamador no pase nada. kosmos2 está en la lista de permitidos: su página de documentación no se puede derivar del nombre del directorio, por lo que el umbral no puede eximirlo. El mismo número ahora tiene dos fuentes de verdad y el llamador elige cuál prevalece, de modo que editar la configuración ya no modifica el modelo que se construye. Además, desplaza el conocimiento de la arquitectura a cada punto de llamada, donde no debería 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
En modeling*.py y modular*.py, las cadenas de atributos con raíz en config o self.config que tienen tres o más niveles de profundidad. config.hidden_size (un salto) y config.text_config.hidden_size (dos saltos, el acceso normal a una subconfiguración) son correctos. Una violación por línea. Un módulo que recorre config.diffusion_config.atom_encoder_config.hidden_size está acoplado a toda la jerarquía de configuración en lugar de a su propia porción, por lo que no se puede reutilizar, probar ni asignarle una subconfiguración diferente. Pasa la subconfiguración relevante hacia abajo y la cadena se reduce a un solo 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
En *.py y modular*.py, se marca como error un @dataclass de nivel superior cuyas clases base no incluyen ninguna que termine en Output, a menos que tenga dos o más campos obligatorios; estos son paquetes de argumentos internos, que ModelOutput rechaza en tiempo de ejecución. Un dataclass de salida simple no se indexa como una tupla, no sobrevive a return_dict=False y es invisible para @auto_docstring, por lo que sus campos nunca llegan a la documentación de la API generada. ModelOutput obtiene las tres ventajas sin coste adicional.
@auto_docstring
@dataclass
-class AcmeStructureOutput:
+class AcmeStructureOutput(ModelOutput):
positions: torch.Tensor
confidence: Optional[torch.Tensor] = NoneTRF032
En modeling*.py y modular*.py, las banderas maskedfill, masked_fill, full, full_like y new_full se llaman con un literal numérico negado de magnitud 1e3 o superior. Un -1e9 codificado de forma fija se desborda a -inf en float16 y está lejos de ser el valor más pequeño en float32, por lo que la misma máscara se comporta de manera diferente según el dtype y puede generar NaNs después del softmax. torch.finfo(dtype).min es el valor representable más pequeño en el dtype que realmente se está ejecutando.
-attention_scores = attention_scores.masked_fill(~mask, -1e9)
+attention_scores = attention_scores.masked_fill(~mask, torch.finfo(attention_scores.dtype).min)TRF033
En *.py and modular*.py, se marcan los métodos cuyo nombre comienza por set_, excepto los métodos del contrato de PreTrainedModel: set_input_embeddings, set_output_embeddings, set_decoder, set_encoder, set_attn_implementation y set_default_language. Un setter hace que el comportamiento dependa del orden de las llamadas: el valor no está en la configuración, por lo que no se guarda, no se restaura con from_pretrained y no es visible para el mapeo de dispositivos ni para la planificación de paralelismo. Los usuarios deben saber que deben llamarlo, y olvidarlo es 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
Marca los comentarios # noqa, con o sin códigos, en modeling*.py, modular.py y configuration_.py. En un archivo modular se aceptan F401, F821 y F822: se trata de una fuente generada que deliberadamente no define todos los nombres que utiliza, por lo que la familia de nombres indefinidos de ruff se activa en código correcto: entradas de __all__ que el conversor rellena, clases que residen en el modelo padre e importaciones conservadas para ser reexportadas. Se omite un # noqa que nombrara únicamente esos códigos; uno que nombrara cualquier otro se informa sobre los códigos que queden. Un # noqa sin código se informa siempre; en un archivo modular, el mensaje pide el código en lugar de una reescritura. Los archivos de modelo son código ordinario sujeto a las reglas de lint del repositorio, por lo que una supresión significa que el problema subyacente se dejó en su lugar — y un # noqa sin código también oculta cualquier violación futura en esa línea. Corrija el código en su lugar.
-from ...modeling_utils import PreTrainedModel # noqa: F401
+from ...modeling_utils import PreTrainedModelTRF036
En *.py de modelado y modular*.py, marca cualquier construcción de nn.Sequential(...). Sequential nombra a sus hijos por posición, por lo que los pesos se ubican en mlp.0.weight y mlp.2.weight: el mapeo de conversión, _tied_weights_keys y cada plan de paralelismo hacen referencia a índices, e insertar una capa renombra todo lo que viene después. Además, oculta el forward, de modo que los casts de dtype y los residuales entre pasos son invisibles en el lugar donde ocurren.
- 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
En *.py and modular*.py, las banderas marcan las llamadas a einsum e informan de la ecuación cuando esta es un literal. Desactivado por defecto: einsum es a veces la forma más clara de expresar una contracción, por lo que es una opción activable y no una convención estricta. Una ecuación de einsum codifica las formas en una notación que el lector debe decodificar, y una ecuación construida dinámicamente oculta qué contracción se ejecuta en realidad. Despliegue la ecuación en operaciones 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
Comprueba que cada archivo de modelado *.py, processing.py, imageprocessing.py, videoprocessing.py, featureextraction.py y tokenization*.py tenga un archivo de pruebas correspondiente en tests/models/<model>/test.py (modelingacme.py -> tests/models/acme/test_modeling_acme.py). Exentos: configuration.py, cubierto por ConfigTester en el archivo de pruebas de modelado modeling.py, y tokenization_utils.py, un auxiliar cubierto a través de su tokenizador; tokenization<name>_fast.py se mapea al archivo de pruebas de su contraparte lenta. Un archivo modular*.py puede definir varias familias a la vez, por lo que sus clases se enrutan por sufijo de nombre: modelado de XxxModel/XxxPreTrainedModel/XxxFor<Task>, procesamiento de imágenes de XxxImageProcessor(Fast), procesamiento de XxxProcessor, procesamiento de video de XxxVideoProcessor, extracción de características de XxxFeatureExtractor, tokenización de XxxTokenizer(Fast) y omisión de XxxConfig — y se informa de una violación por cada archivo de pruebas que falte. # trf-ignore: TRF038 no se admite; use allowlist_models para que la exención sea visible en la revisión. Un archivo de origen sin archivo de pruebas no tiene cobertura de regresión: un paso de propagación hacia adelante roto, un mapeo de conversión incorrecto o un tokenizador que descarta un token especial pueden incorporarse y permanecer rotos indefinidamente. Una configuración simulada con pesos aleatorios, o un vocabulario pequeño escrito a mano, es suficiente para probar cualquiera de ellos.
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
Detecta bloques de if is_*_available(): import ... (incluidas combinaciones como is_vision_available() and is_torch_available()) y marca la importación cuando el nombre no se referencia en ninguna otra parte del archivo, incluyendo dentro de anotaciones de tipo en cadenas y all. La comprobación de importaciones sin usar de ruff no las elimina: la importación es alcanzable, por lo que el bloque parece correcto por sí solo. Una vez que una refactorización ya no necesita PIL.Image, torch, etc., la importación protegida permanece como peso muerto y una señal engañosa sobre las dependencias reales del archivo.
if is_vision_available():
- from PIL import ImageTRF040
En modeling*.py y modular*.py, flags methods decorated with both @capture_outputs and @can_return_tuple. Complementa a TRF003, que cubre la ramificación manual de return_dict en forward(). Ambas decoraciones eliminan return_dict, por lo que solo la más externa ve el valor real. @capture_outputs ya maneja la conversión a to_tuple, lo que hace que @can_return_tuple sea 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
En tests/models//testtokenization.py, se comprueba que el archivo defina una clase de prueba recopilada que herede de TokenizerTesterMixin. Solo cuentan las clases que el runner recopila: una base TestCase, o la convención de nomenclatura *Test cuando la base es una clase de prueba de otro modelo. Por lo tanto, se omiten los archivos que solo contienen utilidades, y una utilidad que incorpora la suite no cumple la regla para una clase de prueba real. La herencia se sigue a través de las bases en el mismo archivo y hacia la prueba de tokenizador de otro modelo importada por nombre; una base que no se pueda resolver nunca cuenta. Se informa en la primera clase de prueba que no ejecuta la suite. auto está en la lista de permitidos: test_tokenization_auto.py prueba la resolución de AutoTokenizer, no un tokenizador. TokenizerTesterMixin es donde se comprueba en realidad el ciclo de codificación/decodificación, el relleno y la truncación, el manejo de tokens especiales, la persistencia de tokens añadidos y la equivalencia de guardado/carga. Una prueba que solo afirma algunas listas de ids de tokens escritas a mano pasa mientras el tokenizador está roto en todas ellas, y aun así parece probada en la revisión.
-class AcmeTokenizationTest(unittest.TestCase):
+class AcmeTokenizationTest(TokenizerTesterMixin, unittest.TestCase):
+ tokenizer_class = AcmeTokenizer
+ test_slow_tokenizer = TrueTRF043
Marca el parámetro `position_ids` declarado en la firma de `forward` de las clases cuyo nombre termina en `Attention`. `position_ids` se consume aguas abajo en el entrenamiento sin relleno de flash-attention y debe fluir a través de kwargs. Si se nombra en la firma, se absorbe antes de que la interfaz de atención pueda leerlo; el estándar de llama pasa `position_embeddings` además dekwargs.
class AcmeAttention(nn.Module):
def forward(
self,
hidden_states,
position_embeddings,
attention_mask=None,
- position_ids=None,
**kwargs: Unpack[TransformersKwargs],
):TRF044
Marca un parámetro llamado position en cualquier función de modeling.py y modular_.py. cache_position se eliminó de todos los modelos en v5. Volver a introducirlo (generalmente copiado de fuentes anteriores a v5) hace que un argumento obsoleto se propague por cada capa; la actualización de la caché es past_key_values.update(key_states, value_states, self.layer_idx), sin propagación de posición.
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 como obsoletos los parámetros de salida heredados attentions, output_hidden_states y return_dict en las firmas de forward en modeling.py y modular_.py. Los modelos contribuidos antes de la fecha límite están exentos. La pila de decoradores controla las salidas: @captureoutputs resuelve las banderas de output* contra la configuración y registra los tensores mediante _can_record_outputs, y @can_return_tuple gestiona return_dict. Declararlos en la firma reintroduce el encadenado manual de banderas, que se desvía de los decoradores.
+@capture_outputs
def forward(
self,
input_ids,
- output_attentions=None,
- output_hidden_states=None,
- return_dict=None,
**kwargs: Unpack[TransformersKwargs],
):TRF046
Asignaciones de flags a atributos de self en los métodos forward de modeling*.py y modular*.py. El estado escrito durante el forward rompe el batching, torch.compile y el razonamiento sobre el módulo. El estado que se transporta se pasa explícitamente (objetos de caché, el bucle de generate); los valores que dependen solo de config o de formas estáticas deben estar en 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
Asignaciones de flags a atributos de self en preprocess, preprocess, call y métodos post_process* en image_processing.py y videoprocessing.py. Un procesador que conserva estado entre llamadas rompe el loteo de preprocess-muchos-entonces-postprocess: el segundo preprocess sobrescribe el estado que el primer postprocess necesita. Devuelve el valor o pásalo a través de la cadena 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
Marca literales de lista/tupla/conjunto en las declaraciones de nivel de clase de _tied_weights_keys. En v5, _tied_weights_keys se cambió a un diccionario que mapea cada parámetro de destino atado a su origen. La forma de lista ya no indica qué parámetro es el origen, por lo que el atado, el cálculo de device_map y el guardado se comportan de forma incorrecta sin avisar.
class AcmeForCausalLM(AcmePreTrainedModel):
- _tied_weights_keys = ["lm_head.weight"]
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}TRF049
Las llamadas a init en los métodos init de modeling*.py y modular.py: primitivas de nn.init. / init.* e inicializadores in-place en los propios parámetros (self.weight.data.normal_()). Los modelos se instancian en el dispositivo meta, por lo que los valores de tensor escritos en init se descartan antes de la carga: un parámetro inicializado solo allí contiene contenido aleatorio al hacer fine-tuning desde cero o tras una recarga del dispositivo meta. Asigne con torch.empty en init e inicialice en _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
Las llamadas a una clase *RotaryEmbedding en el init de las clases cuyo nombre termina en Attention. El Model posee un único rotary_emb, construye inv_freq una sola vez y pasa cos/sin hacia abajo como position_embeddings. Un módulo de rotación por capa de atención duplica los buffers, recalcula las frecuencias por capa y se desvía del contrato según el cual la atención recibe 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
Las comparaciones de banderas se realizan contra un atributo attn_implementation en modeling.py y modular_.py. La asignación de backends corresponde a ALL_ATTENTION_FUNCTIONS.get_interface, y la manipulación de tensores condicional al backend (relleno, reorganización) debe estar en los envoltorios compartidos bajo integrations/. La ramificación en línea mantiene el cuerpo del modelo consciente del kernel y se rompe cuando se registran nuevos backends.
-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 las asignaciones a nivel de módulo de nombres que terminan en ATTENTION_CLASSES en modeling.py y modular_.py. Las clases de atención por backend seleccionadas desde un diccionario son el idiom anterior a la interfaz: las clases casi idénticas se desvían entre sí, y los núcleos de atención del hub registrados en ALL_ATTENTION_FUNCTIONS nunca llegan a ellas. Una única clase de atención que se despacha a través de la interfaz reemplaza al diccionario; no la propagues desde un padre heredado.
-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
En *.py y modular*.py, se marcan las asignaciones de banderas que construyen logits/shift_labels (y variantes desplazadas) mediante rebanado, como en labels[…, 1:]. Recibir etiquetas ya desplazadas (shift_labels = kwargs.pop(“shift_labels”, labels)) es el idiom correcto y no se marca. self.loss_function desplaza las etiquetas por sí mismo, por lo que desplazarlas previamente en el código de modelado entrena con objetivos doblemente desplazados o fuerza una ruta de pérdida a medida. Los modelos solo decodificador pasan etiquetas crudas y dejan que la función de pérdida las desplace. Los modelos codificador-decodificador son el caso espejo: sus etiquetas ya están desplazadas por el token de inicio del decodificador que se antepone, por lo que pasan shift_labels=labels para evitar que la función de pérdida las desplace de nuevo.
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
Banderas config = SomeConfig como atributo de clase en subclases de PreTrainedModel en modeling*.py y modular*.py. PreTrainedModel.__init_subclass__ deriva config_class a partir de una anotación de config, mediante inspect.get_annotations(cls). Una asignación crea un atributo de clase huérfano que la llamada no informa, por lo que la subclase conserva silenciosamente el config_class del padre. Una anotación sin valor no tiene valor en tiempo de ejecución, no crea ningún atributo y se detecta correctamente.
class Gemma4VisionModel(Gemma4PreTrainedModel):
"""The Gemma 4 Vision Encoder."""
- config = Gemma4VisionConfig
+ config: Gemma4VisionConfigTRF056
En *.py and modular*.py, las llamadas a .item() y .tolist() dentro de cualquier forward provocan una ruptura del grafo. Una llamada a .tolist() que alimenta el argumento de tamaño de división de split(...) está exenta: torch.split necesita enteros de Python. Ambas llamadas leen un tensor de vuelta al host, algo que dynamo no puede trazar, por lo que el grafo se rompe.
- 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
Comprueba @auto_docstring en las subclases públicas de PreTrainedModel (<Model>PreTrainedModel, <Model>Model, <Model>For<Task>, backbones), las subclases de PreTrainedConfig, las subclases de ModelOutput, los procesadores de imágenes y las subclases de ProcessorMixin, así como en sus métodos públicos forward, get_image_features, get_video_features, get_audio_features, get_text_features, preprocess y __call__. Un modular_*.py se comprueba en contra de los archivos generados a partir de él. Sin él, una clase se distribuye sin introducción ni documentación de parámetros, y un método sin documentación de argumentos, sin sección Returns y sin ejemplo de uso; todo ello tendría que escribirse a mano para cada modelo en lugar de obtenerse de 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
En *.py y modular*.py, las llamadas a register_buffer("<name>", ...) cuyo nombre de buffer es un literal de cadena se registran en cualquier receptor (self, o bien otro módulo como layer.mamba). Un nombre calculado, como una variable o una f-string (por ejemplo, un buffer por capa dentro de un bucle), no tiene un equivalente mediante asignación de atributo y queda exento. Dado que en torch>=2.5 nn.Buffer registra un buffer mediante una asignación de atributo simple, al igual que nn.Parameter. Un buffer creado por una llamada a un método solo existe como efecto secundario de la ejecución de __init__, por lo que un archivo modular que desee modificarlo debe redefinir todo el __init__. Al asignarse como un atributo, puede heredarse y sobrescribirse de forma independiente.
- 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 los directorios de modelos cuyo plan de paralelismo de tensores asigna moe_tp_experts, se comprueba que las clases *Experts enrutadas reciban los estados ocultos, los índices top-k y los pesos de enrutamiento top-k como los tres primeros argumentos posicionales de forward. Se aceptan alias como selected_experts y routing_weights. MoeExpertsParallel aplica una transformación de gradiente al argumento posicional 3. Una firma diferente lo aplica de forma silenciosa al tensor equivocado o lo omite.
class AcmeExperts(nn.Module):
- def forward(self, hidden_states):
+ def forward(self, hidden_states, top_k_index, top_k_weights):
...Suprimir violaciones
Si necesitas suprimir una violación de regla, utiliza una de las dos opciones siguientes.
Supresión en línea
Agrega un comentario # trf-ignore: RULE_ID en la línea que incumple la regla. Incluye una explicación para que los revisores entiendan por qué la supresión está justificada.
# trf-ignore: TRF011 — mask is derived from self.config, not the layer
hidden_states = layer(hidden_states, attention_mask=mask_from_config)No utilice trf-ignore para silenciar violaciones que deberían corregirse en el código.
allowlist_models
Para los modelos con código heredado que no se puede corregir de inmediato, añade el nombre del directorio del modelo a la lista allowlist_models de la regla correspondiente en mlinter rules.toml.
[rules.TRF004]
allowlist_models = ["existing_model", "your_model_name"]