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

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

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

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

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

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

### المبررات

عند نقل النماذج إلى مكتبة Transformers، وحتى عند الانتقال من لغة Python إلى Python، غالبًا ما يضطر مُضيفو النماذج إلى تنفيذ العديد من العمليات اليدوية، بما في ذلك حفظ وتحميل الموترات (tensors) ومقارنة أنواع البيانات (dtypes) وغيرها. يُرجى أن يساهم هذا الأداة الصغيرة في توفير بعض الوقت.

### الاستخدام

أضِف مُدير السياق هذا على النحو التالي لتصحيح نموذج:

```python
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_ وأبعادها لكل وحدة.

```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` عرضًا كاملًا لجميع المتجهات، وهو مفيد لمقارنة ملفين.

```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](https://huggingface.co/docs/safetensors/en/index).

```python
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](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/files_difference_debugging.png)

### القيود والنطاق[[transformers.model_addition_debugger_context]]

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

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

#### transformers.model_addition_debugger_context[[transformers.model_addition_debugger_context]]

```python
transformers.model_addition_debugger_context(model, debug_path: str | None = None, do_prune_layers: bool = True, use_repr: bool = True)
```

[المصدر](https://github.com/huggingface/transformers/blob/main/src/transformers/model_debugging_utils.py#L391)

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

يتتبع جميع استدعاءات الأمامية (forward) داخل استدعاء الأمامي للنموذج، ويسجّل جزءًا من كل مدخل ومخرج في ملف JSON متداخل. إذا كان `use_repr=True` (الافتراضي)، فسوف يسجّل ملف JSON نسخة مُحوّلة عبر `repr()` من المصفوفات (tensors) على شكل قائمة من النصوص. أما إذا كان `use_repr=False`، فستُخزَّن المصفوفات الكاملة في ملفات SafeTensors منفصلة، وسيوفّر ملف JSON مسارًا نسبيًا إلى ذلك الملف.

يُشار إلى أن مدير السياق هذا يفرض `torch.no_grad()`.

## الاستخدام

أضف مدير السياق إلى نموذج لتصحيح الأخطاء

```python
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](https://huggingface.co/datasets/huggingface/documentation-images/resolve/f7f671f69b88ce4967e19179172c248958d35742/transformers/tests_skipped_visualisation.png)

### الاستخدام

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

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

من جذر مستودع `transformers`، يفحص جميع طرق الاختبار الشائعة ويخرج النتائج إلى ملف JSON (الافتراضي: `all_tests_scan_result.json`).

```bash
python utils/scan_skipped_tests.py --output_dir path/to/output
```

- `--output_dir` (اختياري): المجلد الذي سيتم حفظ نتائج JSON فيه. الافتراضي هو المجلد الحالي.

**مثال على المخرجات:**

```text
🔬 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`.)

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

يمكنك تصور ذلك كما هو موضح أعلاه باستخدام `pandas` على سبيل المثال

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

```

### فحص طريقة اختبار واحدة

يمكنك التركيز على طريقة اختبار محددة باستخدام `--test_method_name`:

```bash
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 فيه.

**مثال على المخرجات:**

```bash
$ 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`:

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

سيقوم الأداة بتنزيل الفهرس المُعدّ مسبقًا من Hub تلقائيًا (يتطلب ذاكرة RAM/VRAM لنموذج التضمين).

**مثال على المخرجات:**

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

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

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

```bash
python utils/modular_model_detector.py --build
```

لإرسال الفهرس المُعاد بناؤه إلى مجموعة بيانات على Hub:

```bash
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 افتراضيًا، مما يتطلب اتصالاً بالإنترنت عند الاستخدام الأول.

النتائج هي اقتراحات مبنية على تشابه الأكواد، وينبغي مراجعتها يدوياً قبل إجراء التعديل المعياري. درجات التشابه العالية لا تضمن التوافق التام.

