/
githubmirror
/
transformers
Обзор
Документация
Войти
/
githubmirror
/
transformers
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
utils/rules.toml
342 строки
16 KB
Tarek Ziade
Switch mlinter to 0.1.2 (#47172)
09 июл 2026, 17:05
Не верифицирован
09 июл 2026, 17:05
0bc3554
Код
Авторство
О чём код?
# Copyright 2021 The HuggingFace Team. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This file can carry repo-local rule overrides for faster iteration between # `transformers-mlinter` releases. # Keep it synced with the upstream package's rules.toml when possible so local # behavior does not drift from the published checker longer than necessary. version = 1 [rules.TRF001] description = "Class-level config_class on <Model>PreTrainedModel should match <Model>Config naming." default_enabled = true allowlist_models = ["qwen3_omni_moe"] [rules.TRF001.explanation] what_it_does = "Checks naming consistency between <Model>PreTrainedModel and config_class." why_bad = "Mismatched config_class can break loading, auto classes, and developer expectations." diff = ''' class AcmePreTrainedModel(PreTrainedModel): - config_class = WileConfig + config_class = AcmeConfig ''' [rules.TRF002] description = "base_model_prefix should be a non-empty canonical string when defined on PreTrainedModel classes." default_enabled = true allowlist_models = ["lighton_ocr"] [rules.TRF002.explanation] what_it_does = "Checks that base_model_prefix, when set, is a non-empty, whitespace-free string literal." why_bad = "Invalid prefixes can break weight loading key mapping and base model access patterns." diff = ''' class AcmePreTrainedModel(PreTrainedModel): - base_model_prefix = "" + base_model_prefix = "model" ''' [rules.TRF003] description = "forward() should use capture_output/can_return_tuple decorators instead of manual return_dict branching." default_enabled = false allowlist_models = [] [rules.TRF003.explanation] what_it_does = "Detects forward methods that use the old 'if not return_dict: return (x,)' pattern." why_bad = "The old return_dict branching pattern is error-prone and verbose. Use the capture_output or can_return_tuple decorators instead." diff = ''' -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) ''' [rules.TRF004] description = "Models must never override tie_weights. Use _tied_weights_keys instead." default_enabled = true allowlist_models = ["data2vec", "hubert", "sew", "sew_d", "unispeech", "unispeech_sat", "wav2vec2", "wav2vec2_conformer", "wavlm"] [rules.TRF004.explanation] what_it_does = "Checks that no model class defines a tie_weights method." why_bad = "Overriding tie_weights leads to bad consequences for loading, device_map computation, and saving. Use _tied_weights_keys class attribute to declare tied weights instead." diff = ''' -def tie_weights(self): - self.lm_head.weight = self.emb.weight +class AcmeForCausalLM(AcmePreTrainedModel): + _tied_weights_keys = ["lm_head.weight"] ''' [rules.TRF005] description = "_no_split_modules, when defined, should be a list/tuple of non-empty strings." default_enabled = true allowlist_models = ["d_fine", "deformable_detr", "glm46v", "lw_detr", "pp_doclayout_v3", "rt_detr", "rt_detr_v2", "voxtral", "voxtral_realtime"] [rules.TRF005.explanation] what_it_does = "Checks the shape of _no_split_modules when present." why_bad = "Malformed values can break device-map partitioning and sharding behavior." diff = ''' -_no_split_modules = [SomeLayerClass, ""] +_no_split_modules = ["AcmeDecoderLayer", "AcmeAttention"] ''' [rules.TRF006] description = "forward with cache arguments should reference cache control/state variables consistently." default_enabled = true allowlist_models = ["chinese_clip", "evolla", "idefics2", "llama4"] [rules.TRF006.explanation] what_it_does = "Checks forward signatures that expose cache arguments for usage of those arguments in method body." why_bad = "Unused cache arguments can indicate incomplete caching support and inconsistent API behavior." diff = ''' def forward(self, x, past_key_values=None, use_cache=False): + if use_cache: + ... return x ''' [rules.TRF007] description = "self.post_init() in __init__ should remain at the end of initialization for PreTrainedModel classes." default_enabled = true allowlist_models = ["distilbert", "lxmert", "mt5", "pix2struct", "pop2piano", "switch_transformers", "t5"] [rules.TRF007.explanation] what_it_does = "Checks for self attribute assignments after self.post_init() in __init__." why_bad = "Mutating model structure after post_init can bypass intended initialization/finalization logic." diff = ''' def __init__(self, config): ... - self.post_init() - self.proj = nn.Linear(...) + self.proj = nn.Linear(...) + self.post_init() ''' [rules.TRF008] description = "Doc decorators on PreTrainedModel classes should avoid empty add_start_docstrings usage." default_enabled = true [rules.TRF008.explanation] what_it_does = "Checks add_start_docstrings usage on model classes for non-empty docstring arguments." why_bad = "Empty decorator usage produces unclear docs and weakens generated API documentation quality." diff = ''' -@add_start_docstrings("") +@add_start_docstrings("The Acme model.") class AcmeModel(AcmePreTrainedModel): ... ''' [rules.TRF009] description = "modeling_<name>.py should avoid importing implementation code from another model package." default_enabled = true allowlist_models = ["dpr", "maskformer", "sam3_video", "vision_text_dual_encoder"] [rules.TRF009.explanation] what_it_does = "Checks modeling files for cross-model imports such as transformers.models.other_model.* or from ..other_model.* imports." why_bad = "Cross-model implementation imports violate the single-file policy and make model behavior harder to inspect and maintain." diff = ''' -from transformers.models.llama.modeling_llama import LlamaAttention +# Keep implementation local to this file. +# If reusing code, copy it with a # Copied from comment. ''' [rules.TRF010] description = "Direct config definitions must use @strict(accept_kwargs=True)." default_enabled = true allowlist_models = ["nemotron_h", "vibevoice_asr"] [rules.TRF010.explanation] what_it_does = "Checks direct PreTrainedConfig/PretrainedConfig subclasses in configuration_*.py and modular_*.py for an explicit @strict(accept_kwargs=True) decorator." why_bad = "Without strict, new config classes miss the repo's runtime type-validation contract and drift from the dataclass-based config standard." diff = ''' +@strict(accept_kwargs=True) class AcmeConfig(PreTrainedConfig): ... ''' [rules.TRF011] description = "forward() must not access non-nn.Module attributes on submodules (breaks pipeline parallelism with Identity replacement)." default_enabled = true allowlist_models = [] [rules.TRF011.explanation] what_it_does = "In forward() methods of PreTrainedModel subclasses, checks for attribute accesses on submodules that would not exist on torch.nn.Identity. This includes attribute accesses on loop variables iterating over self.layers, and self.<submodule>.<attr> chains where <attr> is not a standard nn.Module attribute." why_bad = "Pipeline parallelism may replace any submodule with torch.nn.Identity. Accessing custom attributes (e.g. decoder_layer.attention_type) on a replaced module raises AttributeError at runtime. Per-layer metadata should be read from self.config instead." diff = ''' 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]], ) ''' [rules.TRF012] description = "_init_weights must use init primitives, not in-place operations on module weights." default_enabled = true allowlist_models = [] [rules.TRF012.explanation] what_it_does = "Checks that _init_weights(self, module) does not use in-place operations (e.g. .normal_(), .zero_()) directly on module weights." why_bad = "We rely on internal flags set on parameters to track whether they need re-initialization. In-place ops bypass this mechanism. Use the `init` primitives instead." diff = ''' +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) ''' [rules.TRF013] description = "PreTrainedModel __init__ must call self.post_init()." default_enabled = true allowlist_models = [] [rules.TRF013.explanation] what_it_does = "Checks that every PreTrainedModel subclass with an __init__ method calls self.post_init(). In modular files, calling super().__init__() is also accepted since it propagates post_init from the parent." why_bad = "post_init performs essential finalization (weight initialization, gradient checkpointing setup, etc.). Omitting it causes subtle runtime bugs." diff = ''' class AcmeModel(AcmePreTrainedModel): def __init__(self, config): super().__init__(config) self.layers = nn.ModuleList(...) + self.post_init() ''' [rules.TRF014] description = "`trust_remote_code` should never be used in native model integrations." default_enabled = true # The `auto` package is the loader layer that *implements* the `trust_remote_code` # feature, forwarding the user-supplied flag to `*.from_pretrained`. It is not a native # model integration, so it is exempt from this rule. allowlist_models = ["auto"] [rules.TRF014.explanation] what_it_does = "Checks whether `trust_remote_code` is passed or used in code (e.g. as kwarg) within native model integration files." why_bad = "`trust_remote_code` allows arbitrary loading, including binaries, which should only be a power feature for users, not a standard use-case. Native integrations must not depend on it, as remote code cannot be reviewed or maintained within transformers." diff = ''' class AcmeModel(AcmePreTrainedModel): def __init__(self, config): super().__init__(config) - self.model = AutoModel.from_pretrained(..., trust_remote_code=True) + self.model = AutoModel.from_pretrained(...) ''' [rules.TRF015] description = "Models with non-empty _tied_weights_keys must have tie_word_embeddings in their Config." default_enabled = true allowlist_models = [] [rules.TRF015.explanation] what_it_does = "When a PreTrainedModel subclass defines _tied_weights_keys as a non-empty collection, checks that the corresponding configuration file declares a tie_word_embeddings field." why_bad = "Without tie_word_embeddings in the config, users cannot control weight tying behavior. The model ties weights unconditionally, breaking serialization round-trips and preventing fine-tuning with untied heads." diff = ''' # configuration_foo.py @strict(accept_kwargs=True) class FooConfig(PreTrainedConfig): hidden_size: int = 768 + tie_word_embeddings: bool = True ''' [rules.TRF016] description = "do_* flags declared on a processor class must be referenced by overridden preprocess/_preprocess." default_enabled = true allowlist_models = ["kimi_k25", "minimax_m3_vl"] [rules.TRF016.explanation] what_it_does = "When an image_processing_*.py or video_processing_*.py class declares boolean do_* attributes (e.g. do_resize, do_rescale, do_normalize, do_convert_rgb) and overrides preprocess() or _preprocess(), checks that each declared flag is still consumed along the override path. That can be a direct reference in the override body, delegating back to the base implementation via super().preprocess(..., **kwargs) or super()._preprocess(..., **kwargs), or, for image processors, forwarding do_convert_rgb into the shared image-preparation path via _preprocess_image_like_inputs(...) or _prepare_image_like_inputs(...). The allowlist of base-handled flags (do_sample_frames) is exempted because the base preprocess() consumes them before _preprocess() runs." why_bad = "A do_X attribute that is not referenced by the override is a dead flag: setting do_X=False at construction or call time has no effect, and the underlying operation runs unconditionally. This silently breaks user expectations and makes per-call overrides ineffective." diff = ''' 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) ''' [rules.TRF017] description = "@auto_docstring must be placed above @dataclass on output classes." default_enabled = true allowlist_models = [] [rules.TRF017.explanation] what_it_does = "Checks classes decorated with both @auto_docstring and @dataclass for source ordering: @auto_docstring must appear above @dataclass." why_bad = "Decorators are applied bottom-up. When @dataclass is listed above @auto_docstring, @auto_docstring runs first on a class that has no synthesized __init__ yet and ends up modifying the parent class's __init__.__doc__ instead of the subclass's." diff = ''' -@dataclass @auto_docstring( custom_intro=""" Output type of [`AcmeForPreTraining`]. """ ) +@dataclass class AcmeForPreTrainingOutput(ModelOutput): ... ''' [rules.TRF018] description = "_init_weights overrides should call super()._init_weights(module), except modular-file sentinels." default_enabled = true allowlist_models = ["cosmos3_omni", "diffusion_gemma", "eomt_dinov3", "exaone4_5", "gemma4", "higgs_audio_v2", "kimi_k25", "olmo3", "pp_formulanet", "pp_lcnet_v3", "radio", "sam3_lite_text", "sam3_tracker", "slanet", "voxtral_realtime", "xcodec2"] [rules.TRF018.explanation] what_it_does = "Checks that every PreTrainedModel subclass that overrides `_init_weights(self, module, ...)` chains the call up via `super()._init_weights(...)`. In modular files, `PreTrainedModel._init_weights(self, module)` and `raise AttributeError(...)` are accepted because they are modularization sentinels. If a model intentionally fully overrides initialization, suppress with `# trf-ignore: TRF018` on the line above the method." why_bad = "The base `_init_weights` covers standard module types (Linear, Embedding, LayerNorm, RotaryEmbedding, ...). Skipping `super()._init_weights(...)` silently leaves submodules unhandled by the override uninitialized, which can pass tests and surface much later as subtle weight-init bugs (cf. https://github.com/huggingface/transformers/pull/45597)." diff = ''' 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) ''' [rules.TRF019] description = "A processor TypedDict class must not define `_defaults`, instead push them upstream to the hub (`processor_config.json`)." default_enabled = true allowlist_models = ["blip_2", "grounding_dino", "hunyuan_vl", "kosmos2", "omdet_turbo", "qwen3_asr"] cutoff_date = "2026-06-20" [rules.TRF019.explanation] what_it_does = "Checks that `*ProcessorKwargs` TypedDict classes in `processing_*.py` files do not set a non-empty `_defaults` dict. Old models released before cutoff date are not checked against the rule for backwards compatibility; new models must not hardcode defaults in Python." why_bad = "Hardcoding defaults in `_defaults` scatters processor configuration across Python source files, makes it unintuitive when it comes to overriding defaults via config, and bloats up the code. The canonical home for processor defaults is `processor_config.json` on the hub, which is shipped with the checkpoint and can be updated without touching code." diff = ''' class Gemma4ProcessorKwargs(ProcessingKwargs, total=False): - _defaults = { - "text_kwargs": {"padding": False}, - "images_kwargs": {"return_tensors": "pt"}, - } images_kwargs: Gemma4ImageProcessorKwargs '''