Transformers documentation
Cajas de herramientas para depuración de modelos
Cajas de herramientas para depuración de modelos
Esta página enumera todas las herramientas de depuración y de adición de modelos que utiliza la biblioteca, así como las funciones de utilidad que proporciona para ello.
La mayoría de ellas solo son útiles si estás añadiendo nuevos modelos a la biblioteca.
Depuradores de adición de modelos
Depurador de adición de modelos - gestor de contexto para los agregadores de modelos
Este gestor de contexto es una herramienta para usuarios avanzados, destinada a quienes añaden modelos. Registra todas las llamadas forward dentro de un forward de modelo y registra un fragmento de cada entrada y salida en un JSON anidado. Cabe señalar que este gestor de contexto aplica torch.no_grad().
Justificación
Al portar modelos a Transformers, incluso de Python a Python, las personas que añaden modelos a menudo deben realizar muchas operaciones manuales, como guardar y cargar tensores, comparar dtypes, etc. Esta pequeña herramienta puede ayudar a ahorrar algo de tiempo.
Uso
Agregue este administrador de contexto de la siguiente manera para depurar un 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)
Lectura de resultados
El depurador genera dos archivos a partir de la llamada forward, ambos con el mismo nombre base, pero terminando en _SUMMARY.json o en _FULL_TENSORS.json.
El primero contendrá un resumen de los valores y formas de los tensores de entrada y salida 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 onEl archivo _FULL_TENSORS.json mostrará una vista completa de todos los tensores, lo cual es útil para comparar dos archivos.
"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')"
},Guardar tensores en disco
Algunos creadores de modelos pueden beneficiarse de registrar los valores completos de los tensores en el disco para apoyar, por ejemplo, el análisis numérico entre implementaciones.
Establezca use_repr=False para escribir los tensores en el 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)Al usar use_repr=False, los tensores se escriben en la misma ubicación en disco que los archivos _SUMMARY.json y _FULL_TENSORS.json. La propiedad value de las entradas del archivo _FULL_TENSORS.json contendrá una referencia de ruta relativa al archivo .safetensors asociado. Cada tensor se escribe en su propio archivo como la propiedad data del diccionario de estado. Los nombres de archivo se construyen usando module_path como prefijo, junto con algunos posibles sufijos que se construyen de forma recursiva.
- Las entradas de un módulo se denotan con
_inputsy las salidas con_outputs. - Las instancias de
listytuple, comoargso los valores de retorno de funciones, se verán con el sufijo_{index}. - Las instancias de
dictse verán prefijadas con_{key}.
Comparación entre implementaciones
Una vez que el depurador ha trazado las pasadas hacia adelante de dos modelos, se pueden comparar los archivos de salida json. A continuación se observa una ligera diferencia entre la capa de proyección de claves de estas dos implementaciones. Las entradas son en su mayoría idénticas, pero no del todo. Revisar las diferencias del archivo facilita identificar qué capa es la incorrecta.

Limitaciones y alcance
Esta función solo funcionará con modelos basados en torch. Los modelos que dependen en gran medida de llamadas a kernels externos pueden funcionar, pero el trazado probablemente omitirá algunos elementos. De todos modos, cualquier implementación en python que busque imitar otra implementación puede trazarse una vez en lugar de ejecutarse N veces con puntos de interrupción.
Si pasas do_prune_layers=False a tu depurador de modelos, todas las capas se enviarán a json. De lo contrario, solo se mostrarán la primera y la última capa. Esto es útil cuando algunas capas (típicamente de atención cruzada) solo aparecen después de N capas.
transformers.model_addition_debugger_context
< source >( modeldebug_path: str | None = Nonedo_prune_layers: bool = Trueuse_repr: bool = True )
Depurador de adición de modelos - gestor de contexto para los agregadores de modelos
Este gestor de contexto es una herramienta para usuarios avanzados, destinada a quienes añaden modelos.
Registra todas las llamadas forward dentro de un forward del modelo y registra un fragmento de cada entrada y salida en un archivo JSON anidado.
Si use_repr=True (el valor predeterminado), el archivo JSON registrará una versión repr() de los tensores como una lista de
cadenas. Si use_repr=False, los tensores completos se almacenarán en archivos SafeTensors separados y el archivo JSON
proporcionará una ruta relativa a ese archivo.
Tenga en cuenta que este gestor de contexto aplica torch.no_grad().
Uso
añadir el gestor de contexto a un 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)Analizador de pruebas omitidas
Escanear pruebas omitidas - para quienes añaden y mantienen modelos
Esta pequeña utilidad es una herramienta para usuarios avanzados, destinada a quienes añaden y mantienen modelos. Enumera todos los métodos de prueba existentes en test_modeling_common.py, heredados por todas las clases de probador de modelos, y analiza el repositorio para medir cuántas pruebas se están omitiendo y para qué modelos.
Justificación
Al portar modelos a Transformers, las pruebas fallan como deberían, y a veces test_modeling_common parece irreconciliable con las peculiaridades de nuestro modelo recién creado. Pero, ¿cómo podemos estar seguros de que no estamos rompiendo todo al añadir un skip aparentemente inocuo?
Esta utilidad:
- escanea todos los métodos de test_modeling_common
- busca los momentos en los que se omite un método
- devuelve un resumen en formato json que puedes cargar como un DataFrame/inspeccionar
Por ejemplo, test_inputs_embeds se omite en un impresionante 39% de los casos en el momento de escribir esta utilidad.

Uso
Puedes ejecutar el analizador de pruebas omitidas de dos maneras:
Escaneo completo (predeterminado)
Desde la raíz del repositorio transformers, analiza todos los métodos de prueba comunes y escribe los resultados en un archivo JSON (predeterminado: all_tests_scan_result.json).
python utils/scan_skipped_tests.py --output_dir path/to/output
--output_dir(opcional): Directorio donde se guardarán los resultados en JSON. Por defecto, es el directorio actual.
Ejemplo de salida:
🔬 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
Y generará el archivo all_tests_scan_result.json que puedes inspeccionar. El JSON está indexado por nombre de método, y cada entrada sigue este esquema, indicando también el origen (de common o de GenerationMixin).
{
"<method_name>": {
"origin": "<test suite>"
"models_ran": ["<model_name>", ...],
"models_skipped": ["<model_name>", ...],
"skipped_proportion": <float>,
"reasons_skipped": ["<model_name>: <reason>",
...
]
},
...
}Lo que puede visualizar como se muestra arriba, por ejemplo, con pandas
df = pd.read_json('all_tests_scan_result.json').T
df.sort_values(by=['skipped_proportion'], ascending=False)
Escanear un único método de prueba
Puedes centrarte en un método de prueba 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: Nombre del método de prueba que se debe analizar (p. ej.,test_inputs_embeds).--output_dir(opcional): Directorio donde se guardará el resultado en JSON.
Ejemplo de salida:
$ 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 modelos modulares
Analizador de similitud de código - para quienes añaden modelos
Esta utilidad analiza las similitudes de código entre las implementaciones de modelos para identificar oportunidades de modularización. Compara un archivo de modelado nuevo o existente con todos los modelos de la biblioteca utilizando métricas de similitud basadas en embeddings y en tokens.
Justificación
Al añadir un nuevo modelo a Transformers, muchos componentes (capas de atención, MLP, salidas, etc.) pueden existir ya en forma similar en otros modelos. En lugar de implementar todo desde cero, los creadores de modelos pueden identificar qué clases existentes son similares y potencialmente reutilizables mediante la modularización.
La herramienta calcula dos puntuaciones de similitud:
- Puntuación de incrustación: Utiliza incrustaciones de código semánticas (mediante
Qwen/Qwen3-Embedding-4B) para detectar código funcionalmente similar incluso con diferentes nombres - Puntuación de Jaccard: Mide la superposición de conjuntos de tokens para identificar patrones de código estructuralmente similares
Una puntuación de 1.00 significa que el código es idéntico.
Uso
Desde la raíz del repositorio transformers:
python utils/modular_model_detector.py --modeling-file path/to/modeling_file.py
La herramienta descargará automáticamente el índice precompilado desde el Hub (requiere RAM/VRAM para el modelo de embedding).
Ejemplo de salida:
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:El campo intersection muestra las clases que aparecen en ambos resultados top-5, lo que indica una alta confianza para los candidatos a modularización.
Creación de un índice personalizado
Para reconstruir el índice desde tu base de código local (útil después de agregar nuevos modelos o usar un modelo de embedding diferente):
python utils/modular_model_detector.py --build
Para enviar el índice reconstruido a un conjunto de datos del Hub:
python utils/modular_model_detector.py --build --push-new-index --hub-dataset your-org/your-dataset
Opciones
--modeling-file: Ruta al archivo de modelado a analizar--build: Construye el índice de similitud de código a partir de todos los archivos de modelado ensrc/transformers/models/--push-new-index: Después de la compilación, sube el índice a un conjunto de datos del Hub (requiere--build)--hub-dataset: ID del repositorio de datos del Hub para extraer/enviar el índice (predeterminado:hf-internal-testing/transformers_code_embeddings)
Limitaciones
Esta herramienta requiere recursos de GPU/CPU para ejecutar el modelo de embedding (Qwen/Qwen3-Embedding-4B). El índice precompilado se descarga del Hub de forma predeterminada, lo que requiere una conexión a internet en el primer uso.
Los resultados son sugerencias basadas en la similitud del código y deben revisarse manualmente antes de la modularización. Las puntuaciones de similitud altas no garantizan una compatibilidad perfecta.
Update on GitHub