# Сериализация

`huggingface_hub` предоставляет вспомогательные функции для сохранения и загрузки весов ML-моделей в стандартизированном формате. Эта часть библиотеки всё ещё находится в разработке и будет улучшена в будущих релизах. Цель — унифицировать способы сохранения и загрузки весов на Hub, чтобы устранить дублирование кода между библиотеками и установить согласованные соглашения.

## Формат файлов DDUF

DDUF — это формат файлов, разработанный для диффузионных моделей. Он позволяет сохранить всю информацию, необходимую для запуска модели, в одном файле. Эта работа вдохновлена форматом [GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md). Библиотека `huggingface_hub` предоставляет вспомогательные функции для сохранения и загрузки файлов DDUF, обеспечивая соблюдение требований к формату файла.

> [!WARNING]
> Это очень ранняя версия парсера. API и реализация могут измениться в ближайшем будущем.
>
> Парсер на данный момент выполняет очень мало проверок. Подробнее о формате файла можно узнать здесь: https://github.com/huggingface/huggingface.js/tree/main/packages/dduf.

### Как создать файл DDUF?

Ниже показано, как экспортировать папку, содержащую различные части диффузионной модели, с помощью [export_folder_as_dduf()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.export_folder_as_dduf):

```python
# Export a folder as a DDUF file
>>> from huggingface_hub import export_folder_as_dduf
>>> export_folder_as_dduf("FLUX.1-dev.dduf", folder_path="path/to/FLUX.1-dev")
```

Для большей гибкости можно использовать [export_entries_as_dduf()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.export_entries_as_dduf) и передать список файлов, которые нужно включить в итоговый файл DDUF:

```python
# Export specific files from the local disk.
>>> from huggingface_hub import export_entries_as_dduf
>>> export_entries_as_dduf(
...     dduf_path="stable-diffusion-v1-4-FP16.dduf",
...     entries=[ # List entries to add to the DDUF file (here, only FP16 weights)
...         ("model_index.json", "path/to/model_index.json"),
...         ("vae/config.json", "path/to/vae/config.json"),
...         ("vae/diffusion_pytorch_model.fp16.safetensors", "path/to/vae/diffusion_pytorch_model.fp16.safetensors"),
...         ("text_encoder/config.json", "path/to/text_encoder/config.json"),
...         ("text_encoder/model.fp16.safetensors", "path/to/text_encoder/model.fp16.safetensors"),
...         # ... add more entries here
...     ]
... )
```

Параметр `entries` также поддерживает передачу итерируемого объекта с путями или байтами. Это может оказаться полезным, если у вас уже загружена модель и вы хотите сериализовать её непосредственно в файл DDUF, а не сначала сериализовать каждый компонент на диск, а затем в файл DDUF. Ниже приведён пример сериализации `StableDiffusionPipeline` в формате DDUF:

```python
# Export state_dicts one by one from a loaded pipeline 
>>> from diffusers import DiffusionPipeline
>>> from typing import Generator, Tuple
>>> import safetensors.torch
>>> from huggingface_hub import export_entries_as_dduf
>>> pipe = DiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
... # ... do some work with the pipeline

>>> def as_entries(pipe: DiffusionPipeline) -> Generator[Tuple[str, bytes], None, None]:
...     # Build a generator that yields the entries to add to the DDUF file.
...     # The first element of the tuple is the filename in the DDUF archive (must use UNIX separator!). The second element is the content of the file.
...     # Entries will be evaluated lazily when the DDUF file is created (only 1 entry is loaded in memory at a time)
...     yield "vae/config.json", pipe.vae.to_json_string().encode()
...     yield "vae/diffusion_pytorch_model.safetensors", safetensors.torch.save(pipe.vae.state_dict())
...     yield "text_encoder/config.json", pipe.text_encoder.config.to_json_string().encode()
...     yield "text_encoder/model.safetensors", safetensors.torch.save(pipe.text_encoder.state_dict())
...     # ... add more entries here

>>> export_entries_as_dduf(dduf_path="stable-diffusion-v1-4.dduf", entries=as_entries(pipe))
```

**Примечание:** на практике `diffusers` предоставляет метод для прямой сериализации пайплайна в файл DDUF. Приведённый выше фрагмент кода приведён только в качестве примера.

### Как прочитать файл DDUF?

```python
>>> import json
>>> import safetensors.torch
>>> from huggingface_hub import read_dduf_file

# Read DDUF metadata
>>> dduf_entries = read_dduf_file("FLUX.1-dev.dduf")

# Returns a mapping filename <> DDUFEntry
>>> dduf_entries["model_index.json"]
DDUFEntry(filename='model_index.json', offset=66, length=587)

# Load model index as JSON
>>> json.loads(dduf_entries["model_index.json"].read_text())
{'_class_name': 'FluxPipeline', '_diffusers_version': '0.32.0.dev0', '_name_or_path': 'black-forest-labs/FLUX.1-dev', 'scheduler': ['diffusers', 'FlowMatchEulerDiscreteScheduler'], 'text_encoder': ['transformers', 'CLIPTextModel'], 'text_encoder_2': ['transformers', 'T5EncoderModel'], 'tokenizer': ['transformers', 'CLIPTokenizer'], 'tokenizer_2': ['transformers', 'T5TokenizerFast'], 'transformer': ['diffusers', 'FluxTransformer2DModel'], 'vae': ['diffusers', 'AutoencoderKL']}

# Load VAE weights using safetensors
>>> with dduf_entries["vae/diffusion_pytorch_model.safetensors"].as_mmap() as mm:
...     state_dict = safetensors.torch.load(mm)
```

### Вспомогательные функции[[huggingface_hub.export_entries_as_dduf]]

#### huggingface_hub.export_entries_as_dduf[[huggingface_hub.export_entries_as_dduf]]

```python
huggingface_hub.export_entries_as_dduf(dduf_path: str | os.PathLike, entries: Iterable)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L160)

**Параметры:**

dduf_path (`str` или `os.PathLike`) : Путь к файлу DDUF для записи.

entries (`Iterable[tuple[str, Union[str, Path, bytes]]]`) : Итерируемый объект записей для записи в файл DDUF. Каждая запись — это кортеж, содержащий имя файла и его содержимое. Имя файла должно быть путём к файлу в архиве DDUF. Содержимое может быть строкой или pathlib.Path, представляющим путь к файлу на локальном диске, либо непосредственно содержимое в виде байтов.

**Исключения:** `-`

- - -- `DDUFExportError`: если во время экспорта что-то пошло не так (например, некорректное имя записи, отсутствует 'model_index.json' и т. д.).

Создайте файл DDUF из итерируемого объекта с записями.

Это вспомогательная функция более низкого уровня, чем [export_folder_as_dduf()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.export_folder_as_dduf), которая предоставляет больше гибкости при сериализации данных. В частности, вам не нужно сохранять данные на диск перед их экспортом в файл DDUF.

Пример:
```python
# Export specific files from the local disk.
>>> from huggingface_hub import export_entries_as_dduf
>>> export_entries_as_dduf(
...     dduf_path="stable-diffusion-v1-4-FP16.dduf",
...     entries=[ # List entries to add to the DDUF file (here, only FP16 weights)
...         ("model_index.json", "path/to/model_index.json"),
...         ("vae/config.json", "path/to/vae/config.json"),
...         ("vae/diffusion_pytorch_model.fp16.safetensors", "path/to/vae/diffusion_pytorch_model.fp16.safetensors"),
...         ("text_encoder/config.json", "path/to/text_encoder/config.json"),
...         ("text_encoder/model.fp16.safetensors", "path/to/text_encoder/model.fp16.safetensors"),
...         # ... add more entries here
...     ]
... )
```

```python
# Export state_dicts one by one from a loaded pipeline
>>> from diffusers import DiffusionPipeline
>>> from typing import Generator, Tuple
>>> import safetensors.torch
>>> from huggingface_hub import export_entries_as_dduf
>>> pipe = DiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
... # ... do some work with the pipeline

>>> def as_entries(pipe: DiffusionPipeline) -> Generator[tuple[str, bytes], None, None]:
...     # Build a generator that yields the entries to add to the DDUF file.
...     # The first element of the tuple is the filename in the DDUF archive (must use UNIX separator!). The second element is the content of the file.
...     # Entries will be evaluated lazily when the DDUF file is created (only 1 entry is loaded in memory at a time)
...     yield "vae/config.json", pipe.vae.to_json_string().encode()
...     yield "vae/diffusion_pytorch_model.safetensors", safetensors.torch.save(pipe.vae.state_dict())
...     yield "text_encoder/config.json", pipe.text_encoder.config.to_json_string().encode()
...     yield "text_encoder/model.safetensors", safetensors.torch.save(pipe.text_encoder.state_dict())
...     # ... add more entries here

>>> export_entries_as_dduf(dduf_path="stable-diffusion-v1-4.dduf", entries=as_entries(pipe))
```

#### huggingface_hub.export_folder_as_dduf[[huggingface_hub.export_folder_as_dduf]]

```python
huggingface_hub.export_folder_as_dduf(dduf_path: str | os.PathLike, folder_path: str | os.PathLike)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L249)

**Параметры:**

dduf_path (`str` или `os.PathLike`) : Путь к файлу DDUF для записи.

folder_path (`str` или `os.PathLike`) : Путь к папке, содержащей диффузионную модель.

Экспортируйте папку в файл DDUF.

Aиспользует [export_entries_as_dduf()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.export_entries_as_dduf) под капотом.

Пример:
```python
>>> from huggingface_hub import export_folder_as_dduf
>>> export_folder_as_dduf(dduf_path="FLUX.1-dev.dduf", folder_path="path/to/FLUX.1-dev")
```

#### huggingface_hub.read_dduf_file[[huggingface_hub.read_dduf_file]]

```python
huggingface_hub.read_dduf_file(dduf_path: os.PathLike | str)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L91)

**Параметры:**

dduf_path (`str` или `os.PathLike`) : Путь к файлу DDUF для чтения.

**Возвращает:** `dict[str, DDUFEntry]`

Словарь [DDUFEntry](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.DDUFEntry), индексируемый по имени файла.

**Исключения:** `-`

- - -- `DDUFCorruptedFileError`: если файл DDUF повреждён (то есть не соответствует формату DDUF).

Читает файл DDUF и возвращает словарь записей.

Читается только метаданные, данные не загружаются в память.

Пример:
```python
>>> import json
>>> import safetensors.torch
>>> from huggingface_hub import read_dduf_file

# Read DDUF metadata
>>> dduf_entries = read_dduf_file("FLUX.1-dev.dduf")

# Returns a mapping filename <> DDUFEntry
>>> dduf_entries["model_index.json"]
DDUFEntry(filename='model_index.json', offset=66, length=587)

# Load model index as JSON
>>> json.loads(dduf_entries["model_index.json"].read_text())
{'_class_name': 'FluxPipeline', '_diffusers_version': '0.32.0.dev0', '_name_or_path': 'black-forest-labs/FLUX.1-dev', ...

# Load VAE weights using safetensors
>>> with dduf_entries["vae/diffusion_pytorch_model.safetensors"].as_mmap() as mm:
...     state_dict = safetensors.torch.load(mm)
```

#### huggingface_hub.DDUFEntry[[huggingface_hub.DDUFEntry]]

```python
huggingface_hub.DDUFEntry(filename: str, length: int, offset: int, dduf_path: Path)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L36)

**Параметры:**

filename (str) : имя файла в архиве DDUF.

offset (int) : Смещение файла в архиве DDUF.

length (int) : Длина файла в архиве DDUF.

dduf_path (str) : Путь к архиву DDUF (для внутреннего использования).

Объект, представляющий запись файла в файле DDUF.

См. [read_dduf_file()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.read_dduf_file) для получения информации о чтении файла DDUF.

#### as_mmap[[huggingface_hub.DDUFEntry.as_mmap]]

```python
as_mmap()
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L58)

Откройте файл как файл с отображением в памяти (memory-mapped file).

Полезно для загрузки safetensors непосредственно из файла.

Пример:
```py
>>> import safetensors.torch
>>> with entry.as_mmap() as mm:
...     tensors = safetensors.torch.load(mm)
```

#### read_text[[huggingface_hub.DDUFEntry.read_text]]

```python
read_text(encoding: str = 'utf-8')
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L75)

Прочитайте файл как текст.

Полезно для записей в форматах '.txt' и '.json'.

Пример:
```py
>>> import json
>>> index = json.loads(entry.read_text())
```

### Ошибки[[huggingface_hub.errors.DDUFError]]

#### huggingface_hub.errors.DDUFError[[huggingface_hub.errors.DDUFError]]

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L521)

Базовое исключение для ошибок, связанных с форматом DDUF.

#### huggingface_hub.errors.DDUFCorruptedFileError[[huggingface_hub.errors.DDUFCorruptedFileError]]

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L525)

Исключение, возникающее при повреждении файла DDUF.

#### huggingface_hub.errors.DDUFExportError[[huggingface_hub.errors.DDUFExportError]]

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L529)

Базовое исключение для ошибок при экспорте DDUF.

#### huggingface_hub.errors.DDUFInvalidEntryNameError[[huggingface_hub.errors.DDUFInvalidEntryNameError]]

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L533)

Исключение, возникающее при некорректном имени элемента.

## Сохранение тензоров

Основная вспомогательная функция модуля `serialization` принимает в качестве входного параметра torch `nn.Module` и сохраняет его на диск. Она обрабатывает логику сохранения общих тензоров (см. [описание safetensors](https://huggingface.co/docs/safetensors/torch_shared_tensors)), а также логику разбиения state dictionary на фрагменты, используя под капотом [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards). На данный момент поддерживается только фреймворк `torch`.

Если вы хотите сохранить словарь состояния (например, отображение между именами слоёв и связанными с ними тензорами), а не `nn.Module`, вы можете использовать [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.save_torch_state_dict), который предоставляет те же возможности. Это полезно, например, если вы хотите применить пользовательскую логику к словарю состояния перед его сохранением.

### save_torch_model[[huggingface_hub.save_torch_model]]

#### huggingface_hub.save_torch_model[[huggingface_hub.save_torch_model]]

```python
huggingface_hub.save_torch_model(model: torch.nn.Module, save_directory: str | pathlib.Path, filename_pattern: str | None = None, force_contiguous: bool = True, max_shard_size: int | str = '5GB', metadata: dict[str, str] | None = None, safe_serialization: bool = True, is_main_process: bool = True, shared_tensors_to_discard: list[str] | None = None)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L47)

**Параметры:**

model (`torch.nn.Module`) : модель, которую нужно сохранить на диске.

save_directory (`str` или `Path`) : каталог, в котором будет сохранена модель.

filename_pattern (`str`, *optional*) : Шаблон для генерации имен файлов, в которых будет сохранена модель. Шаблон должен быть строкой, которую можно форматировать с помощью `filename_pattern.format(suffix=...)`, и должен содержать ключевое слово `suffix`. По умолчанию используется `"model{suffix}.safetensors"` или `pytorch_model{suffix}.bin` в зависимости от параметра `safe_serialization`.

force_contiguous (`boolean`, *необязательный*) : Принудительно сохраняет state_dict в виде непрерывных тензоров. Это не влияет на корректность модели, но может потенциально изменить производительность, если расположение тензора было выбрано специально для этого. По умолчанию `True`.

max_shard_size (`int` или `str`, *необязательный*) : Максимальный размер каждого фрагмента в байтах. По умолчанию — 5 ГБ.

metadata (`dict[str, str]`, *необязательный*) : Дополнительная информация, сохраняемая вместе с моделью. Для каждого удалённого тензора будет добавлена некоторая метаданные. Эта информация не позволит восстановить всю разделяемую структуру, но может помочь в понимании происходящего.

safe_serialization (`bool`, *optional*) : Сохранять ли в формате safetensors, что является поведением по умолчанию. Если `False`, фрагменты сохраняются в формате pickle. Безопасная сериализация рекомендуется по соображениям безопасности. Сохранение в формате pickle устарело и будет удалено в будущей версии.

is_main_process (`bool`, *optional*) : Указывает, является ли процесс, вызывающий данный метод, основным. Полезно при распределённом обучении, например на TPU, когда необходимо вызывать эту функцию из всех процессов. В этом случае установите `is_main_process=True` только в основном процессе, чтобы избежать гонок. По умолчанию True.

shared_tensors_to_discard (`list[str]`, *необязательный*) : Список имён тензоров, которые следует исключить при сохранении общих тензоров. Если не указан и общие тензоры обнаружены, будет исключено первое имя в алфавитном порядке.

Сохраняет указанную модель torch на диск, обрабатывая проблемы с шардированием и общими тензорами.

См. также [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.save_torch_state_dict) для сохранения state dict с большей гибкостью.

Для получения дополнительной информации о шаринге тензоров ознакомьтесь с [этим руководством](https://huggingface.co/docs/safetensors/torch_shared_tensors).

Словарь состояния модели разбивается на фрагменты так, чтобы каждый фрагмент был меньше заданного размера. Фрагменты сохраняются в `save_directory` с указанным `filename_pattern`. Если модель слишком велика, чтобы поместиться в один фрагмент, в `save_directory` сохраняется файл индекса, указывающий, где хранится каждый тензор. Этот вспомогательный метод использует [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards) под капотом. Если `safe_serialization` равно `True`, фрагменты сохраняются в формате safetensors (по умолчанию). В противном случае фрагменты сохраняются в формате pickle.

Перед сохранением модели каталог `save_directory` очищается от всех предыдущих файлов шардов.

> [!WARNING]
> Если один из тензоров модели больше `max_shard_size`, он окажется в собственном шарде, размер которого превысит `max_shard_size`.

> [!WARNING]
> Если ваша модель является `transformers.PreTrainedModel`, вы должны передать `model._tied_weights_keys` в качестве `shared_tensors_to_discard`, чтобы корректно обрабатывать сохранение общих тензоров. Это гарантирует, что при сохранении будут отброшены именно те дублирующиеся тензоры, которые нужно.

Пример:

```py
>>> from huggingface_hub import save_torch_model
>>> model = ... # A PyTorch model

# Save state dict to "path/to/folder". The model will be split into shards of 5GB each and saved as safetensors.
>>> save_torch_model(model, "path/to/folder")

# Load model back
>>> from huggingface_hub import load_torch_model  # TODO
>>> load_torch_model(model, "path/to/folder")
>>>
```

### save_torch_state_dict[[huggingface_hub.save_torch_state_dict]]

#### huggingface_hub.save_torch_state_dict[[huggingface_hub.save_torch_state_dict]]

```python
huggingface_hub.save_torch_state_dict(state_dict: dict, save_directory: str | pathlib.Path, filename_pattern: str | None = None, force_contiguous: bool = True, max_shard_size: int | str = '5GB', metadata: dict[str, str] | None = None, safe_serialization: bool = True, is_main_process: bool = True, shared_tensors_to_discard: list[str] | None = None)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L141)

**Параметры:**

state_dict (`dict[str, torch.Tensor]`) : Словарь состояния для сохранения.

save_directory (`str` или `Path`) : каталог, в котором будет сохранена модель.

filename_pattern (`str`, *optional*) : Шаблон для генерации имен файлов, в которых будет сохранена модель. Шаблон должен быть строкой, которую можно форматировать с помощью `filename_pattern.format(suffix=...)`, и должен содержать ключевое слово `suffix`. По умолчанию используется `"model{suffix}.safetensors"` или `pytorch_model{suffix}.bin` в зависимости от параметра `safe_serialization`.

force_contiguous (`boolean`, *необязательный*) : Принудительно сохраняет state_dict в виде непрерывных тензоров. Это не влияет на корректность модели, но может потенциально изменить производительность, если расположение тензора было выбрано специально для этого. По умолчанию `True`.

max_shard_size (`int` или `str`, *необязательный*) : Максимальный размер каждого фрагмента в байтах. По умолчанию — 5 ГБ.

metadata (`dict[str, str]`, *необязательный*) : Дополнительная информация, сохраняемая вместе с моделью. Для каждого удалённого тензора будет добавлена некоторая метаданные. Эта информация не позволит восстановить всю разделяемую структуру, но может помочь в понимании происходящего.

safe_serialization (`bool`, *optional*) : Сохранять ли в формате safetensors, что является поведением по умолчанию. Если `False`, фрагменты сохраняются в формате pickle. Безопасная сериализация рекомендуется по соображениям безопасности. Сохранение в формате pickle устарело и будет удалено в будущей версии.

is_main_process (`bool`, *optional*) : Указывает, является ли процесс, вызывающий данный метод, основным. Полезно при распределённом обучении, например на TPU, когда необходимо вызывать эту функцию из всех процессов. В этом случае установите `is_main_process=True` только в основном процессе, чтобы избежать гонок. По умолчанию True.

shared_tensors_to_discard (`list[str]`, *необязательный*) : Список имён тензоров, которые следует исключить при сохранении общих тензоров. Если не указан и общие тензоры обнаружены, будет исключено первое имя в алфавитном порядке.

Сохранить словарь состояния модели на диск, обрабатывая проблемы с шардированием и общими тензорами.

См. также [save_torch_model()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.save_torch_model) для прямого сохранения модели PyTorch.

Для получения дополнительной информации о шаринге тензоров ознакомьтесь с [этим руководством](https://huggingface.co/docs/safetensors/torch_shared_tensors).

Словарь состояния модели разбивается на фрагменты так, чтобы каждый фрагмент был меньше заданного размера. Фрагменты сохраняются в `save_directory` с указанным `filename_pattern`. Если модель слишком велика, чтобы поместиться в один фрагмент, в `save_directory` сохраняется файл индекса, указывающий, где хранится каждый тензор. Этот вспомогательный метод использует [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards) под капотом. Если `safe_serialization` равно `True`, фрагменты сохраняются в формате safetensors (по умолчанию). В противном случае фрагменты сохраняются в формате pickle.

Перед сохранением модели каталог `save_directory` очищается от всех предыдущих файлов шардов.

> [!WARNING]
> Если один из тензоров модели больше `max_shard_size`, он окажется в собственном шарде, размер которого превысит `max_shard_size`.

> [!WARNING]
> Если ваша модель является `transformers.PreTrainedModel`, вы должны передать `model._tied_weights_keys` в качестве `shared_tensors_to_discard`, чтобы корректно обрабатывать сохранение общих тензоров. Это гарантирует, что при сохранении будут отброшены именно те дублирующиеся тензоры, которые нужно.

Пример:

```py
>>> from huggingface_hub import save_torch_state_dict
>>> model = ... # A PyTorch model

# Save state dict to "path/to/folder". The model will be split into shards of 5GB each and saved as safetensors.
>>> state_dict = model_to_save.state_dict()
>>> save_torch_state_dict(state_dict, "path/to/folder")
```

Модуль `serialization` также содержит низкоуровневые вспомогательные функции для разделения словаря состояния на несколько фрагментов с одновременным созданием соответствующего индекса. Эти функции доступны для тензоров `torch` и разработаны так, чтобы их можно было легко расширить для любых других ML-фреймворков.

### split_torch_state_dict_into_shards[[huggingface_hub.split_torch_state_dict_into_shards]]

#### huggingface_hub.split_torch_state_dict_into_shards[[huggingface_hub.split_torch_state_dict_into_shards]]

```python
huggingface_hub.split_torch_state_dict_into_shards(state_dict: dict, filename_pattern: str = 'model{suffix}.safetensors', max_shard_size: int | str = '5GB')
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L302)

**Параметры:**

state_dict (`dict[str, torch.Tensor]`) : Словарь состояния для сохранения.

filename_pattern (`str`, *необязательный*) : шаблон для генерации имен файлов, в которых будет сохранена модель. Шаблон должен быть строкой, которую можно форматировать с помощью `filename_pattern.format(suffix=...)`, и должен содержать ключевое слово `suffix`. По умолчанию `"model{suffix}.safetensors"`.

max_shard_size (`int` или `str`, *необязательный*) : Максимальный размер каждого фрагмента в байтах. По умолчанию — 5 ГБ.

**Возвращает:** `StateDictSplit`

Объект `StateDictSplit`, содержащий фрагменты и индекс для их получения.

Разделите словарь состояния модели на фрагменты так, чтобы каждый фрагмент был меньше заданного размера.

Шарды определяются путём итерации по `state_dict` в порядке его ключей. Никакая оптимизация для того, чтобы каждый шард был как можно ближе к максимальному размеру, не выполняется. Например, если лимит составляет 10 ГБ, а размеры тензоров равны [6 ГБ, 6 ГБ, 2 ГБ, 6 ГБ, 2 ГБ, 2 ГБ], они будут разбиты на [6 ГБ], [6+2 ГБ], [6+2+2 ГБ], а не на [6+2+2 ГБ], [6+2 ГБ], [6 ГБ].

> [!TIP]
> Чтобы сохранить словарь состояния модели на диск, см. [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.save_torch_state_dict). Этот вспомогательный метод использует `split_torch_state_dict_into_shards` под капотом.

> [!WARNING]
> Если один из тензоров модели больше `max_shard_size`, он окажется в собственном шарде, размер которого превысит `max_shard_size`.

Пример:
```py
>>> import json
>>> import os
>>> from safetensors.torch import save_file as safe_save_file
>>> from huggingface_hub import split_torch_state_dict_into_shards

>>> def save_state_dict(state_dict: dict[str, torch.Tensor], save_directory: str):
...     state_dict_split = split_torch_state_dict_into_shards(state_dict)
...     for filename, tensors in state_dict_split.filename_to_tensors.items():
...         shard = {tensor: state_dict[tensor] for tensor in tensors}
...         safe_save_file(
...             shard,
...             os.path.join(save_directory, filename),
...             metadata={"format": "pt"},
...         )
...     if state_dict_split.is_sharded:
...         index = {
...             "metadata": state_dict_split.metadata,
...             "weight_map": state_dict_split.tensor_to_filename,
...         }
...         with open(os.path.join(save_directory, "model.safetensors.index.json"), "w") as f:
...             f.write(json.dumps(index, indent=2))
```

### split_state_dict_into_shards_factory[[huggingface_hub.split_state_dict_into_shards_factory]]

Это базовый фабрика, из которой производятся все специфичные для фреймворков помощники. На практике вы не должны использовать эту фабрику напрямую, за исключением случаев, когда вам необходимо адаптировать её под фреймворк, который пока не поддерживается. Если это ваш случай, пожалуйста, сообщите нам, [создав новую issue](https://github.com/huggingface/huggingface_hub/issues/new) в репозитории `huggingface_hub`.

#### huggingface_hub.split_state_dict_into_shards_factory[[huggingface_hub.split_state_dict_into_shards_factory]]

```python
huggingface_hub.split_state_dict_into_shards_factory(state_dict: dict, get_storage_size: Callable, filename_pattern: str, get_storage_id: Callable = <function <lambda> at 0x7f9673968670>, max_shard_size: int | str = '5GB')
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_base.py#L50)

**Параметры:**

state_dict (`dict[str, Tensor]`) : Словарь состояния для сохранения.

get_storage_size (`Callable[[Tensor], int]`) : функция, возвращающая размер тензора в байтах при сохранении на диск.

get_storage_id (`Callable[[Tensor], Optional[Any]]`, *optional*) : функция, возвращающая уникальный идентификатор хранилища тензора. Несколько различных тензоров могут использовать одно и то же базовое хранилище. Этот идентификатор гарантированно уникален и неизменен для хранилища данного тензора в течение всего времени его существования. Два хранилища тензоров с непересекающимися временами жизни могут иметь одинаковый id.

filename_pattern (`str`, *необязательный*) : шаблон для генерации имён файлов, в которых будет сохранена модель. Шаблон должен быть строкой, которую можно форматировать с помощью `filename_pattern.format(suffix=...)`, и должен содержать ключевое слово `suffix`

max_shard_size (`int` или `str`, *необязательный*) : Максимальный размер каждого фрагмента в байтах. По умолчанию — 5 ГБ.

**Возвращает:** `StateDictSplit`

Объект `StateDictSplit`, содержащий фрагменты и индекс для их получения.

Разделите словарь состояния модели на фрагменты так, чтобы каждый фрагмент был меньше заданного размера.

Шарды определяются путём итерации по `state_dict` в порядке его ключей. Никакая оптимизация для того, чтобы каждый шард был как можно ближе к максимальному размеру, не выполняется. Например, если лимит составляет 10 ГБ, а размеры тензоров равны [6 ГБ, 6 ГБ, 2 ГБ, 6 ГБ, 2 ГБ, 2 ГБ], они будут разбиты на [6 ГБ], [6+2 ГБ], [6+2+2 ГБ], а не на [6+2+2 ГБ], [6+2 ГБ], [6 ГБ].

> [!WARNING]
> Если один из тензоров модели больше `max_shard_size`, он окажется в собственном шарде, размер которого превысит `max_shard_size`.

## Загрузка тензоров

Вспомогательные функции загрузки поддерживают как одиночные, так и разбитые на части контрольные точки в формате safetensors или pickle. [load_torch_model()](/docs/huggingface_hub/v2.4.0/ru/package_reference/serialization#huggingface_hub.load_torch_model) принимает на вход `nn.Module` и путь к контрольной точке (файл или каталог) и загружает веса в модель.

> [!WARNING]
> Оба хелпера по умолчанию используют `safe=True`, что означает, что чекпоинт всегда десериализуется с помощью загрузчика safetensors — независимо от имени файла. Загрузка чекпоинта в формате pickle требует явного включения, так как распаковка pickle выполняет произвольный код во время загрузки:
> ```py
> >>> from huggingface_hub import load_state_dict_from_file, load_torch_model
>
> # Raises: the file is not safetensors
> >>> load_state_dict_from_file("path/to/pytorch_model.bin")
> >>> load_torch_model(model, "path/to/pytorch_model.bin")
>
> # Explicit opt-in
> >>> load_state_dict_from_file("path/to/pytorch_model.bin", safe=False)
> >>> load_torch_model(model, "path/to/pytorch_model.bin", safe=False)
> ```
> Путь pickle дополнительно по умолчанию использует `weights_only=True`, то есть ограниченный распаковщик torch. Для контрольной точки, содержащей объекты, не являющиеся тензорами (состояния оптимизатора, целая модель, ...), помимо `safe=False` требуется `weights_only=False`.

### load_torch_model[[huggingface_hub.load_torch_model]]

#### huggingface_hub.load_torch_model[[huggingface_hub.load_torch_model]]

```python
huggingface_hub.load_torch_model(model: torch.nn.Module, checkpoint_path: str | os.PathLike, strict: bool = False, safe: bool = True, weights_only: bool = True, map_location: typing.Union[str, ForwardRef('torch.device'), NoneType] = None, mmap: bool = False, filename_pattern: str | None = None)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L375)

**Параметры:**

model (`torch.nn.Module`) : модель, в которую нужно загрузить контрольную точку.

checkpoint_path (`str` или `os.PathLike`) : Путь к файлу контрольной точки или каталогу, содержащему контрольные точки.

strict (`bool`, *необязательный*, по умолчанию `False`) : Указывает, следует ли строго требовать, чтобы ключи в state dict модели совпадали с ключами в контрольной точке. Как и в случае с `torch.nn.Module.load_state_dict`, проверка выполняется после загрузки контрольной точки, поэтому при возникновении ошибки модель могла быть частично обновлена.

safe (`bool`, *необязательный*, по умолчанию `True`) : Если `safe` равно True, файлы safetensors будут загружены. Если `safe` равно False, функция сначала попытается загрузить файлы safetensors, если они доступны, в противном случае будет использована загрузка файлов pickle. `filename_pattern`, не описывающий файлы safetensors, отклоняется, когда `safe=True`.

weights_only (`bool`, *необязательный*, по умолчанию `True`) : Если True, загружаются только веса модели без состояний оптимизатора и других метаданных, с использованием ограниченного unpickler'а torch. Установите False, чтобы разрешить произвольные объекты Python в pickle-чекпоинте (это приводит к выполнению произвольного кода при загрузке). Не влияет на PyTorch < 1.13, в котором нет ограниченного unpickler'а и распаковка всегда выполняется без ограничений.

map_location (`str` или `torch.device`, *необязательный*) : объект `torch.device`, строка или словарь, задающий способ переназначения мест хранения. Указывает расположение, в которое следует загрузить все тензоры.

mmap (`bool`, *необязательный*, по умолчанию `False`) : Использовать ли загрузку файлов с отображением в память (memory-mapped). Отображение в память может повысить производительность загрузки для больших моделей в PyTorch >= 2.1.0 с контрольными точками на основе zipfile.

filename_pattern (`str`, *необязательный*) : Шаблон для поиска файла индекса. Шаблон должен быть строкой, которую можно форматировать с помощью `filename_pattern.format(suffix=...)`, и должен содержать ключевое слово `suffix`. По умолчанию `"model{suffix}.safetensors"`.

**Возвращает:** `NamedTuple`

Именованный кортеж с полями `missing_keys` и `unexpected_keys`.
- `missing_keys` — это список str, содержащий отсутствующие ключи, то есть ключи, которые есть в модели, но отсутствуют в контрольной точке.
- `unexpected_keys` — это список str, содержащий неожиданные ключи, то есть ключи, которые присутствуют в контрольной точке, но отсутствуют в модели.

**Исключения:** ``FileNotFoundError`` или ``ImportError`` или ``ValueError``

- [`FileNotFoundError`](https://docs.python.org/3/library/exceptions.html#FileNotFoundError) -- если файл или каталог контрольной точки не существует.
- [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) -- возникает, если при попытке загрузить файл .safetensors или чекпоинт PyTorch не установлены safetensors или torch соответственно.
- [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) -- если формат контрольной точки не может быть определён.

Загрузите контрольную точку в модель, обрабатывая как разбитые, так и неразбитые контрольные точки.

Пример:
```python
>>> from huggingface_hub import load_torch_model
>>> model = ... # A PyTorch model
>>> load_torch_model(model, "path/to/checkpoint")
```

### load_state_dict_from_file[[huggingface_hub.load_state_dict_from_file]]

#### huggingface_hub.load_state_dict_from_file[[huggingface_hub.load_state_dict_from_file]]

```python
huggingface_hub.load_state_dict_from_file(checkpoint_file: str | os.PathLike, map_location: typing.Union[str, ForwardRef('torch.device'), NoneType] = None, weights_only: bool = True, mmap: bool = False, safe: bool = True)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L633)

**Параметры:**

checkpoint_file (`str` или `os.PathLike`) : Путь к файлу контрольной точки для загрузки. Может быть контрольной точкой в формате safetensors или pickle (`.bin`).

map_location (`str` или `torch.device`, *необязательный*) : объект `torch.device`, строка или словарь, задающий способ переназначения мест хранения. Указывает расположение, в которое следует загрузить все тензоры.

weights_only (`bool`, *необязательный*, по умолчанию `True`) : Если True, загружаются только веса модели без состояний оптимизатора и других метаданных, с использованием ограниченного unpickler'а torch. Установите False, чтобы разрешить произвольные объекты Python в pickle-чекпоинте (это приводит к выполнению произвольного кода при загрузке). Не влияет при загрузке файлов safetensors, а также на PyTorch < 1.13, в котором нет ограниченного unpickler'а — эти версии всегда выполняют unpickle без ограничений, при этом в журнал выводится предупреждение.

mmap (`bool`, *необязательный*, по умолчанию `False`) : Использовать ли загрузку файлов через отображение в память (memory-mapped). Отображение в память может повысить производительность загрузки для больших моделей в PyTorch >= 2.1.0 с контрольными точками на основе zipfile. Не влияет на загрузку файлов safetensors, так как библиотека `safetensors` использует отображение в память по умолчанию.

safe (`bool`, *необязательный*, по умолчанию `True`) : Если True, контрольная точка всегда загружается как safetensors, независимо от её имени. Любой другой формат (например, pickle-файл `.bin`) вызывает `ValueError` вместо десериализации: pickle-контрольные точки могут выполнять произвольный код при загрузке. Если False, файл загружается как safetensors, если это указано в его имени, иначе — с помощью `torch.load`.

**Возвращает:** `Union[dict[str, "torch.Tensor"], Any]`

Загруженная контрольная точка.
- Для файлов safetensors: всегда возвращает словарь, сопоставляющий имена параметров с тензорами.
- Для файлов pickle: возвращает любой объект Python, который был сериализован (обычно это state dict, но это может быть и вся модель, состояние оптимизатора, или любой другой объект Python).

**Исключения:** ``FileNotFoundError`` или ``ImportError`` или ``OSError`` или ``ValueError``

- [`FileNotFoundError`](https://docs.python.org/3/library/exceptions.html#FileNotFoundError) -- если файл контрольной точки не существует.
- [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) -- возникает, если при попытке загрузить файл .safetensors или чекпоинт PyTorch не установлены safetensors или torch соответственно.
- [`OSError`](https://docs.python.org/3/library/exceptions.html#OSError) -- если формат файла контрольной точки недействителен или файлы git-lfs не были корректно загружены.
- [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) -- Если путь к файлу контрольной точки пуст или недействителен, либо если его невозможно десериализовать как safetensors при `safe=True` (передайте `safe=False`, чтобы разрешить контрольные точки в формате pickle).

Загружает файл контрольной точки, поддерживая форматы safetensors и pickle.

Пример:
```python
>>> from huggingface_hub import load_state_dict_from_file

# Load a safetensors checkpoint (safe by default)
>>> state_dict = load_state_dict_from_file("path/to/model.safetensors", safe=True)
>>> model.load_state_dict(state_dict)

# Load a pickle checkpoint. `safe=False` is required: pickle files can execute arbitrary code.
>>> state_dict = load_state_dict_from_file("path/to/model.bin", safe=False, map_location="cpu")
>>> model.load_state_dict(state_dict)
```

## Вспомогательные функции для тензоров

### get_torch_storage_id[[huggingface_hub.get_torch_storage_id]]

#### huggingface_hub.get_torch_storage_id[[huggingface_hub.get_torch_storage_id]]

```python
huggingface_hub.get_torch_storage_id(tensor: torch.Tensor)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L878)

Возвращает уникальный идентификатор хранилища тензора.

Несколько различных тензоров могут использовать одно и то же базовое хранилище. Этот идентификатор гарантированно уникален и неизменен для хранилища данного тензора на протяжении всего его жизненного цикла. Два хранилища тензоров с непересекающимися жизненными циклами могут иметь одинаковый id. В случае мета-тензоров мы возвращаем None, поскольку невозможно определить, разделяют ли они одно и то же хранилище.

Взято из https://github.com/huggingface/transformers/blob/1ecf5f7c982d761b4daaa96719d162c324187c64/src/transformers/pytorch_utils.py#L278.

### get_torch_storage_size[[huggingface_hub.get_torch_storage_size]]

#### huggingface_hub.get_torch_storage_size[[huggingface_hub.get_torch_storage_size]]

```python
huggingface_hub.get_torch_storage_size(tensor: torch.Tensor)
```

[Источник](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L895)

Взято из https://github.com/huggingface/safetensors/blob/08db34094e9e59e2f9218f2df133b7b4aaff5a99/bindings/python/py_src/safetensors/torch.py#L31C1-L41C59

