Transformers documentation

Cajas de herramientas para depuración 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

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 on

El 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 _inputs y las salidas con _outputs.
  • Las instancias de list y tuple, como args o los valores de retorno de funciones, se verán con el sufijo _{index}.
  • Las instancias de dict se 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.

download-icon

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

< >

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

download-icon

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 en src/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