Transformers documentation

Caixas de ferramentas para depuração de modelos

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

and get access to the augmented documentation experience

to get started

Caixas de ferramentas para depuração de modelos

Esta página lista todas as ferramentas de depuração e adição de modelos usadas pela biblioteca, bem como as funções utilitárias que ela fornece para isso.

A maioria delas só é útil se você estiver adicionando novos modelos à biblioteca.

Depuradores de adição de modelos

Depurador de adição de modelos - gerenciador de contexto para adicionadores de modelos

Este gerenciador de contexto é uma ferramenta para usuários avançados, destinada a quem adiciona modelos. Ele rastreia todas as chamadas de forward dentro de um forward de modelo e registra um trecho de cada entrada e saída em um JSON aninhado. Vale notar que este gerenciador de contexto impõe torch.no_grad().

Justificativa

Ao portar modelos para o Transformers, mesmo de Python para Python, os desenvolvedores de modelos frequentemente precisam realizar muitas operações manuais, envolvendo o salvamento e o carregamento de tensores, a comparação de dtypes, etc. Esta pequena ferramenta pode, com sorte, economizar algum tempo.

Uso

Adicione este gerenciador de contexto da seguinte forma para depurar um modelo:

import torch
from PIL import Image
import requests
from transformers import LlavaProcessor, LlavaForConditionalGeneration
from transformers.model_debugging_utils import model_addition_debugger_context
torch.random.manual_seed(673)

# load pretrained model and processor
model_id = "llava-hf/llava-1.5-7b-hf"
processor = LlavaProcessor.from_pretrained(model_id)
model = LlavaForConditionalGeneration.from_pretrained(model_id)

# create random image input
random_image = Image.fromarray(torch.randint(0, 256, (224, 224, 3), dtype=torch.uint8).numpy())

# prompt
prompt = "<image>Describe this image."

# process inputs
inputs = processor(text=prompt, images=random_image, return_tensors="pt")

# call forward method (not .generate!)
with model_addition_debugger_context(
    model,
    debug_path="optional_path_to_your_directory",
    do_prune_layers=False # This will output ALL the layers of a model.
):
    output = model.forward(**inputs)

Lendo os resultados

O depurador gera dois arquivos a partir da chamada de forward, ambos com o mesmo nome base, mas terminando em _SUMMARY.json ou em _FULL_TENSORS.json.

O primeiro conterá um resumo dos valores e das formas dos tensores de entrada e saída de cada módulo.

{
  "module_path": "MolmoForConditionalGeneration",
  "inputs": {
    "args": [],
    "kwargs": {
      "input_ids": {
        "shape": "torch.Size([1, 589])",
        "dtype": "torch.int64"
      },
      "attention_mask": {
        "shape": "torch.Size([1, 589])",
        "dtype": "torch.int64"
      },
      "pixel_values": {
        "shape": "torch.Size([1, 5, 576, 588])",
        "dtype": "torch.float32",
        "mean": "tensor(-8.9514e-01, device='cuda:0')",
        "std": "tensor(9.2586e-01, device='cuda:0')",
        "min": "tensor(-1.7923e+00, device='cuda:0')",
        "max": "tensor(1.8899e+00, device='cuda:0')"
    }
  },
  "children": [
    {
      "module_path": "MolmoForConditionalGeneration.language_model.model.embed_tokens",
      "inputs": {
        "args": [
          {
            "shape": "torch.Size([1, 589])",
            "dtype": "torch.int64"
          }
        ]
      },
      "outputs": {
        "shape": "torch.Size([1, 589, 3584])",
        "dtype": "torch.float32",
        "mean": "tensor(6.5460e-06, device='cuda:0')",
        "std": "tensor(2.3807e-02, device='cuda:0')",
        "min": "tensor(-3.3398e-01, device='cuda:0')",
        "max": "tensor(3.9453e-01, device='cuda:0')"
      }
    },
    {
      "module_path": "MolmoForConditionalGeneration.vision_tower",
      "inputs": {
        "args": [
          {
            "shape": "torch.Size([5, 1, 576, 588])",
            "dtype": "torch.float32",
            "mean": "tensor(-8.9514e-01, device='cuda:0')",
            "std": "tensor(9.2586e-01, device='cuda:0')",
            "min": "tensor(-1.7923e+00, device='cuda:0')",
            "max": "tensor(1.8899e+00, device='cuda:0')"
          }
        ],
        "kwargs": {
          "output_hidden_states": "True"
        }
      },
      "children": [
        { ... and so on

O arquivo _FULL_TENSORS.json exibirá uma visão completa de todos os tensors, o que é útil para comparar dois arquivos.

      "pixel_values": {
        "shape": "torch.Size([1, 5, 576, 588])",
        "dtype": "torch.float32",
        "value": [
          "tensor([[[[-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          ...,",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00]],",
          "",
          "         [[-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          ...,",
          "          [-1.4857e+00, -1.4820e+00, -1.2100e+00,  ..., -6.0979e-01, -5.9650e-01, -3.8527e-01],",
          "          [-1.6755e+00, -1.7221e+00, -1.4518e+00,  ..., -7.5577e-01, -7.4658e-01, -5.5592e-01],",
          "          [-7.9957e-01, -8.2162e-01, -5.7014e-01,  ..., -1.3689e+00, -1.3169e+00, -1.0678e+00]],",
          "",
          "         [[-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          ...,",
          "          [-3.0322e-01, -5.0645e-01, -5.8436e-01,  ..., -6.2439e-01, -7.9160e-01, -8.1188e-01],",
          "          [-4.4921e-01, -6.5653e-01, -7.2656e-01,  ..., -3.4702e-01, -5.2146e-01, -5.1326e-01],",
          "          [-3.4702e-01, -5.3647e-01, -5.4170e-01,  ..., -1.0915e+00, -1.1968e+00, -1.0252e+00]],",
          "",
          "         [[-1.1207e+00, -1.2718e+00, -1.0678e+00,  ..., 1.2013e-01, -1.3126e-01, -1.7197e-01],",
          "          [-6.9738e-01, -9.1166e-01, -8.5454e-01,  ..., -5.5050e-02, -2.8134e-01, -4.2793e-01],",
          "          [-3.4702e-01, -5.5148e-01, -5.8436e-01,  ..., 1.9312e-01, -8.6235e-02, -2.1463e-01],",
          "          ...,",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00]],",
          "",
          "         [[-1.0039e+00, -9.5669e-01, -6.5546e-01,  ..., -1.4711e+00, -1.4219e+00, -1.1389e+00],",
          "          [-1.0039e+00, -9.5669e-01, -6.5546e-01,  ..., -1.7193e+00, -1.6771e+00, -1.4091e+00],",
          "          [-1.6317e+00, -1.6020e+00, -1.2669e+00,  ..., -1.2667e+00, -1.2268e+00, -8.9720e-01],",
          "          ...,",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00],",
          "          [-1.7923e+00, -1.7521e+00, -1.4802e+00,  ..., -1.7923e+00, -1.7521e+00, -1.4802e+00]]]], device='cuda:0')"
        ],
        "mean": "tensor(-8.9514e-01, device='cuda:0')",
        "std": "tensor(9.2586e-01, device='cuda:0')",
        "min": "tensor(-1.7923e+00, device='cuda:0')",
        "max": "tensor(1.8899e+00, device='cuda:0')"
      },

Salvando tensores no disco

Alguns adicionadores de modelos podem se beneficiar do registro dos valores completos dos tensores em disco para suportar, por exemplo, a análise numérica entre implementações.

Defina use_repr=False para gravar os tensores no disco usando SafeTensors.

with model_addition_debugger_context(
    model,
    debug_path="optional_path_to_your_directory",
    do_prune_layers=False,
    use_repr=False,   # Defaults to True
):
    output = model.forward(**inputs)

Ao usar use_repr=False, os tensors são gravados no mesmo local em disco dos arquivos _SUMMARY.json e _FULL_TENSORS.json. A propriedade value das entradas no arquivo _FULL_TENSORS.json conterá uma referência de caminho relativo para o arquivo .safetensors associado. Cada tensor é gravado em seu próprio arquivo como a propriedade data do dicionário de estado. Os nomes dos arquivos são construídos usando o module_path como prefixo, com alguns possíveis sufixos que são construídos recursivamente.

  • As entradas dos módulos são indicadas por _inputs e as saídas por _outputs.
  • Instâncias de list e tuple, como args ou valores de retorno de funções, terão o sufixo _{index}.
  • Instâncias de dict terão o sufixo _{key}.

Comparando entre implementações

Depois que as passadas de frente de dois modelos forem rastreadas pelo depurador, é possível comparar os arquivos de saída json. Veja abaixo: podemos ver pequenas diferenças na camada de projeção de chave dessas duas implementações. As entradas são em grande parte idênticas, mas não exatamente. Examinar as diferenças nos arquivos facilita identificar qual camada está incorreta.

download-icon

Limitações e escopo

Este recurso funcionará apenas para modelos baseados em torch. Modelos que dependem fortemente de chamadas de kernels externos podem funcionar, mas o trace provavelmente perderá alguns detalhes. De qualquer forma, qualquer implementação em python que vise imitar outra implementação pode ser rastreada uma vez, em vez de ser executada N vezes com pontos de interrupção.

Se você passar do_prune_layers=False para o depurador do seu modelo, TODAS as camadas serão exibidas em json. Caso contrário, apenas a primeira e a última camada serão mostradas. Isso é útil quando algumas camadas (geralmente de atenção cruzada) aparecem apenas após N camadas.

transformers.model_addition_debugger_context

< >

( modeldebug_path: str | None = Nonedo_prune_layers: bool = Trueuse_repr: bool = True )

Depurador de adição de modelos - gerenciador de contexto para adicionadores de modelos

Este gerenciador de contexto é uma ferramenta para usuários avançados, destinada a quem adiciona modelos.

Ele rastreia todas as chamadas de forward dentro do forward de um modelo e registra um trecho de cada entrada e saída em um arquivo JSON aninhado. Se use_repr=True (o padrão), o arquivo JSON registrará uma versão repr() dos tensors como uma lista de strings. Se use_repr=False, os tensors completos serão armazenados em arquivos SafeTensors separados e o arquivo JSON fornecerá um caminho relativo para esse arquivo.

Vale notar que este gerenciador de contexto impõe torch.no_grad().

Uso

adicione o gerenciador de contexto a um modelo para depurar

import torch

from PIL import Image
from transformers import LlavaProcessor, LlavaForConditionalGeneration, model_addition_debugger_context

torch.random.manual_seed(673)

# load pretrained model and processor
model_id = "llava-hf/llava-1.5-7b-hf"
processor = LlavaProcessor.from_pretrained(model_id)
model = LlavaForConditionalGeneration.from_pretrained(model_id)

# create random image input
random_image = Image.fromarray(torch.randint(0, 256, (224, 224, 3), dtype=torch.uint8).numpy())

# prompt
prompt = "<image>Describe this image."

# process inputs
inputs = processor(text=prompt, images=random_image, return_tensors="pt")

# call forward method (not .generate!)
with model_addition_debugger_context(model, debug_path="Your_debug_path", do_prune_layers=False):
    output = model.forward(**inputs)

Analisador de testes ignorados

Verificar testes ignorados - para adicioneiros e mantenedores de modelos

Este pequeno utilitário é uma ferramenta para usuários avançados, destinada a quem adiciona e mantém modelos. Ele lista todos os métodos de teste existentes em test_modeling_common.py, herdados por todas as classes de testador de modelos, e varre o repositório para medir quantos testes estão sendo ignorados e para quais modelos.

Justificativa

Ao portar modelos para o Transformers, os testes falham como deveriam, e às vezes test_modeling_common parece irreconciliável com as peculiaridades do nosso modelo recém-criado. Mas como podemos ter certeza de que não estamos quebrando tudo ao adicionar um skip aparentemente inofensivo?

Este utilitário:

  • varre todos os métodos de test_modeling_common
  • procura por momentos em que um método é ignorado
  • retorna um resumo em json que você pode carregar como um DataFrame/inspecionar

Por exemplo, test_inputs_embeds é ignorado em uma proporção impressionante de 39% no momento em que esta utilidade foi escrita.

download-icon

Uso

Você pode executar o analisador de testes ignorados de duas maneiras:

Varredura completa (padrão)

A partir da raiz do repositório transformers, varre todos os métodos de teste comuns e exporta os resultados para um arquivo JSON (padrão: all_tests_scan_result.json).

python utils/scan_skipped_tests.py --output_dir path/to/output
  • --output_dir (opcional): Diretório onde os resultados em JSON serão salvos. O padrão é o diretório atual.

Exemplo de saída:

🔬 Parsing 331 model test files once each...
📝 Aggregating 224 tests...
  (224/224) test_update_candidate_strategy_with_matches_1es_3d_is_nonecodet_schedule_fa_kwargs
✅ Scan complete.

📄 JSON saved to /home/pablo/git/transformers/all_tests_scan_result.json

E ele gerará o arquivo all_tests_scan_result.json que você pode inspecionar. O JSON é indexado pelo nome do método, e cada entrada segue este esquema, indicando também a origem (de common ou de GenerationMixin.)

{
  "<method_name>": {
    "origin": "<test suite>"
    "models_ran": ["<model_name>", ...],
    "models_skipped": ["<model_name>", ...],
    "skipped_proportion": <float>,
    "reasons_skipped": ["<model_name>: <reason>",
      ...
    ]
  },
  ...
}

O que você pode visualizar acima, por exemplo, com pandas

df = pd.read_json('all_tests_scan_result.json').T
df.sort_values(by=['skipped_proportion'], ascending=False)

Escaneie um único método de teste

Você pode focar em um método de teste específico usando --test_method_name:

python utils/scan_skipped_tests.py --test_method_name test_inputs_embeds --output_dir path/to/output
  • --test_method_name: Nome do método de teste a ser verificado (ex.: test_inputs_embeds).
  • --output_dir (opcional): Diretório onde o resultado em JSON será salvo.

Exemplo de saída:

$ python utils/scan_skipped_tests.py --test_method_name test_inputs_embeds

🔬 Parsing 331 model test files once each...

== test_inputs_embeds ==

Ran    : 199/323
Skipped : 124/323 (38.4%)
 - aimv2: Aimv2 does not use inputs_embeds
 - align: Inputs_embeds is tested in individual model tests
 - altclip: Inputs_embeds is tested in individual model tests
 - audio_spectrogram_transformer: AST does not use inputs_embeds
 - beit: BEiT does not use inputs_embeds
 - bit: Bit does not use inputs_embeds
 - blip: Blip does not use inputs_embeds
 - blip_2: Inputs_embeds is tested in individual model tests
 - bridgetower:
 - canine: CANINE does not have a get_input_embeddings() method.
 - ...

📄 JSON saved to /home/pablo/git/transformers/scan_test_inputs_embeds.json

Detector de modelo modular

Analisador de similaridade de código - para adicioneiros de modelos

Esta utilidade analisa as similaridades de código entre implementações de modelos para identificar oportunidades de modularização. Ela compara um arquivo de modelagem novo ou existente com todos os modelos da biblioteca, utilizando métricas de similaridade baseadas em embeddings e em tokens.

Justificativa

Ao adicionar um novo modelo ao Transformers, muitos componentes (camadas de atenção, MLPs, saídas, etc.) podem já existir em forma semelhante em outros modelos. Em vez de implementar tudo do zero, os criadores de modelos podem identificar quais classes existentes são semelhantes e potencialmente reutilizáveis por meio da modularização.

A ferramenta calcula duas pontuações de similaridade:

  • Pontuação de incorporação: usa incorporações de código semântico (via Qwen/Qwen3-Embedding-4B) para detectar código funcionalmente semelhante, mesmo com nomes diferentes
  • Pontuação de Jaccard: mede a sobreposição de conjuntos de tokens para identificar padrões de código estruturalmente semelhantes

Uma pontuação de 1.00 significa que o código é idêntico.

Uso

A partir da raiz do repositório transformers:

python utils/modular_model_detector.py --modeling-file path/to/modeling_file.py

A ferramenta baixará automaticamente o índice pré-compilado do Hub (requer RAM/VRAM para o modelo de embedding).

Exemplo de saída:

Loading checkpoint shards: 100%|████████████████████| 2/2 [00:00<00:00, 33.62it/s]
encoding 21 query definitions with Qwen/Qwen3-Embedding-4B (device=cuda, batch=16, max_length=4096)

stuff.py::Beit3ImageTextMatchingOutput:
embedding:
    blip_2::Blip2ImageTextMatchingModelOutput (0.9994)
    chinese_clip::ChineseCLIPOutput (0.9818)
    owlvit::OwlViTOutput (0.9818)
jaccard:
    owlv2::Owlv2Output (0.9667)
    metaclip_2::MetaClip2Output (0.9667)
    altclip::AltCLIPOutput (0.9667)
intersection:
    blip::BlipOutput
    owlvit::OwlViTOutput

stuff.py::Beit3MLP:
embedding:
    efficientloftr::EfficientLoFTRMLP (0.9718)
    seggpt::SegGptMlp (0.9650)
jaccard:
    chinese_clip::ChineseCLIPTextSelfOutput (0.5294)
    bert::BertSelfOutput (0.5294)
intersection:

O campo intersection exibe as classes que aparecem em ambos os resultados do top-5, indicando alta confiança para os candidatos à modularização.

Criando um índice personalizado

Para reconstruir o índice a partir do seu código local (útil após adicionar novos modelos ou usar um modelo de incorporação diferente):

python utils/modular_model_detector.py --build

Para enviar o índice recriado para um conjunto de dados do Hub:

python utils/modular_model_detector.py --build --push-new-index --hub-dataset your-org/your-dataset

Opções

  • --modeling-file: Caminho para o arquivo de modelagem a ser analisado
  • --build: Constrói o índice de similaridade de código a partir de todos os arquivos de modelagem em src/transformers/models/
  • --push-new-index: após a compilação, envia o índice para um dataset do Hub (requer --build)
  • --hub-dataset: ID do repositório de dataset no Hub para puxar/enviar o índice (padrão: hf-internal-testing/transformers_code_embeddings)

Limitações

Esta ferramenta requer recursos de GPU/CPU para executar o modelo de embedding (Qwen/Qwen3-Embedding-4B). O índice pré-construído é baixado do Hub por padrão, o que exige uma conexão com a internet no primeiro uso.

Os resultados são sugestões baseadas na similaridade do código e devem ser revisados manualmente antes da modularização. Pontuações de similaridade elevadas não garantem compatibilidade perfeita.

Update on GitHub