Transformers documentation
Caixas de ferramentas para depuração de modelos
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 onO 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
_inputse as saídas por_outputs. - Instâncias de
listetuple, comoargsou valores de retorno de funções, terão o sufixo_{index}. - Instâncias de
dictterã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.

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
< source >( 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.

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 emsrc/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