# Sérialisation

`huggingface_hub` fournit des utilitaires pour enregistrer et charger les poids des modèles ML de manière standardisée. Cette partie de la bibliothèque est encore en cours de développement et sera améliorée dans les prochaines versions. L’objectif est d’harmoniser la façon dont les poids sont enregistrés et chargés sur le Hub, afin d’éliminer la duplication de code entre les bibliothèques et d’établir des conventions cohérentes.

## Format de fichier DDUF

DDUF est un format de fichier conçu pour les modèles de diffusion. Il permet d'enregistrer toutes les informations nécessaires à l'exécution d'un modèle dans un seul fichier. Ce travail s'inspire du format [GGUF](https://github.com/ggerganov/ggml/blob/master/docs/gguf.md). `huggingface_hub` fournit des utilitaires pour enregistrer et charger les fichiers DDUF, garantissant le respect du format de fichier.

> [!WARNING]
> Il s'agit d'une version très préliminaire de l'analyseur. L'API et l'implémentation peuvent évoluer à court terme.
>
> Le parseur effectue actuellement très peu de validation. Pour plus de détails sur le format de fichier, consultez https://github.com/huggingface/huggingface.js/tree/main/packages/dduf.

### Comment écrire un fichier DDUF ?

Voici comment exporter un dossier contenant différentes parties d'un modèle de diffusion à l'aide de [export_folder_as_dduf()](/docs/huggingface_hub/v2.4.0/fr/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")
```

Pour plus de flexibilité, vous pouvez utiliser [export_entries_as_dduf()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.export_entries_as_dduf) et passer une liste de fichiers à inclure dans le fichier DDUF final :

```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
...     ]
... )
```

Le paramètre `entries` prend également en charge le passage d'un itérable de chemins ou d'octets. Cela peut s'avérer utile si vous avez un modèle chargé et souhaitez le sérialiser directement dans un fichier DDUF, plutôt que de devoir d'abord sérialiser chaque composant sur le disque puis de le convertir en fichier DDUF. Voici un exemple de la manière dont un `StableDiffusionPipeline` peut être sérialisé au format 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))
```

**Remarque :** en pratique, `diffusers` fournit une méthode pour sérialiser directement un pipeline dans un fichier DDUF. L'extrait ci-dessus n'est fourni qu'à titre d'exemple.

### Comment lire un fichier 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)
```

### Aides[[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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L160)

**Paramètres :**

dduf_path (`str` ou `os.PathLike`) : Le chemin du fichier DDUF à écrire.

entries (`Iterable[tuple[str, Union[str, Path, bytes]]]`) : Un itérable d'entrées à écrire dans le fichier DDUF. Chaque entrée est un tuple contenant le nom du fichier et son contenu. Le nom du fichier doit être le chemin du fichier dans l'archive DDUF. Le contenu peut être une chaîne de caractères ou un pathlib.Path représentant un chemin vers un fichier sur le disque local, ou directement le contenu sous forme d'octets.

**Levée :** `-`

- - -- `DDUFExportError` : Si une erreur survient pendant l'exportation (par exemple, nom d'entrée invalide, absence de 'model_index.json', etc.).

Écrire un fichier DDUF à partir d'un itérable d'entrées.

Il s'agit d'un utilitaire de bas niveau par rapport à [export_folder_as_dduf()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.export_folder_as_dduf), offrant une plus grande flexibilité lors de la sérialisation des données. En particulier, vous n'avez pas besoin d'enregistrer les données sur le disque avant de les exporter dans le fichier DDUF.

Exemple :
```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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L249)

**Paramètres :**

dduf_path (`str` ou `os.PathLike`) : Le chemin du fichier DDUF à écrire.

folder_path (`str` ou `os.PathLike`) : Le chemin vers le dossier contenant le modèle de diffusion.

Exporter un dossier en tant que fichier DDUF.

AUtilise [export_entries_as_dduf()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.export_entries_as_dduf) en interne.

Exemple :
```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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L91)

**Paramètres :**

dduf_path (`str` ou `os.PathLike`) : Le chemin vers le fichier DDUF à lire.

**Retourne :** `dict[str, DDUFEntry]`

Un dictionnaire de [DDUFEntry](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.DDUFEntry) indexé par nom de fichier.

**Levée :** `-`

- - -- `DDUFCorruptedFileError` : si le fichier DDUF est corrompu (c'est-à-dire s'il ne respecte pas le format DDUF).

Lis un fichier DDUF et renvoie un dictionnaire d'entrées.

Seules les métadonnées sont lues, les données ne sont pas chargées en mémoire.

Exemple :
```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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L36)

**Paramètres :**

filename (str) : Le nom du fichier dans l'archive DDUF.

offset (int) : Le décalage du fichier dans l'archive DDUF.

length (int) : La longueur du fichier dans l'archive DDUF.

dduf_path (str) : Le chemin vers l'archive DDUF (pour usage interne).

Objet représentant une entrée de fichier dans un fichier DDUF.

Voir [read_dduf_file()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.read_dduf_file) pour savoir comment lire un fichier DDUF.

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

```python
as_mmap()
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L58)

Ouvrez le fichier en tant que fichier mappé en mémoire.

Utile pour charger les safetensors directement depuis le fichier.

Exemple :
```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')
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_dduf.py#L75)

Lisez le fichier en tant que texte.

Utile pour les entrées '.txt' et '.json'.

Exemple :
```py
>>> import json
>>> index = json.loads(entry.read_text())
```

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

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

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L521)

Exception de base pour les erreurs liées au format DDUF.

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

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L525)

Exception levée lorsque le fichier DDUF est corrompu.

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

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L529)

Exception de base pour les erreurs survenant lors de l'exportation DDUF.

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

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/errors.py#L533)

Exception levée lorsque le nom de l'entrée est invalide.

## Enregistrer des tenseurs

Le principal utilitaire du module `serialization` prend en entrée un `nn.Module` de torch et l'enregistre sur le disque. Il gère la logique d'enregistrement des tenseurs partagés (voir [explication de safetensors](https://huggingface.co/docs/safetensors/torch_shared_tensors)) ainsi que la logique de division du dictionnaire d'état en fragments, en utilisant [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards) en interne. Pour le moment, seul le framework `torch` est pris en charge.

Si vous souhaitez enregistrer un dictionnaire d'état (par exemple, une correspondance entre les noms de couches et les tenseurs associés) plutôt qu'un `nn.Module`, vous pouvez utiliser [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.save_torch_state_dict) qui offre les mêmes fonctionnalités. Cela est utile, par exemple, si vous voulez appliquer une logique personnalisée au dictionnaire d'état avant de l'enregistrer.

### 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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L47)

**Paramètres :**

model (`torch.nn.Module`) : Le modèle à enregistrer sur le disque.

save_directory (`str` ou `Path`) : Le répertoire dans lequel le modèle sera enregistré.

filename_pattern (`str`, *facultatif*) : Le motif à utiliser pour générer les noms des fichiers dans lesquels le modèle sera enregistré. Le motif doit être une chaîne de caractères qui peut être formatée avec `filename_pattern.format(suffix=...)` et doit contenir le mot-clé `suffix`. Par défaut, il s'agit de `"model{suffix}.safetensors"` ou de `pytorch_model{suffix}.bin` en fonction du paramètre `safe_serialization`.

force_contiguous (`boolean`, *facultatif*) : Force la sauvegarde du state_dict sous forme de tenseurs contigus. Cela n'a aucun effet sur la justesse du modèle, mais cela pourrait potentiellement modifier les performances si la disposition du tenseur avait été choisie spécifiquement pour cette raison. La valeur par défaut est `True`.

max_shard_size (`int` ou `str`, *facultatif*) : La taille maximale de chaque fragment, en octets. La valeur par défaut est de 5 Go.

metadata (`dict[str, str]`, *facultatif*) : Informations supplémentaires à enregistrer avec le modèle. Certaines métadonnées seront ajoutées pour chaque tenseur supprimé. Ces informations ne suffiront pas à récupérer l'ensemble de la structure partagée, mais peuvent aider à la comprendre.

safe_serialization (`bool`, *facultatif*) : Indique s'il faut enregistrer au format safetensors, ce qui est le comportement par défaut. Si `False`, les fragments sont enregistrés au format pickle. La sérialisation sécurisée est recommandée pour des raisons de sécurité. L'enregistrement au format pickle est obsolète et sera supprimé dans une version future.

is_main_process (`bool`, *facultatif*) : Indique si le processus qui appelle cette fonction est le processus principal ou non. Utile lors d'une formation distribuée, comme sur des TPU, où il est nécessaire d'appeler cette fonction depuis tous les processus. Dans ce cas, définissez `is_main_process=True` uniquement sur le processus principal pour éviter les conditions de course. La valeur par défaut est True.

shared_tensors_to_discard (`list[str]`, *facultatif*) : Liste des noms de tenseurs à supprimer lors de l’enregistrement des tenseurs partagés. S’il n’est pas fourni et que des tenseurs partagés sont détectés, le premier nom en ordre alphabétique sera supprimé.

Enregistre un modèle torch donné sur le disque, en gérant les problèmes de fragmentation et de tenseurs partagés.

Voir aussi [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.save_torch_state_dict) pour enregistrer un state dict avec plus de flexibilité.

Pour plus d'informations sur le partage de tenseurs, consultez [ce guide](https://huggingface.co/docs/safetensors/torch_shared_tensors).

Le dictionnaire d'état du modèle est découpé en fragments afin que chaque fragment soit inférieur à une taille donnée. Les fragments sont enregistrés dans le `save_directory` avec le `filename_pattern` indiqué. Si le modèle est trop volumineux pour tenir dans un seul fragment, un fichier d'index est enregistré dans le `save_directory` pour indiquer l'emplacement de chaque tenseur. Cet utilitaire utilise [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards) en interne. Si `safe_serialization` est `True`, les fragments sont enregistrés au format safetensors (par défaut). Sinon, les fragments sont enregistrés au format pickle.

Avant d'enregistrer le modèle, le `save_directory` est nettoyé de tout fichier de shard précédent.

> [!WARNING]
> Si l'un des tenseurs du modèle est plus grand que `max_shard_size`, il finira dans son propre shard dont la taille sera supérieure à `max_shard_size`.

> [!WARNING]
> Si votre modèle est un `transformers.PreTrainedModel`, vous devez passer `model._tied_weights_keys` en tant que `shared_tensors_to_discard` pour gérer correctement l'enregistrement des tenseurs partagés. Cela garantit que les tenseurs en double appropriés sont écartés lors de l'enregistrement.

Exemple :

```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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L141)

**Paramètres :**

state_dict (`dict[str, torch.Tensor]`) : Le dictionnaire d'état à enregistrer.

save_directory (`str` ou `Path`) : Le répertoire dans lequel le modèle sera enregistré.

filename_pattern (`str`, *facultatif*) : Le motif à utiliser pour générer les noms des fichiers dans lesquels le modèle sera enregistré. Le motif doit être une chaîne de caractères qui peut être formatée avec `filename_pattern.format(suffix=...)` et doit contenir le mot-clé `suffix`. Par défaut, il s'agit de `"model{suffix}.safetensors"` ou de `pytorch_model{suffix}.bin` en fonction du paramètre `safe_serialization`.

force_contiguous (`boolean`, *facultatif*) : Force la sauvegarde du state_dict sous forme de tenseurs contigus. Cela n'a aucun effet sur la justesse du modèle, mais cela pourrait potentiellement modifier les performances si la disposition du tenseur avait été choisie spécifiquement pour cette raison. La valeur par défaut est `True`.

max_shard_size (`int` ou `str`, *facultatif*) : La taille maximale de chaque fragment, en octets. La valeur par défaut est de 5 Go.

metadata (`dict[str, str]`, *facultatif*) : Informations supplémentaires à enregistrer avec le modèle. Certaines métadonnées seront ajoutées pour chaque tenseur supprimé. Ces informations ne suffiront pas à récupérer l'ensemble de la structure partagée, mais peuvent aider à la comprendre.

safe_serialization (`bool`, *facultatif*) : Indique s'il faut enregistrer au format safetensors, ce qui est le comportement par défaut. Si `False`, les fragments sont enregistrés au format pickle. La sérialisation sécurisée est recommandée pour des raisons de sécurité. L'enregistrement au format pickle est obsolète et sera supprimé dans une version future.

is_main_process (`bool`, *facultatif*) : Indique si le processus qui appelle cette fonction est le processus principal ou non. Utile lors d'une formation distribuée, comme sur des TPU, où il est nécessaire d'appeler cette fonction depuis tous les processus. Dans ce cas, définissez `is_main_process=True` uniquement sur le processus principal pour éviter les conditions de course. La valeur par défaut est True.

shared_tensors_to_discard (`list[str]`, *facultatif*) : Liste des noms de tenseurs à supprimer lors de l’enregistrement des tenseurs partagés. S’il n’est pas fourni et que des tenseurs partagés sont détectés, le premier nom en ordre alphabétique sera supprimé.

Enregistrer un dictionnaire d'état de modèle sur le disque, en gérant les problèmes de fragmentation et de tenseurs partagés.

Voir aussi [save_torch_model()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.save_torch_model) pour enregistrer directement un modèle PyTorch.

Pour plus d'informations sur le partage de tenseurs, consultez [ce guide](https://huggingface.co/docs/safetensors/torch_shared_tensors).

Le dictionnaire d'état du modèle est découpé en fragments afin que chaque fragment soit inférieur à une taille donnée. Les fragments sont enregistrés dans le `save_directory` avec le `filename_pattern` indiqué. Si le modèle est trop volumineux pour tenir dans un seul fragment, un fichier d'index est enregistré dans le `save_directory` pour indiquer l'emplacement de chaque tenseur. Cet utilitaire utilise [split_torch_state_dict_into_shards()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.split_torch_state_dict_into_shards) en interne. Si `safe_serialization` est `True`, les fragments sont enregistrés au format safetensors (par défaut). Sinon, les fragments sont enregistrés au format pickle.

Avant d'enregistrer le modèle, le `save_directory` est nettoyé de tout fichier de shard précédent.

> [!WARNING]
> Si l'un des tenseurs du modèle est plus grand que `max_shard_size`, il finira dans son propre shard dont la taille sera supérieure à `max_shard_size`.

> [!WARNING]
> Si votre modèle est un `transformers.PreTrainedModel`, vous devez passer `model._tied_weights_keys` en tant que `shared_tensors_to_discard` pour gérer correctement l'enregistrement des tenseurs partagés. Cela garantit que les tenseurs en double appropriés sont écartés lors de l'enregistrement.

Exemple :

```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")
```

Le module `serialization` contient également des utilitaires de bas niveau pour diviser un dictionnaire d'état en plusieurs fragments, tout en créant un index approprié au passage. Ces utilitaires sont disponibles pour les tenseurs `torch` et sont conçus pour être facilement étendus à tout autre framework de 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')
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L302)

**Paramètres :**

state_dict (`dict[str, torch.Tensor]`) : Le dictionnaire d'état à enregistrer.

filename_pattern (`str`, *facultatif*) : Le motif pour générer les noms des fichiers dans lesquels le modèle sera enregistré. Le motif doit être une chaîne de caractères qui peut être formatée avec `filename_pattern.format(suffix=...)` et doit contenir le mot-clé `suffix`. Par défaut, `"model{suffix}.safetensors"`.

max_shard_size (`int` ou `str`, *facultatif*) : La taille maximale de chaque fragment, en octets. La valeur par défaut est de 5 Go.

**Retourne :** `StateDictSplit`

Un objet `StateDictSplit` contenant les shards et l'index pour les récupérer.

Diviser le dictionnaire d'état d'un modèle en fragments afin que chaque fragment soit inférieur à une taille donnée.

Les shards sont déterminés en parcourant le `state_dict` dans l'ordre de ses clés. Aucune optimisation n'est effectuée pour que chaque shard soit aussi proche que possible de la taille maximale passée. Par exemple, si la limite est de 10 Go et que nous avons des tenseurs de tailles [6 Go, 6 Go, 2 Go, 6 Go, 2 Go, 2 Go], ils seront shardés en [6 Go], [6+2 Go], [6+2+2 Go] et non en [6+2+2 Go], [6+2 Go], [6 Go].

> [!TIP]
> Pour enregistrer un dictionnaire d'état de modèle sur le disque, consultez [save_torch_state_dict()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.save_torch_state_dict). Cet utilitaire utilise `split_torch_state_dict_into_shards` en interne.

> [!WARNING]
> Si l'un des tenseurs du modèle est plus grand que `max_shard_size`, il finira dans son propre shard dont la taille sera supérieure à `max_shard_size`.

Exemple :
```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]]

C'est la fabrique sous-jacente à partir de laquelle chaque assistant spécifique à un framework est dérivé. En pratique, vous n'êtes pas censé utiliser directement cette fabrique, sauf si vous devez l'adapter à un framework non encore pris en charge. Si c'est le cas, merci de nous en informer en [ouvrant un nouveau problème](https://github.com/huggingface/huggingface_hub/issues/new) sur le dépôt `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')
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_base.py#L50)

**Paramètres :**

state_dict (`dict[str, Tensor]`) : Le dictionnaire d'état à enregistrer.

get_storage_size (`Callable[[Tensor], int]`) : Une fonction qui renvoie la taille d'un tenseur lorsqu'il est enregistré sur disque, en octets.

get_storage_id (`Callable[[Tensor], Optional[Any]]`, *facultatif*) : Une fonction qui renvoie un identifiant unique pour le stockage d'un tenseur. Plusieurs tenseurs différents peuvent partager le même stockage sous-jacent. Cet identifiant est garanti unique et constant pour le stockage de ce tenseur pendant sa durée de vie. Deux stockages de tenseurs dont les durées de vie ne se chevauchent pas peuvent avoir le même identifiant.

filename_pattern (`str`, *facultatif*) : Le motif à utiliser pour générer les noms des fichiers dans lesquels le modèle sera enregistré. Le motif doit être une chaîne de caractères qui peut être formatée avec `filename_pattern.format(suffix=...)` et doit contenir le mot-clé `suffix`

max_shard_size (`int` ou `str`, *facultatif*) : La taille maximale de chaque fragment, en octets. La valeur par défaut est de 5 Go.

**Retourne :** `StateDictSplit`

Un objet `StateDictSplit` contenant les shards et l'index pour les récupérer.

Diviser le dictionnaire d'état d'un modèle en fragments afin que chaque fragment soit inférieur à une taille donnée.

Les shards sont déterminés en parcourant le `state_dict` dans l'ordre de ses clés. Aucune optimisation n'est effectuée pour que chaque shard soit aussi proche que possible de la taille maximale passée. Par exemple, si la limite est de 10 Go et que nous avons des tenseurs de tailles [6 Go, 6 Go, 2 Go, 6 Go, 2 Go, 2 Go], ils seront shardés en [6 Go], [6+2 Go], [6+2+2 Go] et non en [6+2+2 Go], [6+2 Go], [6 Go].

> [!WARNING]
> Si l'un des tenseurs du modèle est plus grand que `max_shard_size`, il finira dans son propre shard dont la taille sera supérieure à `max_shard_size`.

## Chargement des tenseurs

Les utilitaires de chargement prennent en charge les points de contrôle monofichier et fragmentés, au format safetensors ou pickle. [load_torch_model()](/docs/huggingface_hub/v2.4.0/fr/package_reference/serialization#huggingface_hub.load_torch_model) prend en entrée un `nn.Module` et un chemin de point de contrôle (fichier unique ou répertoire) et charge les poids dans le modèle.

> [!WARNING]
> Les deux utilitaires utilisent par défaut `safe=True`, ce qui signifie que le point de contrôle est toujours désérialisé avec le chargeur safetensors — quel que soit le nom du fichier. Le chargement d'un point de contrôle pickle nécessite une opt-in explicite, car le dépickling exécute du code arbitraire au moment du chargement :
> ```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)
> ```
> Le chemin pickle utilise par défaut `weights_only=True`, c'est-à-dire le dépickleur restreint de torch. Un point de contrôle contenant des objets non tenseurs (états de l'optimiseur, un modèle entier, ...) nécessite `weights_only=False` en plus de `safe=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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L375)

**Paramètres :**

model (`torch.nn.Module`) : Le modèle dans lequel charger le point de contrôle.

checkpoint_path (`str` ou `os.PathLike`) : Chemin vers le fichier de point de contrôle ou le répertoire contenant les points de contrôle.

strict (`bool`, *facultatif*, valeur par défaut `False`) : Indique s'il faut imposer strictement que les clés du dictionnaire d'état du modèle correspondent aux clés du point de contrôle. Comme pour `torch.nn.Module.load_state_dict`, la vérification a lieu une fois le point de contrôle chargé, de sorte que le modèle peut avoir été partiellement mis à jour lorsque l'erreur est levée.

safe (`bool`, *facultatif*, valeur par défaut `True`) : Si `safe` est True, les fichiers safetensors seront chargés. Si `safe` est False, la fonction tentera d’abord de charger les fichiers safetensors s’ils sont disponibles, sinon elle basculera sur le chargement des fichiers pickle. Un `filename_pattern` qui ne décrit pas des fichiers safetensors est rejeté lorsque `safe=True`.

weights_only (`bool`, *facultatif*, valeur par défaut `True`) : Si True, charge uniquement les poids du modèle sans les états de l’optimiseur ni les autres métadonnées, en utilisant le dépickleur restreint de torch. Définissez False pour autoriser des objets Python arbitraires dans un point de contrôle pickle (ce qui exécute du code arbitraire au moment du chargement). N’a aucun effet sur PyTorch < 1.13, qui ne dispose pas de dépickleur restreint et effectue toujours le dépickling sans restriction.

map_location (`str` ou `torch.device`, *facultatif*) : un objet `torch.device`, une chaîne de caractères ou un dictionnaire spécifiant comment remapper les emplacements de stockage. Il indique l’emplacement où tous les tenseurs doivent être chargés.

mmap (`bool`, *facultatif*, par défaut `False`) : Indique s'il faut utiliser le chargement de fichiers en mémoire mappée. Le mappage mémoire peut améliorer les performances de chargement pour les grands modèles dans PyTorch >= 2.1.0 avec des points de contrôle basés sur zipfile.

filename_pattern (`str`, *facultatif*) : Le motif à rechercher pour le fichier d'index. Le motif doit être une chaîne de caractères qui peut être formatée avec `filename_pattern.format(suffix=...)` et doit contenir le mot-clé `suffix`. Par défaut, `"model{suffix}.safetensors"`.

**Retourne :** `NamedTuple`

Un tuple nommé avec les champs `missing_keys` et `unexpected_keys`.
- `missing_keys` est une liste de str contenant les clés manquantes, c’est-à-dire les clés présentes dans le modèle mais absentes du checkpoint.
- `unexpected_keys` est une liste de str contenant les clés inattendues, c’est-à-dire les clés présentes dans le checkpoint mais absentes du modèle.

**Exceptions levées :** ``FileNotFoundError`` ou ``ImportError`` ou ``ValueError``

- [`FileNotFoundError`](https://docs.python.org/3/library/exceptions.html#FileNotFoundError) -- Si le fichier ou le répertoire de point de contrôle n'existe pas.
- [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) -- Si safetensors ou torch n'est pas installé lors de la tentative de chargement d'un fichier .safetensors ou d'un checkpoint PyTorch, respectivement.
- [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) -- Si le format du point de contrôle ne peut pas être déterminé.

Charger un point de contrôle dans un modèle, en gérant à la fois les points de contrôle fragmentés et non fragmentés.

Exemple :
```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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L633)

**Paramètres :**

checkpoint_file (`str` ou `os.PathLike`) : Chemin du fichier de point de contrôle à charger. Peut être un point de contrôle safetensors ou pickle (`.bin`).

map_location (`str` ou `torch.device`, *facultatif*) : un objet `torch.device`, une chaîne de caractères ou un dictionnaire spécifiant comment remapper les emplacements de stockage. Il indique l’emplacement où tous les tenseurs doivent être chargés.

weights_only (`bool`, *facultatif*, valeur par défaut `True`) : Si True, charge uniquement les poids du modèle sans les états de l'optimiseur ni les autres métadonnées, en utilisant le dé-sérialiseur restreint de torch. Définissez False pour autoriser des objets Python arbitraires dans un point de contrôle pickle (ce qui exécute du code arbitraire au moment du chargement). N'a aucun effet lors du chargement de fichiers safetensors, ni sur PyTorch < 1.13 qui ne dispose pas de dé-sérialiseur restreint — ces versions dé-sérialisent toujours sans restriction et un avertissement est journalisé.

mmap (`bool`, *facultatif*, valeur par défaut `False`) : Indique s'il faut utiliser le chargement de fichiers en mémoire mappée. Le mappage mémoire peut améliorer les performances de chargement pour les grands modèles dans PyTorch >= 2.1.0 avec des points de contrôle basés sur zipfile. N'a aucun effet lors du chargement de fichiers safetensors, car la bibliothèque `safetensors` utilise le mappage mémoire par défaut.

safe (`bool`, *facultatif*, valeur par défaut `True`) : Si True, le point de contrôle est toujours chargé au format safetensors, quel que soit son nom. Tout autre format (par exemple un fichier pickle `.bin`) provoque une `ValueError` au lieu d'être désérialisé : les points de contrôle pickle peuvent exécuter du code arbitraire au moment du chargement. Si False, le fichier est chargé au format safetensors si son nom l'indique, et avec `torch.load` dans le cas contraire.

**Retourne :** `Union[dict[str, "torch.Tensor"], Any]`

Le point de contrôle chargé.
- Pour les fichiers safetensors : renvoie toujours un dictionnaire associant les noms de paramètres aux tenseurs.
- Pour les fichiers pickle : renvoie n'importe quel objet Python qui a été sérialisé (généralement un dictionnaire d'état, mais cela peut être un modèle entier, l'état d'un optimiseur, ou tout autre objet Python).

**Exceptions levées :** ``FileNotFoundError`` ou ``ImportError`` ou ``OSError`` ou ``ValueError``

- [`FileNotFoundError`](https://docs.python.org/3/library/exceptions.html#FileNotFoundError) -- Si le fichier de point de contrôle n'existe pas.
- [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) -- Si safetensors ou torch n'est pas installé lors de la tentative de chargement d'un fichier .safetensors ou d'un checkpoint PyTorch, respectivement.
- [`OSError`](https://docs.python.org/3/library/exceptions.html#OSError) -- Si le format du fichier de point de contrôle est invalide ou si les fichiers git-lfs ne sont pas téléchargés correctement.
- [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) -- Si le chemin du fichier de point de contrôle est vide ou invalide, ou s'il ne peut pas être désérialisé en tant que safetensors alors que `safe=True` (passez `safe=False` pour autoriser les points de contrôle pickle).

Charge un fichier de point de contrôle, en gérant à la fois les formats de point de contrôle safetensors et pickle.

Exemple :
```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)
```

## Aides pour les tenseurs

### 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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L878)

Retourne un identifiant unique pour un stockage de tenseur.

Plusieurs tenseurs différents peuvent partager le même stockage sous-jacent. Cet identifiant est garanti unique et constant pour le stockage de ce tenseur pendant sa durée de vie. Deux stockages de tenseurs dont les durées de vie ne se chevauchent pas peuvent avoir le même id. Dans le cas des tenseurs meta, nous renvoyons None car nous ne pouvons pas déterminer s'ils partagent le même stockage.

Extrait de 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)
```

[Source](https://github.com/huggingface/huggingface_hub/blob/v2.4.0/src/huggingface_hub/serialization/_torch.py#L895)

Extrait de https://github.com/huggingface/safetensors/blob/08db34094e9e59e2f9218f2df133b7b4aaff5a99/bindings/python/py_src/safetensors/torch.py#L31C1-L41C59

