- Safetensors est un format de fichier permettant de stocker les poids des modèles d’apprentissage automatique, conçu pour éliminer les vulnérabilités liées à l’exécution de code arbitraire présentes dans les formats basés sur pickle.
- Il se charge 2 à 10 fois plus rapidement que les fichiers .bin de PyTorch grâce au memory mapping sans copie et prend en charge le chargement différé (lazy loading) pour les modèles de plusieurs gigaoctets.
- Installez-le avec la commande
pip install safetensorspuis utilisezsafe_open()pour charger ousave_file()pour sauvegarder des tenseurs. - Pris en charge de façon étendue par Hugging Face, Ollama, LM Studio, ComfyUI et tous les principaux frameworks d’apprentissage automatique.
Safetensors est un format binaire destiné au stockage et au chargement des poids des modèles d’apprentissage automatique, développé par Hugging Face. Il répond à des vulnérabilités critiques de sécurité inhérentes aux formats basés sur pickle (fichiers .bin et .pt de PyTorch) en adoptant une structure simple et statiquement analysable, incapable d’exécuter du code arbitraire lors de la désérialisation. Ce format permet des temps de chargement nettement plus rapides grâce au memory mapping et aux opérations sans copie, ce qui en fait, en 2026, le format privilégié pour la distribution et le chargement des modèles d’IA.
- Qu’est-ce que Safetensors ?
- Pourquoi Safetensors a-t-il été créé ?
- Installation et utilisation de Safetensors
- Conversion entre formats
- Détails techniques du format de fichier
- Prise en charge par l’écosystème
- Caractéristiques de performance
- Modèles fragmentés (sharded)
- Bindings linguistiques
- Questions fréquemment posées
Qu’est-ce que Safetensors ?
Safetensors stocke les tenseurs (tableaux multidimensionnels de nombres représentant les poids des réseaux de neurones) dans un format binaire brut accompagné d’un en-tête JSON. Contrairement aux formats historiques basés sur pickle utilisés dans PyTorch, safetensors ne contient que les données brutes des tenseurs et des métadonnées — aucun code Python, aucune définition de classe, aucune instruction exécutable.
La structure du fichier se compose de :
- Un en-tête de 8 octets contenant la longueur des métadonnées
- Une section JSON de métadonnées décrivant les noms des tenseurs, leurs dimensions, leurs types de données et leurs décalages en octets
- Les données brutes des tenseurs, stockées de façon contiguë dans des blocs alignés en mémoire
Cette simplicité permet un chargement via memory mapping : le système d’exploitation mappe directement le fichier en mémoire du processus, offrant un accès immédiat aux données des tenseurs sans copier des gigaoctets en RAM. Lorsque vous chargez un modèle de 7 milliards de paramètres au format safetensors, le temps de chargement se mesure en millisecondes plutôt qu’en secondes.
Pourquoi Safetensors a-t-il été créé ?
Le format Python pickle, utilisé par défaut dans la fonction torch.save() et torch.load()de PyTorch, peut exécuter du code Python arbitraire lors de la désérialisation. Un attaquant malveillant peut ainsi fabriquer un fichier .bin ou .pt capable d’exécuter un logiciel malveillant dès l’appel de torch.load(). Cette vulnérabilité n’est pas théorique : plusieurs incidents ont déjà démontré l’existence de fichiers modèles armés dans la nature.
Au-delà de la sécurité, les formats basés sur pickle souffrent également de problèmes de performance :
| Problème | Basés sur pickle (.bin, .pt) | Safetensors |
|---|---|---|
| Exécution de code arbitraire | Oui, inhérente à pickle | Non, format statique |
| Temps de chargement pour un modèle de 7 milliards de paramètres | 5 à 15 secondes | 0,5 à 2 secondes |
| Surcharge mémoire pendant le chargement | 2× la taille du modèle (copie obligatoire) | ≈1× (memory mapping) |
| Portabilité entre frameworks | Spécifique à Python/PyTorch | Compatible avec tout langage disposant de bindings |
| Prise en charge du chargement différé (lazy loading) | Non | Oui |
Lors du chargement d’un fichier pickle, Python doit désérialiser l’intégralité de la structure en mémoire, reconstruire les objets Python, puis copier les données des tenseurs dans le format natif du framework. Safetensors élimine toutes ces étapes en mappant directement les données binaires des tenseurs.
Installation et utilisation de Safetensors
Installez la bibliothèque Python :
pip install safetensorsChargement de fichiers Safetensors
Utilisez safe_open() pour un chargement différé (lazy loading) avec memory mapping :
from safetensors import safe_open
with safe_open("model.safetensors", framework="pt", device="cpu") as f:
# Obtenir la liste des noms de tenseurs
tensor_names = f.keys()
# Charger un tenseur spécifique (chargement différé – seul ce tenseur est chargé)
embedding_weights = f.get_tensor("model.embed_tokens.weight")
# Récupérer les métadonnées du tenseur sans le charger
metadata = f.metadata()Le framework spécifie le framework cible : "pt" pour PyTorch, "tf" pour TensorFlow, "np" pour NumPy, ou "jax" pour JAX. Le paramètre device détermine où les tenseurs sont placés : "cpu", "cuda:0", ou d'autres identifiants de périphérique.
Pour charger tous les tenseurs en une seule fois :
from safetensors.torch import load_file
tensors = load_file("model.safetensors")
# Renvoie un dictionnaire : {"layer.weight": tenseur, "layer.bias": tenseur, ...}Enregistrement de fichiers Safetensors
Enregistrez un dictionnaire de tenseurs :
from safetensors.torch import save_file
import torch
tensors = {
"embedding.weight": torch.randn(50000, 768),
"layer1.weight": torch.randn(768, 768),
"layer1.bias": torch.randn(768)
}
save_file(tensors, "model.safetensors")Inclure des métadonnées personnalisées :
save_file(
tensors,
"model.safetensors",
metadata={"model_type": "bert", "vocab_size": "50000"}
)Chargement de modèles depuis Hugging Face
La bibliothèque transformers de Hugging Face utilise automatiquement safetensors lorsqu’elle est disponible :
from transformers import AutoModel
# Télécharge et charge automatiquement le fichier .safetensors s’il est disponible
model = AutoModel.from_pretrained("bert-base-uncased")Forcer le format safetensors :
model = AutoModel.from_pretrained(
"bert-base-uncased",
use_safetensors=True # Échoue si safetensors n’est pas disponible
)La plupart des modèles disponibles sur le Hub Hugging Face incluent désormais à la fois les fichiers model.safetensors et et pytorch_model.bin . La bibliothèque privilégie safetensors lorsque les deux formats sont présents.
Conversion entre formats
Conversion de fichiers PyTorch .bin vers Safetensors
from safetensors.torch import save_file
import torch
# Charger un checkpoint PyTorch
state_dict = torch.load("pytorch_model.bin", map_location="cpu")
# Enregistrer au format safetensors
save_file(state_dict, "model.safetensors")Conversion de fichiers Safetensors vers PyTorch .bin
from safetensors.torch import load_file
import torch
tensors = load_file("model.safetensors")
torch.save(tensors, "pytorch_model.bin")Script de conversion Hugging Face
Le transformers La bibliothèque inclut un outil de conversion :
python -m transformers.convert_safetensors_to_pytorch
--model_name_or_path ./model_folder
--output_dir ./convertedDétails techniques du format de fichier
Un fichier safetensors possède la structure suivante :
- En-tête (8 octets) : Entier non signé sur 64 bits, en boutisme petit (little-endian), contenant la longueur, en octets, des métadonnées JSON
- Métadonnées (longueur variable) : Objet JSON respectant ce schéma :
{ "layer_name": { "dtype": "F32", // Type de données : F32, F16, BF16, I64, I32, etc. "shape": [768, 768], // Dimensions du tenseur "data_offsets": [0, 2359296] // Début et fin, en octets, dans la section de données }, "__metadata__": { // Métadonnées personnalisées facultatives "key": "value" } } - Section de données : Octets bruts des tenseurs, stockés dans l’ordre C-contigu (row-major), alignés sur des limites de 8 octets
Le format prend en charge les types de données suivants : F64, F32, F16, BF16, I64, U64, I32, U32, I16, U16, I8, U8, BOOL. La plage d’octets de chaque tenseur est précisée dans les métadonnées, permettant un chargement sélectif sans analyse complète du fichier.
Prise en charge par l’écosystème
Safetensors est pris en charge dans tout l’écosystème de l’IA :
| Outil / Cadre | Niveau de prise en charge | Remarques |
|---|---|---|
| Hugging Face Transformers | Natif | Format par défaut depuis la version v4.30 |
| Hugging Face Diffusers | Natif | Utilisé pour les modèles Stable Diffusion |
| PyTorch | Via la bibliothèque | Nécessite le paquet safetensors safetensors |
| TensorFlow | Via la bibliothèque | Pris en charge via des liaisons |
| JAX | Via la bibliothèque | Pris en charge via des liaisons |
| Ollama | Natif | Convertit en interne vers GGUF |
| LM Studio | Natif | Charge directement les fichiers safetensors |
| ComfyUI | Natif | Format principal pour les modèles personnalisés |
| AUTOMATIC1111 | Natif | Prise en charge dans l’interface WebUI Stable Diffusion |
| llama.cpp | Via conversion | Convertir au format GGUF |
| vLLM | Natif | Prise en charge des serveurs d’inférence |
| TGI | Natif | Prise en charge de Text Generation Inference |
Lors de l’évaluation de la compatibilité d’un modèle avec la mémoire GPU disponible, utilisez le Calculateur de VRAM pour estimer les besoins en fonction du nombre de paramètres et du niveau de quantification. Le format de fichier lui-même n’affecte pas l’utilisation de la VRAM : les fichiers safetensors et pickle d’un même modèle consomment une quantité identique de mémoire GPU une fois chargés.
Caractéristiques de performance
Résultats de benchmarks sur un système équipé d’un disque SSD NVMe et de 64 Go de RAM, chargement d’un modèle de 7 milliards de paramètres :
| Format | Temps de chargement | Utilisation maximale de la mémoire RAM | Taille du fichier |
|---|---|---|---|
| PyTorch .bin | 8,2 s | 28 Go | 13,5 Go |
| Safetensors (load_file) | 1,1 s | 14 Go | 13,5 Go |
| Safetensors (safe_open lazy) | 0,08 s | 0,5 Go | 13,5 Go |
L’approche de chargement différé avec safe_open() s’avère particulièrement utile lorsque vous devez inspecter l’architecture d’un modèle, extraire des couches spécifiques ou charger des modèles dépassant la mémoire RAM disponible, en chargeant sélectivement les tenseurs requis.
Pour les modèles quantifiés, safetensors prend en charge tous les types de données standards, notamment FP16, BF16, INT8 et INT4. Le Base de données des modèles IA inclut les tailles de fichiers safetensors et les exigences en VRAM pour 37 modèles populaires, à différents niveaux de quantification.
Modèles fragmentés (sharded)
Les modèles volumineux (plusieurs gigaoctets) sont souvent distribués sous forme de plusieurs fichiers safetensors (sharding). Un modèle de 70 milliards de paramètres peut ainsi être divisé en 8 fragments :
model-00001-of-00008.safetensors
model-00002-of-00008.safetensors
...
model-00008-of-00008.safetensors
model.safetensors.index.jsonLe fichier d’index associe chaque nom de tenseur à son fragment correspondant :
{
"metadata": {"total_size": 141123453952},
"weight_map": {
"model.embed_tokens.weight": "model-00001-of-00008.safetensors",
"model.layers.0.self_attn.q_proj.weight": "model-00001-of-00008.safetensors",
"model.layers.40.mlp.gate_proj.weight": "model-00005-of-00008.safetensors"
}
}Les bibliothèques Hugging Face gèrent automatiquement le chargement des fragments. Chargement manuel :
import json
from safetensors import safe_open
with open("model.safetensors.index.json") as f:
index = json.load(f)
weight_map = index["weight_map"]
# Charger un tenseur spécifique en identifiant son fragment
tensor_name = "model.layers.20.mlp.down_proj.weight"
shard_file = weight_map[tensor_name]
with safe_open(shard_file, framework="pt", device="cpu") as f:
tensor = f.get_tensor(tensor_name)Bindings linguistiques
Bien que l’implémentation de référence soit écrite en Python, safetensors propose des liaisons pour plusieurs langages :
- Rust : Implémentation principale en Rust, conçue pour les performances et la sécurité
- Python : Liaisons officielles disponibles via PyPI
- JavaScript/Node.js :
@huggingface/safetensorsPaquet npm - C/C++ : Disponible via FFI vers la bibliothèque Rust
- Go : Implémentations communautaires disponibles
L’implémentation Rust constitue la référence canonique. Les liaisons Python encapsulent cette implémentation et héritent donc de ses caractéristiques de performance.
Questions fréquemment posées
Puis-je utiliser safetensors avec mes modèles PyTorch existants sans modifier mon code ?
Oui, si vous utilisez les bibliothèques Hugging Face. Pour des modèles personnalisés, vous devez remplacer les appels à torch.load() sur load_file() de safetensors et torch.save() sur save_file(). Les données tensorielles et l’architecture du modèle restent inchangées — seul le format de sérialisation évolue. La conversion des checkpoints existants est une opération ponctuelle qui ne prend que quelques secondes.
Les fichiers safetensors sont-ils compatibles entre différentes versions de PyTorch ?
Oui. Contrairement aux fichiers pickle, qui peuvent devenir incompatibles suite à des changements de version de Python ou de PyTorch, safetensors stocke des données binaires brutes sans recourir à une sérialisation dépendante de la version. Un fichier safetensors créé avec PyTorch 1.12 se charge correctement sous PyTorch 2.x, et inversement. Cela rend safetensors nettement plus adapté à l’archivage à long terme et à la distribution des modèles.
Pourquoi certains modèles sur le Hugging Face Hub sont-ils encore distribués au format .bin ?
Les modèles plus anciens, publiés avant 2023, peuvent ne comporter que des fichiers basés sur pickle. Hugging Face convertit progressivement l’intégralité du Hub, mais certains modèles restent exclusivement au format pickle si leur auteur initial n’a pas fourni de versions safetensors. Lorsque les deux formats sont disponibles, safetensors est automatiquement privilégié. Vous pouvez effectuer la conversion localement à l’aide de la méthode décrite dans la section « Conversion » ci-dessus.
Le format safetensors augmente-t-il la taille des fichiers par rapport aux fichiers PyTorch .bin ?
Non. Les tailles de fichiers sont généralement identiques, ou diffèrent de moins de 1 à 2 %, car les deux formats stockent exactement les mêmes données tensorielles brutes. Safetensors ajoute un faible surcoût (un en-tête JSON de quelques kilo-octets), tandis que pickle introduit un surcoût lié à la sérialisation des objets Python. Pour un modèle de 7 milliards de paramètres, les deux formats produisent des fichiers d’environ 13 à 14 Go. La différence réside dans la vitesse de chargement et la sécurité, non dans l’efficacité de stockage.
Puis-je inspecter un fichier safetensors sans charger entièrement le modèle en mémoire ?
Oui, c’est l’un des principaux avantages de safetensors. Utilisez safe_open() pour lire les métadonnées et charger sélectivement des tenseurs spécifiques. Vous pouvez lister tous les noms de tenseurs, vérifier leurs dimensions et leurs types de données, et extraire des couches individuelles sans charger l’intégralité du fichier, qui peut faire plusieurs gigaoctets. Cette fonctionnalité est particulièrement utile pour l’analyse, le débogage et l’extraction de composants de modèles.
GGUF et safetensors sont-ils identiques ?
Non. GGUF (GPT-Generated Unified Format) est un format différent, utilisé principalement par llama.cpp pour l’inférence quantifiée. GGUF intègre des schémas de quantification optimisés pour l’inférence sur CPU, que safetensors ne prend pas en charge. Safetensors est conçu pour l’entraînement et la distribution généraliste de modèles, tandis que GGUF est optimisé pour une inférence efficace sur du matériel grand public. De nombreux outils comme Ollama acceptent les fichiers safetensors en entrée et les convertissent automatiquement en GGUF pour l’inférence.

