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

كتابة اختبارات النموذج

تستخدم مجموعة اختبارات Transformers بنية مبنية على مزيج (mixin) لتوليد أكثر من 100 اختبار تلقائيًا من الحد الأدنى من الكود. تكتب كمية صغيرة من الكود الخاص بالنموذج، ويتولى المزيج (mixins) مهام الحفظ/التحميل، والتوليد، والخطوط الأنابيب (pipelines)، والتدريب، والتوازي على مستوى الموترات (tensor parallelism).

شغّل اختبارات نموذجك باستخدام الأوامر التالية.

# run your model's tests
pytest tests/models/mymodel/test_modeling_mymodel.py -v

# run a specific test
pytest tests/models/mymodel/test_modeling_mymodel.py::MyModelTest::test_model

# run tests matching a keyword pattern (useful to run all integration tests)
pytest tests/models/mymodel/ -k integration -v

# include slow integration tests
RUN_SLOW=1 pytest tests/models/mymodel/ -v

تشغّل منظومة Hugging Face CI اختبارات النماذج دون @slow مع كل طلب سحب، بينما تُنفَّذ الاختبارات البطيئة وفق جدول ليلي (راجع فحوصات طلبات السحب لمعرفة ما تتحقق منه منظومة CI).

اختر فئة اختبار أساسية

تغطي ثلاث فئات أساسية أكثر عائلات النماذج شيوعاً. اختر الفئة التي تتوافق مع نمط نموذجك.

الفئة الأساسيةيُستخدممزيج
CausalLMModelTestنماذج اللغة السببيةModelTesterMixin, GenerationTesterMixin, PipelineTesterMixin, TrainingTesterMixin, TensorParallelTesterMixin
VLMModelTestنماذج الرؤية واللغةModelTesterMixin, GenerationTesterMixin, PipelineTesterMixin
ALMModelTestنماذج اللغة والصوتModelTesterMixin, GenerationTesterMixin, PipelineTesterMixin

يتشارك VLMModelTest وALMModelTest في الوالد المشترك MultiModalModelTest الذي يُضمّن الإعدادات الفرعية داخل إعداد علوي مركّب، ويضع رموز المحلّلات الخاصة بالأنماط في input_ids إلى جانب ميزات النمط الخام (الصوت أو الرؤية). لا يستخدم CausalLMModelTest الوالد متعدد الأنماط. بل يُبنى على المزيجات الثلاث المشتركة ويضيف TrainingTesterMixin وTensorParallelTesterMixin لتغطية التدريب والتوازي على مستوى المصفوفات.

بالنسبة إلى البنى المعمارية التي لا تنتمي إلى أيٍّ من الأنماط الثلاثة (المُشفِّر فقط، المُشفِّر-المُفكِّك، إلخ)، قم ببناء بنية الاختبار مباشرةً من نمط الصنفين ومزيجات الاختبار الموضّحة أدناه.

CausalLMModelTest

CausalLMModelTest هي الفئة الأساسية الموصى بها لاختبار نماذج اللغة السببية. ترث من خمسة مزيج اختبارات وتولّد الاختبارات تلقائيًا للحفظ/التحميل، والتوليد، والخطوط الأنابيب، والتدريب، والتوازي على مستوى الموترات.

import unittest

from transformers.testing_utils import require_torch
from transformers import is_torch_available

from ...causal_lm_tester import CausalLMModelTest, CausalLMModelTester

if is_torch_available():
    from transformers import MyModel


class MyModelTester(CausalLMModelTester):
    if is_torch_available():
        base_model_class = MyModel


@require_torch
class MyModelTest(CausalLMModelTest, unittest.TestCase):
    model_tester_class = MyModelTester

توفر هاتان الصنفان تغطية اختبارية كاملة لـ MyModel وجميع أصناف رؤوسه (MyModelForCausalLM، MyModelForSequenceClassification، إلخ). راجع tests/models/llama/test_modeling_llama.py للحصول على مثال حقيقي.

يتطلب CausalLMModelTester فقط base_model_class. يقوم المُختبِر بإزالة لاحقة Model للحصول على الاسم الأساسي (حيث يصبح LlamaModel هو Llama)، ثم يضيف لواحق مثل Config أو ForCausalLM لاكتشاف الفئات ذات الصلة. إذا لم تكن الفئة موجودة في الوحدة، يبقى الخاصية None ويتخطى المُختبِر الاختبارات المقابلة.

التجاوز عن القيم الافتراضية في CausalLMTester

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

class MyModelTester(CausalLMModelTester):
    if is_torch_available():
        base_model_class = MyModel
        # override if the class name doesn't follow the convention
        causal_lm_class = MyCustomCausalLM


@require_torch
class MyModelTest(CausalLMModelTest, unittest.TestCase):
    model_tester_class = MyModelTester
    # disable embedding resize tests
    test_resize_embeddings = False

بالنسبة إلى النماذج التي تتطلب معلمات مُخصّصة لمُنشئ الاختبار، تجاوز __init__ واستدعِ super().__init__(parent=parent) قبل تعيين السمات الإضافية. راجع tests/models/youtu/test_modeling_youtu.py كمثال حقيقي.

class YoutuModelTester(CausalLMModelTester):
    if is_torch_available():
        base_model_class = YoutuModel

    def __init__(self, parent, kv_lora_rank=16, q_lora_rank=32):
        super().__init__(parent=parent)
        self.kv_lora_rank = kv_lora_rank
        self.q_lora_rank = q_lora_rank

VLMModelTest

VLMModelTest هي الفئة الأساسية لنماذج الرؤية واللغة. ترث من ثلاثة امتزاجات (ModelTesterMixin، GenerationTesterMixin، PipelineTesterMixin) وتضبط _is_composite = True للتعامل مع عدة نماذج فرعية.

import unittest

from transformers.testing_utils import require_torch
from transformers import is_torch_available

from ...vlm_tester import VLMModelTest, VLMModelTester

if is_torch_available():
    from transformers import (
        MyVLMConfig,
        MyVLMModel,
        MyVLMTextConfig,
        MyVLMVisionConfig,
        MyVLMForConditionalGeneration,
    )


class MyVLMTester(VLMModelTester):
    if is_torch_available():
        base_model_class = MyVLMModel
        config_class = MyVLMConfig
        text_config_class = MyVLMTextConfig
        vision_config_class = MyVLMVisionConfig
        conditional_generation_class = MyVLMForConditionalGeneration


@require_torch
class MyVLMTest(VLMModelTest, unittest.TestCase):
    model_tester_class = MyVLMTester

تجاوز القيم الافتراضية في VLMModelTester

عندما يحتاج نموذج VLM إلى معلمات رؤية مخصصة أو قيم إعدادات غير افتراضية، قم بتجاوز __init__. اضبط القيم الافتراضية باستخدام setdefault قبل استدعاء super().__init__(parent, **kwargs). يُظهر المثال أدناه بعض القيم الافتراضية الأولى من tests/models/qianfan_ocr/test_modeling_qianfan_ocr.py.

class QianfanOCRVisionText2TextModelTester(VLMModelTester):
    base_model_class = QianfanOCRModel
    config_class = QianfanOCRConfig
    text_config_class = Qwen3Config
    vision_config_class = QianfanOCRVisionConfig
    conditional_generation_class = QianfanOCRForConditionalGeneration

    def __init__(self, parent, **kwargs):
        kwargs.setdefault("image_token_id", 1)
        kwargs.setdefault("image_size", 32)
        kwargs.setdefault("patch_size", 4)
        kwargs.setdefault("num_channels", 3)
        # ... more defaults
        super().__init__(parent, **kwargs)

تختلف اختبارات VLM عن CausalLMModelTest في عدة نقاط.

  • يجب عليك تعيين config_class وtext_config_class وvision_config_class وconditional_generation_class على المُختبِر.
  • لا يتضمن VLMModelTest أيًا من TrainingTesterMixin أو TensorParallelTesterMixin.
  • يقبل __init__ الخاص بالمختبر معاملات الرؤية (image_size، patch_size، num_channels، num_image_tokens) من **kwargs وsetdefault().
  • ConfigTester يستخدم has_text_modality=False لأن الإعداد العلوي هو إعداد مركّب وليس إعداد نموذج نصي.

ALMModelTest

ALMModelTest هي الفئة الأساسية لنماذج الصوت واللغة (ALMs) مثل Qwen2Audio وAudioFlamingo3 وGraniteSpeech. وهي تعكس نمط نماذج الرؤية واللغة (VLM) مع الفئة الأم MultiModalModelTest نفسها واكتشاف تلقائي لفئات الرؤوس. يتم استبدال آلية جانب الرؤية بخصائص صوتية، وتكوين فرعي للصوت، واستراتيجية لتوزيع رموز الصوت.

class MyALMTester(ALMModelTester):
    config_class = MyALMConfig
    text_config_class = MyALMTextConfig
    audio_config_class = MyALMAudioConfig
    conditional_generation_class = MyALMForConditionalGeneration
    audio_mask_key = "feature_attention_mask"


class MyALMTest(ALMModelTest, unittest.TestCase):
    model_tester_class = MyALMTester

تجاوز القيم الافتراضية في ALMModelTester

يُعيّن __init__ الخاصّ بالاختبار الافتراضيات المحددة لـ ALM (feat_seq_length=128، num_mel_bins=80، audio_token_id=0). عاود ضبطها باستخدام setdefault قبل استدعاء super().__init__(parent, **kwargs).

يُخبر سِمَتان من سِمات الفئة المُختبِرَ كيف يُسمّي نموذجك الأشياء.

  • audio_mask_key: اسم معامل الكلمة الذي يتوقعه النموذج الخاص بك للقناع الصوتي ("feature_attention_mask"، "input_features_mask"، إلخ). اتركه None إذا كان نموذجك لا يستهلك قناعًا صوتيًا منفصلًا.
  • audio_config_key: اسم الخاصية التي يستخدمها الإعداد الرئيسي لتضمين إعداد الصوت الفرعي. القيمة الافتراضية هي "audio_config" لكن نماذج مثل GraniteSpeech تستخدم "encoder_config".
class Qwen2AudioModelTester(ALMModelTester):
    def __init__(self, parent, **kwargs):
        kwargs.setdefault("feat_seq_length", 60)
        kwargs.setdefault("max_source_positions", kwargs["feat_seq_length"] // 2)
        super().__init__(parent, **kwargs)

يتطلب ALMModelTester منك تجاوز خطاف واحد، وهو get_audio_embeds_mask(audio_mask)، كما يعرض خطافات اختيارية إضافية للتخصيص.

  • get_audio_embeds_mask(audio_mask): تُرجع قناع مواضع تضمينات الصوت لكل دفعة بعد عملية تقليل العينات في المُشفِّر. يستخدم المُختبِر مجموع هذا القناع على مستوى الصفوف لتحديد عدد عناصر audio_token_id التي يجب إدراجها في input_ids، لذا يجب أن يتطابق هذا العدد مع ما يُخرجه مُشفِّرك.
  • create_audio_features(): تُرجع متجه ميزات الصوت. الشكل الافتراضي هو [batch_size, num_mel_bins, feat_seq_length]. تجاوز هذا الدالة إذا كان نموذجك، مثل GraniteSpeech، يتوقع ميزات ذات أولوية زمنية ([batch_size, feat_seq_length, num_mel_bins]).
  • create_audio_mask(): تُرجع قناع الانتباه على مستوى الصوت. يقوم الإعداد الافتراضي ببناء منطقة صالحة متصلة عشوائياً لكل صف في الدفعة. استبدله بقناع حتمي بطول كامل إذا كانت اختباراتك تقارن بين استدعائين لـ prepare_config_and_inputs_for_common()، أو إذا كان مُرمِّز الصوت لديك يُحوَّل إلى واجهة خلفية ترفض الأقنعة غير الفارغة.
  • place_audio_tokens(input_ids, config, num_audio_tokens): يضع رموز المحلّلات الصوتية بشكل متتالي بعد BOS. لا تُعدّل هذا الدالة إلا إذا كان نموذجك يتطلب تخطيطًا مختلفًا.
  • get_audio_feature_key(): تُرجع مفتاح قاموس المدخلات الخاص بسمات الصوت (افتراضيًا "input_features").

بالإضافة إلى اختبارات الوسائط المتعددة الموروثة، يضيف ALMModelTest الاختبار test_mismatching_num_audio_tokens. يتحقق هذا الاختبار من أن النموذج يرمي ValueError واضحاً عندما لا يتطابق عدد ميزات الصوت مع عدد رموز الوكيل الصوتية في input_ids، ويتأكد من أن الموجّه الذي يحتوي على مقاطع صوتية متعددة يمرر بنجاح.

اكتب اختبارات لمعماريات أخرى

للمعماريات غير القياسية مثل معماريات المُشفِّر فقط، أو المُشفِّر-المُفكِّك، أو الصوتية، أو غيرها، قم ببناء بنية الاختبار مباشرةً من نمط الصنفين ومزيجات الاختبار (test mixins) الموضحة أدناه.

ModelTester و ModelTest

يتبع كل ملف اختبار للنموذج نفس البنية.

  1. ModelTester (فئة عادية) تنشئ إعدادات صغيرة ومدخلات وهمية للاختبار، كما يمكنها استضافة اختبارات انحدار صغيرة خاصة بالنموذج.
  2. ModelTest (المشتق من unittest.TestCase مع مزيج من الخصائص) يرث الاختبارات المولّدة تلقائيًا وينفّذها على كل متغيّر من نماذج النموذج.

يستدعي ModelTest الدالة prepare_config_and_inputs_for_common() على المُختبِر (tester) للحصول على مجموعة مرتبة من نوع (config, inputs_dict). وتعتمد جميع الإضافات (mixins) على prepare_config_and_inputs_for_common() للحصول على بيانات الاختبار.

اختبار المزيج

اختر الإضافات التي يحتاجها نموذجك.

مزيجملف المصدرما يختبره
ModelTesterMixintests/test_modeling_common.pyالحفظ/التحميل، نقطة التفتيش للتدرّج، توقيع الدالة الأمامية، السمات الشائعة
GenerationTesterMixintests/generation/test_utils.pyالطمع، العينة، البحث الحزمي، فك الترميز المساعد
PipelineTesterMixintests/test_pipeline_mixin.pyاختبار واحد لكل مهمة خط أنابيب
TrainingTesterMixintests/test_training_mixin.pyالانحياز على دفعة صغيرة
TensorParallelTesterMixintests/test_tensor_parallel_mixin.pyالتوازي الموزّع للتّنسورات

كتابة اختبار للنموذج

راجع tests/models/modernbert/test_modeling_modernbert.py للحصول على مثال عملي كامل. الخطوات الأساسية مبيّنة أدناه.

  1. تقوم فئة ModelTester ببناء إعدادات صغيرة ومدخلات وهمية. حافظ على الأبعاد صغيرة حتى تنتهي الاختبارات خلال ثوانٍ على المعالج المركزي. استخدم أدوات المصفوفات الثلاثة أدناه لبناء المدخلات.

    • ids_tensor(shape, vocab_size): مصفوفة أعداد صحيحة عشوائية ضمن [0, vocab_size). تُستخدم مع input_ids وtoken_type_ids ومصفوفات التسميات.
    • random_attention_mask(shape): مصفوفة ثنائية (تتكون من أصفار وواحدات) يكون فيها الرمز الأول دائماً 1. يُستخدم لـ attention_mask.
    • floats_tensor(shape, scale=1.0): مصفوفة عشوائية من الأعداد العشرية. تُستخدم للمدخلات المستمرة مثل pixel_values أو inputs_embeds.

    يجب على المُختبِر تنفيذ get_config() وprepare_config_and_inputs() وprepare_config_and_inputs_for_common(). أضف دوال create_and_check_* لكل رأس مهمة (النموذج الأساسي، تصنيف التسلسل، تصنيف الرموز، إلخ).

  2. ورث من المزيجات (mixins) التي يحتاجها نموذجك، وعرّف all_model_classes وpipeline_model_mapping، وحدد setUp(). اكتب دوال test_* تفوّض المهمة إلى دوال create_and_check_* الخاصة بالفاحص (tester).

  3. لكل رأس مهمة، أضف طريقة create_and_check_* على المُختبِر تُنشئ النموذج، وتُنفّذ تمريرة أمامية، وتتحقق من أشكال المخرجات. ثم أضف طريقة test_* مقابلة على فئة الاختبار.

تنظيم الملفات

توجد ملفات الاختبار في tests/models/mymodel/ وفقاً للهيكل الموضح أدناه.

tests/models/mymodel/
├── __init__.py
├── test_modeling_mymodel.py            # model tests (required)
├── test_tokenization_mymodel.py        # tokenizer tests (if custom tokenizer)
├── test_image_processing_mymodel.py    # image processor tests (if vision model)
├── test_feature_extraction_mymodel.py  # feature extractor tests (if audio/speech model)
└── test_processing_mymodel.py          # processor tests (if multimodal)

تتبع اختبارات المُجزِّئ (Tokenizer) النمط نفسه. ورِّث TokenizerTesterMixin من tests/test_tokenization_common.py، واضبط بعض السمات، لتحصل على اختبارات مُولَّدة تلقائيًا. راجع tests/models/llama/test_tokenization_llama.py كمثال.

اختبارات الإعداد

يتحقق ConfigTester من أن فئة الإعدادات تتعامل مع التسلسل، والحفظ/التحميل، والخصائص القياسية بشكل صحيح. تتضمن CausalLMModelTest وVLMModelTest اختبارات الإعدادات تلقائيًا. بالنسبة للمسار العام باستخدام ModelTester وModelTest، عرّف مُختبِر الإعدادات يدويًا في setUp().

from tests.test_configuration_common import ConfigTester

def setUp(self):
    self.config_tester = ConfigTester(self, config_class=MyModelConfig, hidden_size=32)

def test_config(self):
    self.config_tester.run_common_tests()

run_common_tests() ينفّذ عدة فحوصات.

  • يتحقق من وجود خصائص شائعة مثل hidden_size وnum_attention_heads وnum_hidden_layers (وvocab_size إذا كان has_text_modality=True).
  • يختبر تسلسل JSON باستخدام to_json_string() وto_json_file().
  • تُعيد save_pretrained() وfrom_pretrained() إلى الحالة الأصلية.
  • يتحقق من اتساق id2label وlabel2id.
  • ينشئ تكوينًا دون أي حُجج للتحقق من التهيئة الافتراضية.
  • يُعيّن معاملات مشتركة مثل output_hidden_states ويتحقق من تخزينها بشكل صحيح.

مرّر has_text_modality=False للنماذج البصرية فقط التي تفتقر إلى vocab_size، ومرّر **kwargs إضافية لتجاوز الإعدادات الافتراضية.

self.config_tester = ConfigTester(
    self, config_class=MyVisionConfig, has_text_modality=False, hidden_size=64
)

اختبارات التكامل والنماذج الصغيرة

تستخدم اختبارات المزيج (Mixin tests) إعدادات صغيرة بأوزان عشوائية للتحقق من سلوك النموذج بسرعة. أما اختبارات التكامل (Integration tests) فتشغّل الاستدلال (inference) باستخدام أوزان مُسبقة التدريب الفعلية للتحقق من صحة المخرجات. النماذج الصغيرة على Hub صغيرة الحجم بما يكفي لاختبارات CI السريعة، لكنها مُنظّمة على غرار نقاط التفتيش (checkpoints) الفعلية.

كتابة اختبارات التكامل

ضع اختبارات التكامل في فئة اختبار منفصلة، وعلّمها بـ @slow، وأدرج MemoryCleanupMixin. يقوم كل اختبار بتنزيل أوزان حقيقية، وتشغيل الاستدلال، والتحقق من المخرجات مقابل القيم المتوقعة. يحرر المزيج الذاكرة التي يستهلكها كل اختبار، وينفّذ طرق الاختبار تحت torch.no_grad() — راجع إطلاق الذاكرة بين الاختبارات لمعرفة ما يفعله وكيفية الاستثناء منه.

import torch
from transformers import AutoTokenizer
from transformers.testing_utils import MemoryCleanupMixin, require_torch, slow, torch_device

class MyModelIntegrationTest(MemoryCleanupMixin, unittest.TestCase):
    @slow
    @require_torch
    def test_inference(self):
        model = MyModelForCausalLM.from_pretrained("myorg/mymodel-base").to(torch_device)
        tokenizer = AutoTokenizer.from_pretrained("myorg/mymodel-base")
        inputs = tokenizer("Hello, world", return_tensors="pt").to(torch_device)

        outputs = model(**inputs)

        # check against expected values
        expected_slice = torch.tensor([[-0.1234, 0.5678, -0.9012]])
        torch.testing.assert_close(outputs.logits[0, :1, :3], expected_slice, atol=1e-4, rtol=1e-4)

علّم أي اختبار بـ @slow إذا كان يقوم بتنزيل الأوزان، أو تحميل مجموعة بيانات كبيرة، أو يستغرق أكثر من بضع ثوانٍ. يتخطى اختبار CI الخاص بطلب السحب الاختبارات البطيئة، لكن الجدولة الليلية تشغّلها.

إفراج عن الذاكرة بين الاختبارات

تحمّل اختبارات التكامل نقاط تفتيش حقيقية، لذا فإن اختباراً يحتفظ بمراجع إلى نموذج يمكن أن يستهلك كل الذاكرة المتاحة لأي عملية تُنفَّذ بعده. يتولى MemoryCleanupMixin، الموجود في tests/test_memory_cleanup_mixin.py، معالجة ذلك على مستوى الفئة بأكملها:

  • يُنفّذ cleanup(torch_device, gc_collect=True) قبل وبعد كل اختبار حتى لا تنتقل أي بقايا.
  • يحذف السمات التي أضافها الاختبار على self (بما في ذلك كاشات @cached_property) وعلى الفئة (على سبيل المثال cls.model = ... في setUpClass). يحافظ Pytest على بقاء كائنات الاختبار حية طوال الجلسة، لذا لا يمكن لـgc.collect() تحرير الكائنات التي لا تزال هذه المراجع تحتفظ بها.
  • تشغّل طرق الاختبار تحت torch.no_grad() حتى لا تحتفظ عملية المرور الأمامي بالتفعيلات.

تضبط الفئات التي تُدرّب أو تستدعي backward() قيمة run_under_no_grad = False. أما الفئة التي تجمع بين الأمرين فتضع @with_grad أو @with_no_grad على طرق الاختبار الفردية بدلاً من ذلك.

تُحفظ السمات المُعيَّنة في جسم الفئة، بينما تُهمل كل ما يُضاف لاحقًا. إذا تجاوزت setUp، فاستدعِ super().setUp(): إذ يلتقط المزيج (mixin) سمات الكائن هناك، وسيُصدر خطأً في حال عدم استدعائه.

يجمع MemoryCleanupTestCase بين المكوّن المختلط (mixin) وTestCasePlus، وذلك للاختبارات التي ترغب أيضًا في إزالة المجلدات المؤقتة تلقائيًا.

لاستخراج اختبار تسرّب، اضبط TRANSFORMERS_TEST_MEMORY_LEAK_MIB على ميزانية محددة بوحدة ميغابايت؛ وسيتم الإبلاغ عن أي اختبار يترك تخصيصًا أكبر من ذلك على الجهاز مع ذكر ذروة استهلاكه. أضف TRANSFORMERS_TEST_MEMORY_LEAK_MODE=error لتحويل التحذير إلى فشل. هذا الفحص معطّل افتراضيًا، وينبغي تفعيله عند البحث عن بقايا الذاكرة. كما أن عملية التفكيك المعتادة في الميكس-إن تشغّل gc.collect، مما قد يؤدي إلى مسح التخصيص الذي ترغب في فحصه أثناء إعادة إنتاج التسرّب.

اختبارات تكامل التوليد

استخدم do_sample=False في اختبارات التوليد حتى تكون المخرجات حتمية عبر التكرارات والأجهزة. بالنسبة لنماذج مزيج الخبراء، استدعِ أيضاً model.set_experts_implementation("eager") قبل التوليد لفرض مسار ثابت لتوجيه الخبراء. بدونه، قد تُغيّر الفروق العددية الصغيرة في الموجّه الخبير الذي يتولى معالجة الرمز، مما يغيّر المخرجات.

@slow
@require_torch
def test_generate(self):
    model = MyModelForCausalLM.from_pretrained("myorg/mymodel-base").to(torch_device)
    tokenizer = AutoTokenizer.from_pretrained("myorg/mymodel-base")
    inputs = tokenizer("Hello, world", return_tensors="pt").to(torch_device)

    # model.set_experts_implementation("eager")  # uncomment for MoE models
    generated_ids = model.generate(**inputs, max_new_tokens=20, do_sample=False)
    output = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)
    self.assertEqual(output, ["Hello, world! This is the expected continuation..."])

التوقعات الخاصة بالمعدات

تُنفّذ اختبارات CI الخاصة بـ Transformers الاختبارات البطيئة على بطاقة NVIDIA A10. قد تختلف النتائج العددية قليلاً بين أجيال وحدات معالجة الرسوميات (GPU)، لذا تستخدم اختبارات التكامل فئة Expectations لتسجيل القيم المتوقعة لكل جهاز. تختار Expectations التطابق الأنسب للأجهزة الحالية بناءً على مفاتيح SM من نوع (device_type, (major, minor))، وتلجأ إلى قيمة افتراضية عند عدم وجود تطابق.

شغّل torch.cuda.get_device_capability() لطباعة إصدار SM المحلي لديك (مثل (8, 6) لبطاقة A10، أو (9, 0) لبطاقة H100).

from transformers.testing_utils import Expectations

expected_texts = Expectations(
    {
        ("cuda", (8, 6)): ["Hello, world! This is the A10 continuation..."],
        ("cuda", (9, 0)): ["Hello, world! This is the H100 continuation..."],
    }
).get_expectation()

self.assertEqual(output, expected_texts)

إنشاء نماذج صغيرة

توجد نماذج صغيرة ذات أوزان عشوائية على الـ Hub ضمن منظمة hf-internal-testing. تعتمد اختبارات خطوط الأنابيب على النماذج الصغيرة عندما تحتاج إلى نقطة تفتيش مستضافة على الـ Hub دون الاهتمام بجودة المخرجات. كما تُحمّل اختبارات الدخان السريعة النماذج الصغيرة للتحقق من أشكال المرور الأمامي دون الحاجة إلى تنزيل نقاط تفتيش كبيرة.

تُعدّ النماذج الصغيرة الملاذ الأخير لاختبارات التكامل. لا تستخدمها إلا عندما يتجاوز أصغر نقطة تفتيش (checkpoint) المتاحة حوالي 24 غيغابايت من ذاكرة الفيديو (VRAM). استخدم الأوزان المُسبقة التدريب الأصلية، كلما أمكن ذلك، للكشف عن الانحسارات العددية الحقيقية.

ينشئ السكربت utils/create_dummy_models.py نماذج صغيرة من ModelTester.get_config(). يستخرج السكربت المعاملات الفائقة الصغيرة من مُختبِرك، ويبني نموذجًا بأوزان عشوائية، ثم يرفع النتيجة إلى Hub.

أنشئ نماذج صغيرة محليًا.

python utils/create_dummy_models.py output_dir -m your_model_type

ارفعها إلى Hub.

python utils/create_dummy_models.py output_dir -m your_model_type --upload --organization hf-internal-testing

يستخدم كل نموذج الاسم hf-internal-testing/tiny-random-{ModelClassName} ويُسجَّل في tests/utils/tiny_model_summary.json. يقوم سير عمل CI (.github/workflows/check_tiny_models.yml) بإعادة توليد النماذج الصغيرة يوميًا.

تحكّم في ما يتم اختباره

تتحكم الأعلام المنطقية على ModelTesterMixin في الاختبارات المولَّدة تلقائيًا. يمكنك تجاوز أي علم في فئة الاختبار الخاصة بك لتفعيل أو تعطيل فحوصات محددة.

class MyModelTest(CausalLMModelTest, unittest.TestCase):
    model_tester_class = MyModelTester
    test_resize_embeddings = False
    test_all_params_have_gradient = False  # when not all parameters are activated in every forward pass
علمافتراضيما يتحكم به
test_resize_embeddingsTrueتغيير حجم طبقة التضمين
test_resize_position_embeddingsFalseتغيير حجم تضمين الموقع
test_mismatched_shapesTrueمعالجة الأشكال غير المتطابقة للمدخلات/المخرجات
test_missing_keysTrueتحذيرات مفاتيح مفقودة عند التحميل
test_torch_exportableTrueالتوافق مع torch.export
test_all_params_have_gradientTrueتستقبل جميع المعاملات التدرجات (اضبط False عندما لا يتم تفعيل جميع المعاملات في كل تمريرة أمامية، كما هو الحال مع خبراء MoE)
is_encoder_decoderFalseاختبارات محددة لمعمارية المُشفِّر-المُفكِّك
has_attentionsTrueاختبارات مخرجات الانتباه
_is_compositeFalseمعالجة النماذج المركبة/المتعددة الوسائط
model_split_percents[0.5, 0.7, 0.9]نسب التقسيم لاختبارات توازي النموذج

الخطوات التالية

  • تصفّح وثائق pytest لمزيد من المعلومات حول اختيار الاختبارات، والتثبيتات، والتسجيل، والمزيد.
Update on GitHub