Transformers documentation
Наборы инструментов для отладки моделей
Наборы инструментов для отладки моделей
На этой странице перечислены все инструменты отладки и добавления моделей, используемые библиотекой, а также вспомогательные функции, которые она предоставляет.
Большинство из них полезны только в том случае, если вы добавляете новые модели в библиотеку.
Отладчики добавления моделей
Отладчик добавления моделей — контекстный менеджер для добавляющих моделей
Этот контекстный менеджер — инструмент для опытных пользователей, предназначенный для добавления моделей. Он отслеживает все вызовы forward внутри forward модели и записывает фрагмент каждого входного и выходного значения в вложенный JSON. Обратите внимание, что этот контекстный менеджер принудительно применяет torch.no_grad().
Обоснование
При переносе моделей в transformers, даже из Python в Python, разработчикам моделей часто приходится выполнять множество ручных операций, связанных с сохранением и загрузкой тензоров, сравнением dtypes и т. д. Этот небольшой инструмент, надеюсь, позволит сэкономить время.
Использование
Добавьте этот контекстный менеджер следующим образом для отладки модели:
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)
Чтение результатов
Отладчик генерирует два файла из вызова forward, оба с одинаковым базовым именем, но с окончанием _SUMMARY.json или _FULL_TENSORS.json.
Первый будет содержать сводку значений и форм тензоров входа и выхода каждого модуля.
{
"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Файл _FULL_TENSORS.json отображает полную информацию обо всех тензорах, что удобно для сравнения двух файлов.
"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')"
},Сохранение тензоров на диск
Некоторым разработчикам моделей может быть полезно записывать полные значения тензоров на диск, чтобы, например, проводить численный анализ между различными реализациями.
Установите use_repr=False, чтобы записывать тензоры на диск с помощью 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)При использовании use_repr=False тензоры записываются в то же место на диске, что и файлы _SUMMARY.json и _FULL_TENSORS.json. Свойство value записей в файле _FULL_TENSORS.json будет содержать относительный путь к соответствующему файлу .safetensors. Каждый тензор записывается в отдельный файл в качестве свойства data словаря состояния. Имена файлов формируются с использованием module_path в качестве префикса и нескольких возможных суффиксов, которые строятся рекурсивно.
- Входы модуля обозначаются как
_inputs, а выходы — как_outputs. - Экземпляры
listиtuple, такие какargsили значения, возвращаемые функцией, будут дополнены суффиксом_{index}. - Экземпляры
dictбудут дополнены суффиксом_{key}.
Сравнение реализаций
После того как отладчик проследил прямые проходы двух моделей, можно сравнить файлы вывода в формате json. Ниже мы видим небольшие различия между слоями проекции ключей в этих двух реализациях. Входы в основном идентичны, но не совсем. Просмотр различий в файлах помогает точнее определить, какой слой работает некорректно.

Ограничения и область применения
Эта функция будет работать только с моделями на базе torch. Модели, сильно зависящие от вызовов внешних ядер, могут работать, но трассировка, вероятно, упустит некоторые детали. В любом случае, любая реализация на Python, нацеленная на имитацию другой реализации, может быть оттрассирована один раз вместо повторного запуска N раз с точками останова.
Если передать do_prune_layers=False в отладчик модели, все слои будут выведены в json. В противном случае будут показаны только первый и последний слои. Это полезно, когда некоторые слои (обычно cross-attention) появляются только после N слоёв.
transformers.model_addition_debugger_context
< source >( modeldebug_path: str | None = Nonedo_prune_layers: bool = Trueuse_repr: bool = True )
Отладчик добавления моделей — контекстный менеджер для добавляющих моделей
Этот менеджер контекста — инструмент для опытных пользователей, предназначенный для добавления моделей.
Он отслеживает все вызовы forward внутри forward модели и записывает фрагмент каждого входного и выходного значения в вложенный JSON-файл.
Если use_repr=True (значение по умолчанию), в JSON-файле будет записана версия тензоров, преобразованная с помощью repr(), в виде списка
строк. Если use_repr=False, полные тензоры будут сохранены в отдельных файлах SafeTensors, а JSON-файл будет
содержать относительный путь к этому файлу.
Обратите внимание, что этот контекстный менеджер принудительно применяет torch.no_grad().
Использование
добавьте контекстный менеджер к модели для отладки
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)Анализатор пропущенных тестов
Просмотр пропущенных тестов — для добавляющих и поддерживающих модели
Эта небольшая утилита — инструмент для опытных пользователей, предназначенный для добавления и поддержки моделей. Она перечисляет все методы тестирования, присутствующие в test_modeling_common.py и наследуемые всеми классами тестеров моделей, а также сканирует репозиторий, чтобы определить, сколько тестов пропускается и для каких моделей.
Обоснование
При переносе моделей в transformers тесты, как и положено, падают, а иногда test_modeling_common кажется несовместимым с особенностями нашей совершенно новой модели. Но как нам быть уверенными, что, добавляя, казалось бы, безобидный skip, мы не ломаем всё остальное?
Эта утилита:
- сканирует все методы test_modeling_common
- ищет моменты, когда метод пропускается
- возвращает сводный json, который можно загрузить как DataFrame/исследовать
Например, test_inputs_embeds пропускается в 39% случаев на момент написания этой утилиты.

Использование
Вы можете запустить анализатор пропущенных тестов двумя способами:
Полное сканирование (по умолчанию)
Из корня репозитория transformers сканирует все общие методы тестирования и выводит результаты в файл JSON (по умолчанию: all_tests_scan_result.json).
python utils/scan_skipped_tests.py --output_dir path/to/output
--output_dir(необязательный): каталог, в котором будут сохранены результаты в формате JSON. По умолчанию используется текущий каталог.
Пример вывода:
🔬 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
И будет создан файл all_tests_scan_result.json, который можно просмотреть. JSON индексируется по имени метода, и каждая запись следует этой схеме, указывая также источник (из common или GenerationMixin).
{
"<method_name>": {
"origin": "<test suite>"
"models_ran": ["<model_name>", ...],
"models_skipped": ["<model_name>", ...],
"skipped_proportion": <float>,
"reasons_skipped": ["<model_name>: <reason>",
...
]
},
...
}Это можно визуализировать, как показано выше, например, с помощью pandas
df = pd.read_json('all_tests_scan_result.json').T
df.sort_values(by=['skipped_proportion'], ascending=False)
Сканирование одного тестового метода
Вы можете сосредоточиться на конкретном методе теста с помощью --test_method_name:
python utils/scan_skipped_tests.py --test_method_name test_inputs_embeds --output_dir path/to/output
--test_method_name: Имя метода теста для сканирования (например,test_inputs_embeds).--output_dir(необязательный): каталог, в котором будет сохранён JSON-файл с результатами.
Пример вывода:
$ 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
Модульный детектор моделей
Анализатор сходства кода - для добавляющих модели
Эта утилита анализирует сходство кода между реализациями моделей, чтобы выявить возможности для модулизации. Она сравнивает новый или существующий файл моделирования со всеми моделями в библиотеке, используя метрики сходства на основе эмбеддингов и токенов.
Обоснование
При добавлении новой модели в transformers многие компоненты (слои внимания, MLP, выходные слои и т. д.) могут уже существовать в похожем виде в других моделях. Вместо реализации всего с нуля, разработчики моделей могут определить, какие существующие классы похожи и потенциально могут быть переиспользованы с помощью модульности.
Инструмент вычисляет два показателя сходства:
- Оценка встраивания: использует семантические встраивания кода (через
Qwen/Qwen3-Embedding-4B) для обнаружения функционально схожего кода даже при различном именовании - Показатель Жаккара: измеряет пересечение наборов токенов для выявления структурно похожих паттернов кода
Оценка 1.00 означает, что код идентичен.
Использование
Из корня репозитория transformers:
python utils/modular_model_detector.py --modeling-file path/to/modeling_file.py
Инструмент автоматически загрузит предварительно созданный индекс из Hub (требуется RAM/VRAM для модели эмбеддингов).
Пример вывода:
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:Поле intersection показывает классы, которые присутствуют в обоих результатах top-5, что указывает на высокую уверенность в кандидатах на модулирование.
Создание собственного индекса
Чтобы перестроить индекс из вашей локальной кодовой базы (полезно после добавления новых моделей или при использовании другой модели эмбеддингов):
python utils/modular_model_detector.py --build
Чтобы отправить перестроенный индекс в набор данных на Hub:
python utils/modular_model_detector.py --build --push-new-index --hub-dataset your-org/your-dataset
Параметры
--modeling-file: Путь к файлу моделирования для анализа--build: Построить индекс сходства кода по всем файлам моделирования вsrc/transformers/models/--push-new-index: после сборки отправить индекс в датасет на Hub (требуется--build)--hub-dataset: идентификатор репозитория датасета на Hub для получения/отправки индекса (по умолчанию:hf-internal-testing/transformers_code_embeddings)
Ограничения
Для работы этого инструмента необходимы ресурсы GPU/CPU для запуска модели эмбеддингов (Qwen/Qwen3-Embedding-4B). По умолчанию готовый индекс загружается с Hub, что требует подключения к интернету при первом использовании.
Результаты представляют собой рекомендации, основанные на сходстве кода, и их следует вручную проверить перед модуляцией. Высокие значения сходства не гарантируют полной совместимости.
Update on GitHub