Transformers documentation

صناديق أدوات تصحيح أخطاء النماذج

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

صناديق أدوات تصحيح أخطاء النماذج

تُدرج هذه الصفحة جميع أدوات التصحيح وإضافة النماذج التي يستخدمها المكتبة، بالإضافة إلى دوال المرافق التي توفرها له.

معظمها لا يكون مفيدًا إلا إذا كنت تضيف نماذج جديدة إلى المكتبة.

أدوات تصحيح أخطاء إضافة النموذج

مُصحِّح إضافة النموذج - مدير سياق لإضافات النموذج

يُعدّ مدير السياق هذا أداة متقدمة موجهة لإضافات النماذج. يتتبع جميع استدعاءات الأمامية (forward) داخل استدعاء الأمامي للنموذج، ويسجّل جزءًا من كل مدخل ومخرج في ملف JSON متداخل. تجدر الإشارة إلى أن مدير السياق هذا يفرض torch.no_grad().

المبررات

عند نقل النماذج إلى مكتبة Transformers، وحتى من لغة بايثون إلى بايثون، غالبًا ما يضطر مَن يضيفون النماذج إلى تنفيذ العديد من العمليات اليدوية، بما في ذلك حفظ وتحميل المتجهات (tensors) ومقارنة أنواع البيانات (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)

قراءة النتائج

يولّد مُصحِّح الأخطاء ملفَّين من استدعاء الأمامي، وكلاهما يحمل الاسم الأساسي نفسه، لكن ينتهي أحدهما بـ_SUMMARY.json والآخر بـ_FULL_TENSORS.json.

ستحتوي الأولى على ملخص لقيم الأشكال input وoutput وأبعادها لكل وحدة.

{
  "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، تُكتب المتجهات (tensors) إلى نفس الموقع على القرص الذي تُحفظ فيه ملفات _SUMMARY.json و_FULL_TENSORS.json. ستحتوي خاصية value في إدخالات ملف _FULL_TENSORS.json على مسار نسبي يشير إلى ملف .safetensors المرتبط. يُكتب كل متجه في ملف خاص به كخاصية data في قاموس الحالة (state dictionary). تُبنى أسماء الملفات باستخدام module_path كبداية، مع بعض لاحقات محتملة تُبنى بشكل تكراري.

  • يُرمز إلى مدخلات الوحدة بـ _inputs ومخرجاتها بـ _outputs.
  • ستُضاف لاحقة _{index} إلى كائنات list وtuple، مثل args أو قيم إرجاع الدوال.
  • ستُضاف لاحقة _{key} إلى كائنات dict.

المقارنة بين التطبيقات

بمجرد أن يتتبع مُصحّح الأخطاء عمليات المرور الأمامية لنموذجين، يمكن مقارنة ملفات المخرجات json. انظر أدناه: يمكننا ملاحظة اختلافات طفيفة بين طبقة الإسقاط الرئيسية لهذين التنفيذين. المدخلات متطابقة إلى حد كبير، لكن ليس تمامًا. يساعد التصفح عبر اختلافات الملفات في تحديد الطبقة الخاطئة بدقة أكبر.

download-icon

القيود والنطاق

ستعمل هذه الميزة فقط مع النماذج القائمة على torch. قد تعمل النماذج التي تعتمد بشكل كبير على استدعاءات نواة خارجية، لكن التتبع (trace) على الأرجح سيفوّت بعض الأمور. ومع ذلك، يمكن تتبّع أي تطبيق بلغة بايثون يهدف إلى محاكاة تطبيق آخر مرة واحدة بدلاً من إعادة تشغيله N مرات مع نقاط توقف.

إذا مررت do_prune_layers=False إلى مُصحِّح النموذج الخاص بك، فسيتم إخراج جميع الطبقات إلى json. وإلا، فسيتم عرض الطبقة الأولى والأخيرة فقط. وهذا مفيد عندما تظهر بعض الطبقات (عادةً الانتباه المتقاطع) فقط بعد N طبقة.

transformers.model_addition_debugger_context

< >

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

مُصحِّح إضافة النموذج - مدير سياق لإضافات النموذج

هذا مدير السياق هو أداة متقدمة مخصصة لإضافات النماذج.

يتتبع جميع استدعاءات الأمامية (forward) داخل استدعاء الأمامي للنموذج، ويسجّل جزءًا من كل مدخل ومخرج في ملف JSON متداخل. إذا كان use_repr=True (الافتراضي)، فسوف يسجّل ملف JSON نسخة مُحوّلة عبر repr() من المصفوفات (tensors) على شكل قائمة من النصوص. أما إذا كان 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
  • يبحث عن الأوقات التي يتم فيها تجاوز طريقة
  • يعيد ملف json ملخص يمكنك تحميله كـ DataFrame أو فحصه

على سبيل المثال، يتم تجاوز test_inputs_embeds بنسبة مذهلة تبلغ 39% عند كتابة هذا الأداة المساعدة.

download-icon

الاستخدام

يمكنك تشغيل محلل الاختبارات المتخطاة بطريقتين:

مسح كامل (افتراضي)

من جذر مستودع 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

كاشف نماذج معيارية

محلل تشابه الأكواد - لإضافة النماذج

تحلل هذه الأداة تشابهات الأكواد بين تنفيذه نماذج مختلفة لتحديد الفرص المتاحة لتجزئة البنية. وتقوم بمقارنة ملف نمذجة جديد أو قائم مع جميع النماذج الموجودة في المكتبة باستخدام مقاييس التشابه القائمة على التضمينات (embeddings) ومقاييس التشابه القائمة على الرموز (tokens).

المبررات

عند إضافة نموذج جديد إلى 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 الفئات التي تظهر في كلا قائمتي النتائج الخمس الأولى، مما يدل على درجة عالية من الثقة في المرشحين للتقسيم إلى وحدات.

بناء فهرس مخصص

لإعادة بناء الفهرس من قاعدة الكود المحلية (مفيد بعد إضافة نماذج جديدة أو استخدام نموذج تضمين مختلف):

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