Transformers documentation
モデルデバッグツールボックス
モデルデバッグツールボックス
このページでは、libraryが使用するデバッグおよびモデル追加ツール、およびそれらに付随するユーティリティ関数をすべて一覧にしています。
それらの多くは、ライブラリに新しいモデルを追加する場合にのみ有用です。
モデル追加デバッガー
モデル追加デバッガー - モデルアダー用のコンテキストマネージャー
このコンテキストマネージャーは、モデルの追加者向けの高度なツールです。モデルの forward 内のすべての forward 呼び出しを追跡し、各入力と出力のスライスをネストされた JSON に記録します。なお、このコンテキストマネージャーは torch.no_grad() を強制します。
根拠
Transformers へのモデル移植において、Python から Python への移行であっても、モデルを追加する際は、テンソルの保存と読み込み、dtype の比較など、多くの手動操作が必要になることがよくあります。この小さなツールが、その作業時間を短縮できることを願っています。
使用方法
モデルのデバッグには、このコンテキストマネージャーを次のように追加します。
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 呼び出しから2つのファイルを生成します。どちらも同じベース名を持ち、末尾が _SUMMARY.json または _FULL_TENSORS.json になります。
最初の1つには、各モジュールの入力および出力テンソルの値と形状のサマリーが含まれます。
{
"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 ファイルには、すべてのテンソルの詳細が表示されるため、2つのファイルを比較する際に便利です。
"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 ファイルと同じディスクの場所に書き込まれます。_FULL_TENSORS.json ファイル内のエントリの value プロパティには、関連する .safetensors ファイルへの相対パスの参照が含まれます。各テンソルは、状態辞書の data プロパティとして、それぞれ個別のファイルに書き込まれます。ファイル名は、module_path をプレフィックスとして使用し、再帰的に構築されるいくつかの可能なサフィックスを付けて作成されます。
- モジュールの入力は
_inputsで、出力は_outputsで表されます。 listやtupleのインスタンス(argsや関数の戻り値など)には、_{index}が接尾辞として付与されます。dictのインスタンスには、_{key}が接尾辞として付与されます。
実装の比較
デバッガによって2つのモデルのフォワードパスがトレースされた後、json出力ファイルを比較できます。以下を参照してください。これら2つの実装のキー投影層にわずかな違いがあることがわかります。入力はおおむね同一ですが、完全に一致していません。ファイルの差分を確認することで、どの層に問題があるかを特定しやすくなります。

制約とスコープ
この機能は、torch ベースのモデルでのみ動作します。外部カーネル呼び出しに大きく依存するモデルは動作する可能性がありますが、trace によって一部の処理が取りこぼされる可能性があります。いずれにせよ、別の実装を模倣することを目的とした Python 実装であれば、ブレークポイント付きで N 回再実行する代わりに、一度だけ trace できます。
モデルデバッガーにdo_prune_layers=Falseを渡すと、すべてのレイヤーがjsonに出力されます。それ以外の場合は、最初のレイヤーと最後のレイヤーのみが表示されます。これは、一部のレイヤー(通常はクロスアテンション)が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 が、私たちの全く新しいモデルの特殊性と折り合いがつかないように感じられることがあります。しかし、一見無害に見えるスキップを追加することで、すべてを壊していないとどうやって確信できるのでしょうか。
このユーティリティは:
- test_modeling_common のすべてのメソッドをスキャンします
- メソッドがスキップされたタイミングを検索します
- DataFrameとして読み込むことや、内容を確認できるサマリーJSONを返します
例えば、このユーティリティの作成時点では、test_inputs_embeds は実に 39% の割合でスキップされていました。

使用方法
スキップされたテストのアナライザーは、2つの方法で実行できます。
フルスキャン(デフォルト)
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
モジュール式モデル検出器
Code similarity analyzer - モデル追加者向け
このユーティリティは、モデル実装間のコード類似性を分析し、モジュール化の機会を特定します。埋め込みベースとトークンベースの類似性指標を用いて、新規または既存のモデリングファイルをライブラリ内のすべてのモデルと比較します。
根拠
transformers に新しいモデルを追加する際、多くのコンポーネント(アテンション層、MLP、出力など)が、他のモデルに類似した形で既に存在する可能性があります。すべてをゼロから実装するのではなく、モデルの追加者は、モジュール化を通じて既存のクラスの中で類似しており再利用可能なものを特定できます。
このツールは2つの類似度スコアを計算します:
- 埋め込みスコア:
Qwen/Qwen3-Embedding-4Bを用いたセマンティックなコード埋め込みにより、命名が異なっても機能的に類似したコードを検出します - Jaccard score: トークン集合の重複を測定し、構造的に類似したコードパターンを特定します
スコアが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 フィールドは、上位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: インデックスの pull/push に使用する Hub データセットリポジトリ ID(デフォルト:hf-internal-testing/transformers_code_embeddings)
制限事項
このツールは、埋め込みモデル(Qwen/Qwen3-Embedding-4B)を実行するために GPU/CPU リソースが必要です。デフォルトでは、事前構築されたインデックスが Hub からダウンロードされるため、初回使用時にはインターネット接続が必要です。
結果はコードの類似性に基づく提案であり、モジュール化の前に手動で確認する必要があります。類似度スコアが高いことは、完全な互換性を保証するものではありません。
Update on GitHub