Transformers documentation

Bộ công cụ gỡ lỗi mô hình

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Bộ công cụ gỡ lỗi mô hình

Trang này liệt kê tất cả các công cụ gỡ lỗi và thêm mô hình được thư viện sử dụng, cũng như các hàm tiện ích mà nó cung cấp.

Phần lớn những điều đó chỉ hữu ích nếu bạn đang thêm các mô hình mới vào thư viện.

Trình gỡ lỗi thêm mô hình

Trình gỡ lỗi thêm mô hình - trình quản lý ngữ cảnh cho các trình thêm mô hình

Context manager này là công cụ dành cho người dùng nâng cao, được thiết kế cho những người thêm model. Nó theo dõi tất cả các lời gọi forward bên trong một forward của model và ghi log một phần (slice) của mỗi input và output vào một JSON lồng nhau. Lưu ý rằng context manager này ép buộc torch.no_grad().

Lý do

Khi chuyển các mô hình sang transformers, ngay cả khi chuyển từ python sang python, những người thêm mô hình thường phải thực hiện nhiều thao tác thủ công, bao gồm lưu và nạp tensor, so sánh dtype, v.v. Công cụ nhỏ này hy vọng có thể giúp tiết kiệm một ít thời gian.

Cách sử dụng

Thêm trình quản lý ngữ cảnh này như sau để gỡ lỗi một mô hình:

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)

Đọc kết quả

Bộ gỡ lỗi tạo ra hai tệp từ lời gọi forward, cả hai đều có cùng tên cơ sở, nhưng kết thúc bằng _SUMMARY.json hoặc _FULL_TENSORS.json.

Phần đầu tiên sẽ chứa tóm tắt về giá trị và hình dạng của tensor đầu vào và đầu ra của từng module.

{
  "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

Tệp _FULL_TENSORS.json sẽ hiển thị toàn bộ các tensor, rất hữu ích để so sánh hai tệp.

      "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')"
      },

Lưu tensor vào đĩa

Một số người thêm model có thể được hưởng lợi từ việc ghi log giá trị tensor đầy đủ xuống đĩa để hỗ trợ, ví dụ, phân tích số học giữa các triển khai.

Đặt use_repr=False để ghi các tensor ra đĩa bằng 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)

Khi sử dụng use_repr=False, các tensor được ghi vào cùng vị trí trên đĩa với các tệp _SUMMARY.json và _FULL_TENSORS.json. Thuộc tính value của các mục trong tệp _FULL_TENSORS.json sẽ chứa tham chiếu đường dẫn tương đối đến tệp .safetensors liên quan. Mỗi tensor được ghi vào tệp riêng của nó dưới dạng thuộc tính data của từ điển trạng thái. Tên tệp được xây dựng bằng cách sử dụng module_path làm tiền tố cùng một vài hậu tố có thể, được xây dựng đệ quy.

  • Đầu vào của module được ký hiệu bằng _inputs và đầu ra bằng _outputs.
  • Các instance của list và tuple, chẳng hạn như args hoặc giá trị trả về của hàm, sẽ được thêm hậu tố _{index}.
  • Các instance dict sẽ được thêm hậu tố _{key}.

So sánh giữa các bản triển khai

Sau khi các bước truyền tiến (forward passes) của hai mô hình đã được debugger theo dõi, ta có thể so sánh các tệp đầu ra json. Xem bên dưới: ta có thể thấy những khác biệt nhỏ giữa lớp dự đoán khóa (key projection layer) của hai cài đặt này. Đầu vào phần lớn là giống hệt nhau, nhưng không hoàn toàn. Việc xem xét các khác biệt trong tệp giúp dễ dàng xác định chính xác lớp nào đang có lỗi.

download-icon

Hạn chế và phạm vi

Tính năng này chỉ hoạt động với các mô hình dựa trên torch. Các mô hình phụ thuộc nhiều vào các lệnh gọi kernel bên ngoài có thể hoạt động, nhưng trace có thể bỏ sót một số thứ. Dù vậy, bất kỳ cài đặt python nào nhằm mô phỏng một cài đặt khác đều có thể được trace một lần thay vì chạy lại N lần với các điểm dừng.

Nếu bạn truyền do_prune_layers=False cho trình gỡ lỗi mô hình của bạn, TẤT CẢ các lớp sẽ được xuất ra json. Ngược lại, chỉ lớp đầu tiên và lớp cuối cùng sẽ được hiển thị. Điều này hữu ích khi một số lớp (thường là cross-attention) chỉ xuất hiện sau N lớp.

transformers.model_addition_debugger_context

< >

( modeldebug_path: str | None = Nonedo_prune_layers: bool = Trueuse_repr: bool = True )

Trình gỡ lỗi thêm mô hình - trình quản lý ngữ cảnh cho các trình thêm mô hình

Trình quản lý ngữ cảnh này là công cụ dành cho người dùng nâng cao, được thiết kế cho những người thêm mô hình.

Nó theo dõi tất cả các lời gọi forward trong một forward của model và ghi lại một phần của mỗi đầu vào và đầu ra vào một tệp JSON lồng nhau. Nếu use_repr=True (mặc định), tệp JSON sẽ ghi lại phiên bản được repr()- hóa của các tensor dưới dạng một danh sách các chuỗi. Nếu use_repr=False, các tensor đầy đủ sẽ được lưu trong các tệp SafeTensors riêng biệt và tệp JSON sẽ cung cấp đường dẫn tương đối đến tệp đó.

Lưu ý rằng trình quản lý ngữ cảnh này thực thi torch.no_grad().

Cách sử dụng

thêm context manager vào một model để gỡ lỗi

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)

Trình phân tích các bài kiểm thử bị bỏ qua

Quét các bài kiểm tra bị bỏ qua - dành cho người thêm và người duy trì model

Công cụ tiện ích nhỏ này là một công cụ dành cho người dùng nâng cao, được thiết kế cho những người thêm và bảo trì model. Nó liệt kê tất cả các phương thức kiểm thử có trong test_modeling_common.py, được kế thừa bởi tất cả các lớp tester của model, và quét kho mã để đo lường số lượng kiểm thử bị bỏ qua và cho những model nào.

Lý do

Khi port các model sang transformers, các test sẽ thất bại như dự kiến, và đôi khi test_modeling_common có vẻ không thể dung hòa với những đặc thù của model hoàn toàn mới của chúng ta. Nhưng làm sao chúng ta có thể chắc chắn rằng mình không phá hỏng mọi thứ khi thêm một skip có vẻ vô hại?

Công cụ tiện ích này:

  • quét tất cả các phương thức test_modeling_common
  • tìm kiếm các thời điểm mà một phương thức bị bỏ qua
  • trả về một tệp json tóm tắt mà bạn có thể tải lên như một DataFrame/xem xét

Ví dụ, test_inputs_embeds bị bỏ qua với tỷ lệ lên đến 39% tại thời điểm viết tiện ích này.

download-icon

Cách sử dụng

Bạn có thể chạy trình phân tích kiểm thử bị bỏ qua theo hai cách:

Quét đầy đủ (mặc định)

Từ thư mục gốc của repo transformers, quét tất cả các phương thức kiểm thử phổ biến và xuất kết quả ra tệp JSON (mặc định: all_tests_scan_result.json).

python utils/scan_skipped_tests.py --output_dir path/to/output
  • --output_dir (tùy chọn): Thư mục nơi kết quả JSON sẽ được lưu. Mặc định là thư mục hiện tại.

Kết quả đầu ra mẫu:

🔬 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

Và nó sẽ tạo ra tệp all_tests_scan_result.json để bạn kiểm tra. JSON được lập chỉ mục theo tên phương thức, và mỗi mục tuân theo schema này, đồng thời chỉ rõ nguồn gốc (từ common hoặc GenerationMixin.)

{
  "<method_name>": {
    "origin": "<test suite>"
    "models_ran": ["<model_name>", ...],
    "models_skipped": ["<model_name>", ...],
    "skipped_proportion": <float>,
    "reasons_skipped": ["<model_name>: <reason>",
      ...
    ]
  },
  ...
}

Bạn có thể trực quan hóa điều này như ở trên, ví dụ bằng pandas

df = pd.read_json('all_tests_scan_result.json').T
df.sort_values(by=['skipped_proportion'], ascending=False)

Quét một phương thức kiểm thử

Bạn có thể tập trung vào một phương thức kiểm thử cụ thể bằng cách sử dụng --test_method_name:

python utils/scan_skipped_tests.py --test_method_name test_inputs_embeds --output_dir path/to/output
  • --test_method_name: Tên của phương thức kiểm tra cần quét (ví dụ: test_inputs_embeds).
  • --output_dir (tùy chọn): Thư mục nơi kết quả JSON sẽ được lưu.

Kết quả đầu ra mẫu:

$ 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

Trình phát hiện mô-đun

Trình phân tích độ tương đồng mã - dành cho người thêm mô hình

Công cụ tiện ích này phân tích sự tương đồng mã giữa các cài đặt mô hình để xác định các cơ hội cho việc mô-đun hóa. Nó so sánh một tệp modeling mới hoặc hiện có với tất cả các mô hình trong thư viện bằng cách sử dụng các chỉ số tương đồng dựa trên embedding và dựa trên token.

Lý do

Khi thêm một mô hình mới vào transformers, nhiều thành phần (lớp attention, MLP, đầu ra, v.v.) có thể đã tồn tại dưới dạng tương tự trong các mô hình khác. Thay vì triển khai mọi thứ từ đầu, người thêm mô hình có thể xác định các lớp hiện có nào tương tự và có khả năng tái sử dụng thông qua việc mô-đun hóa.

Công cụ tính toán hai điểm số tương tự:

  • Điểm nhúng: Sử dụng nhúng mã ngữ nghĩa (thông qua Qwen/Qwen3-Embedding-4B) để phát hiện mã có chức năng tương tự ngay cả khi đặt tên khác nhau
  • Điểm Jaccard: Đo mức độ chồng chéo của tập token để xác định các mẫu mã có cấu trúc tương tự

Điểm 1.00 có nghĩa là mã giống hệt nhau.

Cách sử dụng

Từ thư mục gốc của kho transformers:

python utils/modular_model_detector.py --modeling-file path/to/modeling_file.py

Công cụ sẽ tự động tải xuống chỉ mục đã được xây dựng sẵn từ Hub (yêu cầu RAM/VRAM cho mô hình nhúng).

Kết quả đầu ra mẫu:

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:

Trường intersection hiển thị các lớp xuất hiện trong cả hai kết quả top-5, cho thấy độ tin cậy cao đối với các ứng viên modularization.

Xây dựng chỉ mục tùy chỉnh

Để xây dựng lại chỉ mục từ mã nguồn cục bộ của bạn (hữu ích sau khi thêm các mô hình mới hoặc sử dụng một mô hình nhúng khác):

python utils/modular_model_detector.py --build

Để đẩy chỉ mục đã xây dựng lại lên bộ dữ liệu Hub:

python utils/modular_model_detector.py --build --push-new-index --hub-dataset your-org/your-dataset

Tùy chọn

  • --modeling-file: Đường dẫn đến tệp modeling cần phân tích
  • --build: Xây dựng chỉ mục tương đồng mã từ tất cả các tệp mô hình hóa trong src/transformers/models/
  • --push-new-index: Sau khi xây dựng, đẩy index lên một dataset trên Hub (yêu cầu --build)
  • --hub-dataset: ID kho dữ liệu Hub để kéo/đẩy chỉ mục (mặc định: hf-internal-testing/transformers_code_embeddings)

Hạn chế

Công cụ này yêu cầu tài nguyên GPU/CPU để chạy mô hình embedding (Qwen/Qwen3-Embedding-4B). Chỉ mục được xây dựng sẵn sẽ được tải xuống từ Hub theo mặc định, điều này đòi hỏi kết nối internet khi sử dụng lần đầu.

Kết quả là các gợi ý dựa trên độ tương đồng của mã và nên được xem xét thủ công trước khi thực hiện modularization. Điểm số tương đồng cao không đảm bảo khả năng tương thích hoàn hảo.

Update on GitHub