# أدوات

دوال مساعدة وأدوات للعمل مع 🤗 Diffusers.

## numpy_to_pil[[diffusers.utils.numpy_to_pil]]

#### diffusers.utils.numpy_to_pil[[diffusers.utils.numpy_to_pil]]

```python
diffusers.utils.numpy_to_pil(images)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/pil_utils.py#L35)

تحويل صورة numpy أو دفعة من الصور إلى صورة PIL.

## pt_to_pil[[diffusers.utils.pt_to_pil]]

#### diffusers.utils.pt_to_pil[[diffusers.utils.pt_to_pil]]

```python
diffusers.utils.pt_to_pil(images)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/pil_utils.py#L25)

تحويل صورة torch إلى صورة PIL.

## load_image[[diffusers.utils.load_image]]

#### diffusers.utils.load_image[[diffusers.utils.load_image]]

```python
diffusers.utils.load_image(image: str | PIL.Image.Image, convert_method: typing.Optional[typing.Callable[[PIL.Image.Image], PIL.Image.Image]] = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/loading_utils.py#L14)

**المعاملات:**

image (`str` أو `PIL.Image.Image`) : الصورة التي سيتم تحويلها إلى صيغة صورة PIL.

convert_method (Callable[[PIL.Image.Image], PIL.Image.Image], *اختياري*) : طريقة تحويل تُطبَّق على الصورة بعد تحميلها. عند ضبطها على `None` ستُحوَّل الصورة إلى "RGB".

**يعيد:** `PIL.Image.Image`

صورة PIL.

يحمّل `image` إلى صورة PIL.

## load_video[[diffusers.utils.load_video]]

#### diffusers.utils.load_video[[diffusers.utils.load_video]]

```python
diffusers.utils.load_video(video: str, convert_method: typing.Optional[typing.Callable[[list[PIL.Image.Image]], list[PIL.Image.Image]]] = None, return_fps: bool = False)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/loading_utils.py#L57)

**المعاملات:**

video (`str`) : عنوان URL أو مسار لفيديو لتحويله إلى قائمة بصيغة صور PIL.

convert_method (Callable[[list[PIL.Image.Image]], list[PIL.Image.Image]], *اختياري*) : طريقة تحويل تُطبَّق على الفيديو بعد تحميله. عند ضبطها على `None` سيتم تحويل الصور إلى "RGB".

return_fps (`bool`، *اختياري*، القيمة الافتراضية `False`) : ما إذا كان يجب إرجاع معدل الإطارات الذي تم ترميز الفيديو به أيضاً. وهو مطلوب في خطوط الأنابيب التي تعيد أخذ عينات من الإدخال إلى معدل الإطارات الذي يعمل به النموذج، لأن قائمة الإطارات لا تحمل هذه المعلومات.

**يعيد:** `list[PIL.Image.Image]` أو `tuple[list[PIL.Image.Image], float]`

الفيديو كقائمة من صور PIL، ومعدل إطاراته إذا تم تعيين `return_fps`.

يحمّل `video` إلى قائمة من صور PIL.

## export_to_gif[[diffusers.utils.export_to_gif]]

#### diffusers.utils.export_to_gif[[diffusers.utils.export_to_gif]]

```python
diffusers.utils.export_to_gif(image: list[PIL.Image.Image], output_gif_path: str = None, fps: int = 10)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/export_utils.py#L37)

## export_to_video[[diffusers.utils.export_to_video]]

#### diffusers.utils.export_to_video[[diffusers.utils.export_to_video]]

```python
diffusers.utils.export_to_video(video_frames: list[np.ndarray] | list[PIL.Image.Image], output_video_path: str = None, fps: int = 10, quality: float = 5.0, bitrate: int | None = None, macro_block_size: int | None = 16)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/export_utils.py#L150)

quality: جودة مخرجات الفيديو. القيمة الافتراضية هي 5. يستخدم معدل بت متغير. أعلى جودة هي 10، وأدناها هي 0. اضبطها على None لمنع أعلام معدل البت المتغير من الوصول إلى FFMPEG حتى تتمكن من تحديدها يدويًا باستخدام output_params بدلاً من ذلك. تحديد معدل بت ثابت باستخدام `bitrate` يعطّل هذا المعامل.

bitrate: تحديد معدل بت ثابت لتشفير الفيديو. القيمة الافتراضية هي None مما يؤدي إلى استخدام معامل `quality` بدلاً من ذلك. ستنتج فيديوهات بجودة أفضل وحجم ملف أصغر عند استخدام معامل معدل بت متغير `quality` بدلاً من تحديد معدل بت ثابت باستخدام هذا المعامل.

macro_block_size: قيد الحجم للفيديو. العرض والارتفاع، ويجب أن يكونا قابلين للقسمة على هذا الرقم. إذا لم يكونا قابلين للقسمة على هذا الرقم، سيطلب imageio من ffmpeg تكبير الصورة إلى أقرب حجم قابل للقسمة على هذا الرقم. معظم مشفّرات الفيديو متوافقة مع حجم كتلة ماكرو يساوي 16 (الافتراضي)، وبعضها يمكن أن يكون أصغر (4، 8). لتعطيل هذه الميزة التلقائية، اضبطه على None أو 1، مع تحذير بأن العديد من مشغلات الفيديو لا تستطيع فك ترميز الفيديوهات ذات الأبعاد الفردية، وبعض المشفّرات ستنتج نتائج رديئة أو تفشل. راجع https://en.wikipedia.org/wiki/Macroblock.

## encode_video[[diffusers.utils.encode_video]]

#### diffusers.utils.encode_video[[diffusers.utils.encode_video]]

```python
diffusers.utils.encode_video(video: list[PIL.Image.Image] | np.ndarray | 'torch.Tensor' | Iterator['torch.Tensor'], fps: int, output_path: str, audio: 'torch.Tensor' | None = None, audio_sample_rate: int | None = None, video_chunks_number: int = 1)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/export_utils.py#L304)

**المعاملات:**

video (`List[PIL.Image.Image]` أو `np.ndarray` أو `torch.Tensor`) : متجه فيديو (video tensor) بأبعاد [frames, height, width, channels] بقيم بكسل صحيحة ضمن المدى [0, 255]. إذا كان المدخل من نوع `np.ndarray`، يُتوقع أن يكون مصفوفة أرقام عشرية بقيم ضمن المدى [0, 1] (وهو ما تعيده خطوط الأنابيب عادةً مع `output_type="np"`).

fps (`int`) : عدد الإطارات في الثانية (FPS) للفيديو المُرمَّز.

output_path (`str`) : المسار الذي سيتم حفظ الفيديو المُرمَّز فيه.

audio (`torch.Tensor`، *اختياري*) : موجة صوتية ذات الشكل [audio_channels, samples].

audio_sample_rate : (`int`, *اختياري*): معدل أخذ العينات لموجة الصوت.

video_chunks_number (`int`، *اختياري*، القيمة الافتراضية `1`) : عدد الأجزاء التي يُقسَّم إليها الفيديو للتشفير. سيتم تشفير كل جزء بشكل مستقل. غالبًا ما يعتمد عدد الأجزاء المستخدمة على إعدادات التقطيع (tiling) الخاصة بنموذج VAE للفيديو.

يقوم بتشفير فيديو مع صوت اختياري باستخدام مكتبة PyAV. يعتمد على الكود من مستودع LTX-2 الأصلي: https://github.com/Lightricks/LTX-2/blob/4f410820b198e05074a1e92de793e3b59e9ab5a0/packages/ltx-pipelines/src/ltx_pipelines/utils/media_io.py#L182

## make_image_grid[[diffusers.utils.make_image_grid]]

#### diffusers.utils.make_image_grid[[diffusers.utils.make_image_grid]]

```python
diffusers.utils.make_image_grid(images: list[PIL.Image.Image], rows: int, cols: int, resize: int = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/pil_utils.py#L51)

يُعدّ شبكة واحدة من الصور. مفيد لأغراض التصور.

## randn_tensor[[diffusers.utils.torch_utils.randn_tensor]]

#### diffusers.utils.torch_utils.randn_tensor[[diffusers.utils.torch_utils.randn_tensor]]

```python
diffusers.utils.torch_utils.randn_tensor(shape: tuple | list, generator: list['torch.Generator'] | 'torch.Generator' | None = None, device: str | 'torch.device' | None = None, dtype: 'torch.dtype' | None = None, layout: 'torch.layout' | None = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/torch_utils.py#L61)

دالة مساعدة لإنشاء مصفوفات عشوائية على `device` المطلوب مع `dtype` المطلوب. عند تمرير قائمة من المولّدات، يمكنك تحديد البذرة لكل حجم دفعة على حدة. إذا تم تمرير مولّدات CPU، فإن المصفوفة تُنشأ دائمًا على CPU.

## TorchDeviceBackend[[diffusers.utils.torch_utils.TorchDeviceBackend]]

#### diffusers.utils.torch_utils.TorchDeviceBackend[[diffusers.utils.torch_utils.TorchDeviceBackend]]

```python
diffusers.utils.torch_utils.TorchDeviceBackend(device: str | torch.device | None = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/torch_utils.py#L228)

وكيل (Proxy) لمساحة الأسماء `torch.<backend>` (`torch.cuda`، `torch.xpu`، `torch.mps`، ...) لجهاز واحد. الخصائص التي لا تُعرّفها الفئة هي خصائص الوحدة نفسها (`synchronize`، `device_count`، `Stream`، `current_stream`، ...)؛ أما الطرق المعرّفة هنا فتتجاوز العمليات التي يختلف توفرها بين الخلفيات (backends) وتحتاج إلى بديل احتياطي: مسح ذاكرة التخزين المؤقت، وتعيين البذرة (seeding)، واستعلامات الذاكرة. في حال عدم وجود `device`، يكتشف مُسرّع المضيف (host accelerator) عبر `torch.accelerator`. يثير استثناءً إذا لم يكن لدى torch وحدة للخلفية (backend) بدلاً من الرجوع بصمت إلى `torch.cuda`.

#### max_memory_allocated[[diffusers.utils.torch_utils.TorchDeviceBackend.max_memory_allocated]]

```python
max_memory_allocated()
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/torch_utils.py#L291)

ذروة الذاكرة المخصصة على الجهاز بالبايت منذ آخر إعادة تعيين؛ 0 حيث لا يحتفظ البرنامج الخلفي بأي إحصاءات.

#### mem_get_info[[diffusers.utils.torch_utils.TorchDeviceBackend.mem_get_info]]

```python
mem_get_info()
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/utils/torch_utils.py#L279)

الذاكرة الحرة وإجمالي ذاكرة الجهاز بالبايت.

## apply_layerwise_casting[[diffusers.hooks.apply_layerwise_casting]]

#### diffusers.hooks.apply_layerwise_casting[[diffusers.hooks.apply_layerwise_casting]]

```python
diffusers.hooks.apply_layerwise_casting(module: Module, storage_dtype: dtype, compute_dtype: dtype, skip_modules_pattern: str | tuple[str, ...] = 'auto', skip_modules_classes: tuple[typing.Type[torch.nn.Module], ...] | None = None, non_blocking: bool = False)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/hooks/layerwise_casting.py#L101)

**المعاملات:**

module (`torch.nn.Module`) : الوحدة التي سيتم تحويل وحداتها الفرعية إلى نوع بيانات عالي الدقة للحساب، وإلى نوع بيانات منخفض الدقة للتخزين.

storage_dtype (`torch.dtype`) : نوع البيانات (dtype) الذي يجب تحويل الوحدة إليه قبل/بعد تمرير الأمامي (forward pass) من أجل التخزين.

compute_dtype (`torch.dtype`) : نوع البيانات الذي يُحوَّل إليه الوحدة أثناء المرور الأمامي للحساب.

skip_modules_pattern (`tuple[str, ...]`، القيمة الافتراضية `"auto"`) : قائمة أنماط لمطابقة أسماء الوحدات التي يجب تجاوزها أثناء عملية الإخفاء الطبقي. إذا تم ضبطها على `"auto"`، تُستخدم الأنماط الافتراضية. إذا تم ضبطها على `None`، لا يتم تجاوز أي وحدات. إذا تم ضبطها على `None` بالتزامن مع كون `skip_modules_classes` هي `None`، تُطبَّق عملية الإخفاء الطبقي مباشرةً على الوحدة بدلاً من وحداتها الفرعية الداخلية.

skip_modules_classes (`tuple[Type[torch.nn.Module], ...]`، القيمة الافتراضية `None`) : قائمة بفئات الوحدات التي يجب تجاوزها أثناء عملية الصب على مستوى الطبقات.

non_blocking (`bool`، القيمة الافتراضية `False`) : إذا كانت `True`، فإن عمليات تحويل الأوزان غير حاصِرة.

يطبّق الإجراء تحويل الطبقات (layerwise casting) على وحدة محددة. يُفترض أن تكون الوحدة هنا من نوع Diffusers ModelMixin، لكنها يمكن أن تكون أي nn.Module يستخدم طبقات diffusers أو أساسيات pytorch.

مثال:

```python
>>> import torch
>>> from diffusers import CogVideoXTransformer3DModel

>>> transformer = CogVideoXTransformer3DModel.from_pretrained(
...     model_id, subfolder="transformer", torch_dtype=torch.bfloat16
... )

>>> apply_layerwise_casting(
...     transformer,
...     storage_dtype=torch.float8_e4m3fn,
...     compute_dtype=torch.bfloat16,
...     skip_modules_pattern=["patch_embed", "norm", "proj_out"],
...     non_blocking=True,
... )
```

## apply_group_offloading[[diffusers.hooks.apply_group_offloading]]

#### diffusers.hooks.apply_group_offloading[[diffusers.hooks.apply_group_offloading]]

```python
diffusers.hooks.apply_group_offloading(module: Module, onload_device: typing.Union[str, torch.device], offload_device: typing.Union[str, torch.device] = torch.device(), offload_type: str | diffusers.hooks.group_offloading.GroupOffloadingType = 'block_level', num_blocks_per_group: int | None = None, non_blocking: bool = False, use_stream: bool = False, record_stream: bool = False, low_cpu_mem_usage: bool = False, offload_to_disk_path: str | None = None, block_modules: list[str] | None = None, exclude_kwargs: list[str] | None = None)
```

[المصدر](https://github.com/huggingface/diffusers/blob/v0.43.0/src/diffusers/hooks/group_offloading.py#L567)

**المعاملات:**

module (`torch.nn.Module`) : الوحدة التي يُطبَّق عليها تفريغ المجموعة.

onload_device (`torch.device`) : الجهاز الذي تُحمَّل عليه مجموعة الوحدات.

offload_device (`torch.device`، الافتراضي هو `torch.device("cpu")`) : الجهاز الذي يتم نقل مجموعة الوحدات إليه. يجب أن يكون هذا الجهاز عادةً وحدة المعالجة المركزية (CPU). الافتراضي هو وحدة المعالجة المركزية (CPU).

offload_type (`str` أو `GroupOffloadingType`، الافتراضي هو "block_level") : نوع الإزاحة (offloading) الذي سيتم تطبيقه. يمكن أن يكون أحد "block_level" أو "leaf_level". الافتراضي هو "block_level".

offload_to_disk_path (`str`، *اختياري*، القيمة الافتراضية `None`) : المسار إلى المجلد الذي سيتم فيه تفريغ المعاملات. قد يكون ضبط هذا الخيار مفيدًا في بيئات محدودة الذاكرة العشوائية (RAM) حيث يُرغب في تحقيق توازن معقول بين السرعة والذاكرة.

num_blocks_per_group (`int`, *اختياري*) : عدد الكتل في كل مجموعة عند استخدام offload_type="block_level". هذا مطلوب عند استخدام offload_type="block_level".

non_blocking (`bool`، القيمة الافتراضية `False`) : إذا كانت القيمة True، يتم تنفيذ عمليات الإزاحة (offloading) والتحميل (onloading) باستخدام نقل بيانات غير محجوز.

use_stream (`bool`، القيمة الافتراضية `False`) : إذا كانت القيمة True، يتم تنفيذ عمليات الإزاحة (offloading) والتحميل (onloading) بشكل غير متزامن باستخدام تدفق CUDA. قد يكون ذلك مفيدًا لتداخل العمليات الحسابية مع نقل البيانات.

record_stream (`bool`، القيمة الافتراضية `False`) : عند تفعيله مع `use_stream`، يُعلّم المصفوفة الحالية بأنها استُخدمت بواسطة هذا التيار. فهو أسرع على حساب زيادة طفيفة في استهلاك الذاكرة. راجع [التوثيق الرسمي لـ PyTorch](https://pytorch.org/docs/stable/generated/torch.Tensor.record_stream.html) لمزيد من التفاصيل.

low_cpu_mem_usage (`bool`، القيمة الافتراضية `False`) : إذا كانت القيمة True، يتم تقليل استخدام ذاكرة المعالج المركزي (CPU) عن طريق تثبيت المصفوفات (tensors) أثناء التشغيل بدلاً من تثبيتها مسبقاً. لا تهم هذه الخيارات إلا عند استخدام إزاحة المعالج المركزي (CPU) عبر البث (أي `use_stream=True`). قد يكون هذا مفيداً عندما تكون ذاكرة المعالج المركزي عنقاً زجاجة، لكنه قد يقاوم فوائد استخدام البث (streams).

block_modules (`list[str]`، *اختياري*) : قائمة بأسماء الوحدات التي يجب معالجتها كتُحَف (blocks) للتفريغ. إذا تم تقديمها، فسيتم النظر في هذه الوحدات فقط للتفريغ على مستوى التُحَف. إذا لم تُقدَّم، فسيتم استخدام منطق اكتشاف التُحَف الافتراضي.

exclude_kwargs (`list[str]`، *اختياري*) : قائمة بمفاتيح kwarg التي يجب ألا تُعالج بواسطة send_to_device. هذا مفيد للحالات المتغيرة مثل قوائم التخزين المؤقت التي تحتاج إلى الحفاظ على هوية كائنها عبر عمليات الأمامية. إذا لم يُقدَّم، فسيتم استنتاجها من خاصية `_skip_keys` للوحدة إذا كانت موجودة.

يطبّق تفريغ المجموعات على الطبقات الداخلية لـ torch.nn.Module. لفهم ما هو تفريغ المجموعات، وأين يكون مفيداً، نحتاج أولاً إلى تقديم بعض السياق حول كيفية عمل طرق التفريغ الأخرى المدعومة.

عادةً، يتم تنفيذ الإزاحة على مستويين:
- على مستوى الوحدة: في Diffusers، يمكن تفعيل ذلك باستخدام طريقة `ModelMixin::enable_model_cpu_offload()`. تعمل هذه الطريقة عن طريق نقل كل مكوّن من مكوّنات خط الأنابيب إلى وحدة المعالجة المركزية (CPU) للتخزين، ثم تحميله على جهاز التسريع عند الحاجة إليه للحساب. هذه الطريقة أكثر كفاءة في استخدام الذاكرة من إبقاء جميع المكوّنات على جهاز التسريع، لكن متطلبات الذاكرة لا تزال مرتفعة إلى حد كبير. لكي تعمل هذه الطريقة، يجب توفر ذاكرة تعادل حجم النموذج في نوع البيانات وقت التشغيل + حجم أكبر توترات التنشيط الوسيطة، وذلك لإكمال مسار الأمامي.
- على مستوى الأوراق: في Diffusers، يمكن تفعيل ذلك باستخدام طريقة `ModelMixin::enable_sequential_cpu_offload()`. تعمل هذه الطريقة عن طريق نقل معاملات مستوى الأوراق الأدنى في رسم الحساب إلى وحدة المعالجة المركزية (CPU) للتخزين، ونقل الأوراق فقط إلى جهاز التسريع لأداء الحسابات. يستخدم هذا الأسلوب أقل قدر من ذاكرة التسريع، لكنه قد يكون أبطأ بسبب العدد المفرط من عمليات المزامنة بين الأجهزة.

يعتبر تفريغ المجموعات (Group offloading) حلًا وسطًا بين المنهجين المذكورين. يعمل هذا الأسلوب عن طريق تفريغ مجموعات من الطبقات الداخلية، (سواءً كانت `torch.nn.ModuleList` أو `torch.nn.Sequential`). يستخدم هذا الأسلوب ذاكرة أقل من تفريغ مستوى الوحدة (module-level offloading). كما أنه أسرع من تفريغ مستوى الورقة/التسلسلي (leaf-level/sequential offloading)، نظرًا لتقليل عدد مزامنات الأجهزة.

ميزة أخرى مدعومة (لأجهزة CUDA التي تدعم تدفقات نقل البيانات غير المتزامنة) هي القدرة على تداخل نقل البيانات والحساب لتقليل وقت التنفيذ الإجمالي مقارنةً بالتفريغ التسلسلي. يتم تمكين ذلك باستخدام الاستباق للطبقات مع التدفقات، أي أن الطبقة التي سيتم تنفيذها التالية تبدأ التحميل إلى جهاز المعالج التسارعي بينما يتم تنفيذ الطبقة الحالية - وهذا يزيد من متطلبات الذاكرة قليلاً. لاحظ أن هذا التنفيذ يدعم أيضًا التفريغ على مستوى الأوراق، لكنه يمكن أن يصبح أسرع بكثير عند استخدام التدفقات.

مثال:
```python
>>> from diffusers import CogVideoXTransformer3DModel
>>> from diffusers.hooks import apply_group_offloading

>>> transformer = CogVideoXTransformer3DModel.from_pretrained(
...     "THUDM/CogVideoX-5b", subfolder="transformer", torch_dtype=torch.bfloat16
... )

>>> apply_group_offloading(
...     transformer,
...     onload_device=torch.device("cuda"),
...     offload_device=torch.device("cpu"),
...     offload_type="block_level",
...     num_blocks_per_group=2,
...     use_stream=True,
... )
```

