- Safetensors è un formato di file per archiviare i pesi dei modelli di machine learning che previene le vulnerabilità legate all'esecuzione arbitraria di codice presenti nei formati basati su pickle
- Carica da 2 a 10 volte più velocemente rispetto ai file .bin di PyTorch, grazie al memory mapping senza copia e supporta il caricamento lazy per modelli di dimensioni superiori al gigabyte
- Installa con
pip install safetensorse utilizzasafe_open()per caricare osave_file()per salvare tensori - Ampio supporto da parte di Hugging Face, Ollama, LM Studio, ComfyUI e tutti i principali framework di machine learning
Safetensors è un formato binario per archiviare e caricare i pesi dei modelli di machine learning sviluppato da Hugging Face. Risolve critiche vulnerabilità di sicurezza insite nei formati basati su pickle (file .bin e .pt di PyTorch) adottando una struttura semplice e staticamente analizzabile, incapace di eseguire codice arbitrario durante la deserializzazione. Il formato garantisce tempi di caricamento significativamente più rapidi grazie al memory mapping e alle operazioni senza copia, rendendolo il formato preferito per la distribuzione e il caricamento dei modelli AI nel 2026.
Che cos'è Safetensors
Safetensors memorizza i tensori (array multidimensionali di numeri che rappresentano i pesi delle reti neurali) in un semplice formato binario accompagnato da un header JSON. A differenza dei formati basati su pickle storicamente utilizzati in PyTorch, safetensors contiene esclusivamente dati grezzi dei tensori e metadati — nessun codice Python, nessuna definizione di classe, nessuna istruzione eseguibile.
La struttura del file è composta da:
- Un header di 8 byte contenente la lunghezza dei metadati
- Una sezione JSON di metadati che descrive nomi, forme, tipi di dato e offset in byte dei tensori
- Dati grezzi dei tensori memorizzati in blocchi contigui allineati in memoria
Questa semplicità consente il caricamento tramite memory mapping: il sistema operativo mappa direttamente il file nella memoria del processo, permettendo un accesso istantaneo ai dati dei tensori senza dover copiare gigabyte di dati nella RAM. Quando si carica un modello da 7 miliardi di parametri salvato in formato safetensors, il tempo di caricamento è misurato in millisecondi anziché in secondi.
Perché è stato creato Safetensors
Il formato Python pickle, utilizzato per impostazione predefinita nelle funzioni di PyTorch torch.save() e torch.load(), può eseguire codice Python arbitrario durante la deserializzazione. Un attaccante malintenzionato può creare un file .bin o .pt che esegue malware non appena viene chiamata la funzione torch.load(). Questa non è una vulnerabilità teorica: numerosi incidenti hanno dimostrato l’uso di file modello malevoli nel mondo reale.
Oltre alla sicurezza, i formati basati su pickle presentano problemi prestazionali:
| Problema | Basati su pickle (.bin, .pt) | Safetensors |
|---|---|---|
| Esecuzione di codice arbitrario | Sì, intrinseca al formato pickle | No, formato statico |
| Tempo di caricamento per un modello da 7B | 5–15 secondi | 0,5–2 secondi |
| Overhead di memoria durante il caricamento | 2× la dimensione del modello (richiede copia) | ~1× (tramite memory mapping) |
| Portabilità tra framework | Specifico per Python/PyTorch | Disponibile in qualsiasi linguaggio con binding dedicati |
| Supporto al caricamento lazy | No | Sì |
Durante il caricamento di un file pickle, Python deve deserializzare l’intera struttura in memoria, ricostruire gli oggetti Python e quindi copiare i dati dei tensori nel formato nativo del framework. Safetensors elimina questi passaggi mappando direttamente i dati binari dei tensori in memoria.
Installazione e utilizzo di Safetensors
Installa la libreria Python:
pip install safetensorsCaricamento di file Safetensors
Usa safe_open() per un caricamento lazy con memory mapping:
from safetensors import safe_open
with safe_open("model.safetensors", framework="pt", device="cpu") as f:
# Ottieni l'elenco dei nomi dei tensori
tensor_names = f.keys()
# Carica un tensore specifico (lazy: carica solo questo tensore)
embedding_weights = f.get_tensor("model.embed_tokens.weight")
# Ottieni i metadati del tensore senza caricarlo
metadata = f.metadata()Il framework specifica il framework di destinazione: "pt" per PyTorch, "tf" per TensorFlow, "np" per NumPy, oppure "jax" per JAX. Il parametro device controlla su quale dispositivo vengono allocati i tensori: "cpu", "cuda:0", oppure altri identificativi di dispositivo.
Per caricare tutti i tensori in un’unica operazione:
from safetensors.torch import load_file
tensors = load_file("model.safetensors")
# Restituisce un dizionario: {"layer.weight": tensor, "layer.bias": tensor, ...}Salvataggio di file Safetensors
Salva un dizionario di tensori:
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")Includi metadati personalizzati:
save_file(
tensors,
"model.safetensors",
metadata={"model_type": "bert", "vocab_size": "50000"}
)Caricamento di modelli da Hugging Face
La libreria transformers di Hugging Face utilizza automaticamente safetensors quando disponibile:
from transformers import AutoModel
# Scarica e carica automaticamente il file .safetensors, se disponibile
model = AutoModel.from_pretrained("bert-base-uncased")Forza il formato safetensors:
model = AutoModel.from_pretrained(
"bert-base-uncased",
use_safetensors=True # Genera un errore se safetensors non è disponibile
)La maggior parte dei modelli sull’Hugging Face Hub include ormai entrambi i file model.safetensors e e pytorch_model.bin . La libreria preferisce safetensors quando entrambi i formati sono presenti.
Conversione tra formati
Conversione da PyTorch .bin a Safetensors
from safetensors.torch import save_file
import torch
# Carica il checkpoint PyTorch
state_dict = torch.load("pytorch_model.bin", map_location="cpu")
# Salva in formato safetensors
save_file(state_dict, "model.safetensors")Conversione da Safetensors a PyTorch .bin
from safetensors.torch import load_file
import torch
tensors = load_file("model.safetensors")
torch.save(tensors, "pytorch_model.bin")Script di conversione di Hugging Face
Il transformers include uno strumento di conversione:
python -m transformers.convert_safetensors_to_pytorch
--model_name_or_path ./model_folder
--output_dir ./convertedDettagli tecnici del formato di file
Un file safetensors ha la seguente struttura:
- Intestazione (8 byte): intero senza segno a 64 bit in formato little-endian contenente la lunghezza, in byte, dei metadati JSON
- Metadati (lunghezza variabile): oggetto JSON con questo schema:
{ "layer_name": { "dtype": "F32", // Tipo di dato: F32, F16, BF16, I64, I32, ecc. "shape": [768, 768], // Dimensioni del tensore "data_offsets": [0, 2359296] // Posizione iniziale e finale, in byte, nella sezione dati }, "__metadata__": { // Metadati personalizzati opzionali "key": "value" } } - Sezione dati: byte grezzi dei tensori, memorizzati in ordine C-contiguous (row-major) e allineati a multipli di 8 byte
Il formato supporta i seguenti tipi di dato: F64, F32, F16, BF16, I64, U64, I32, U32, I16, U16, I8, U8, BOOL. L’intervallo di byte occupato da ciascun tensore è specificato nei metadati, consentendo il caricamento selettivo senza dover analizzare l’intero file.
Supporto nell'ecosistema
Safetensors è supportato nell’intero ecosistema dell’intelligenza artificiale:
| Strumento / Framework | Livello di supporto | Note |
|---|---|---|
| Hugging Face Transformers | Nativo | Formato predefinito dalla versione v4.30 |
| Hugging Face Diffusers | Nativo | Utilizzato per i modelli Stable Diffusion |
| PyTorch | Tramite libreria | Richiede il pacchetto safetensors safetensors |
| TensorFlow | Tramite libreria | Supportato tramite binding |
| JAX | Tramite libreria | Supportato tramite binding |
| Ollama | Nativo | Esegue internamente una conversione in GGUF |
| LM Studio | Nativo | Carica direttamente i file safetensors |
| ComfyUI | Nativo | Formato principale per i modelli personalizzati |
| AUTOMATIC1111 | Nativo | Supporto per Stable Diffusion WebUI |
| llama.cpp | Tramite conversione | Converti nel formato GGUF |
| vLLM | Nativo | Supporto per server di inferenza |
| TGI | Nativo | Supporto per Text Generation Inference |
Quando valuti se un modello rientra nella memoria GPU disponibile, utilizza la Calcolatore VRAM per stimare i requisiti in base al numero di parametri e al livello di quantizzazione. Il formato del file in sé non influisce sull’uso della VRAM: file in formato safetensors e pickle dello stesso modello consumano identica memoria GPU una volta caricati.
Caratteristiche prestazionali
Benchmark su un sistema dotato di SSD NVMe e 64 GB di RAM, con caricamento di un modello da 7 miliardi di parametri:
| Formato | Tempo di caricamento | Utilizzo massimo della RAM | Dimensione del file |
|---|---|---|---|
| PyTorch .bin | 8,2 s | 28 GB | 13,5 GB |
| Safetensors (load_file) | 1,1 s | 14 GB | 13,5 GB |
| Safetensors (safe_open lazy) | 0,08 s | 0,5 GB | 13,5 GB |
L’approccio lazy loading con safe_open() è particolarmente utile quando devi esaminare l’architettura del modello, estrarre strati specifici o caricare modelli più grandi della RAM disponibile, caricando selettivamente solo i tensori necessari.
Per i modelli quantizzati, safetensors supporta tutti i tipi di dati standard, inclusi FP16, BF16, INT8 e INT4. La Database di modelli IA include le dimensioni dei file safetensors e i requisiti di VRAM per 37 modelli popolari, a diversi livelli di quantizzazione.
Modelli suddivisi in shard
I modelli di dimensioni superiori a pochi gigabyte sono spesso distribuiti come più file safetensors (sharding). Un modello da 70 miliardi di parametri potrebbe essere suddiviso in 8 shard:
model-00001-of-00008.safetensors
model-00002-of-00008.safetensors
...
model-00008-of-00008.safetensors
model.safetensors.index.jsonIl file indice associa i nomi dei tensori ai rispettivi shard:
{
"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"
}
}Le librerie Hugging Face gestiscono automaticamente il caricamento degli shard. Caricamento manuale:
import json
from safetensors import safe_open
with open("model.safetensors.index.json") as f:
index = json.load(f)
weight_map = index["weight_map"]
# Carica un tensore specifico individuandone lo shard
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)Binding per diversi linguaggi di programmazione
Sebbene l’implementazione di riferimento sia in Python, safetensors dispone di binding per diversi linguaggi:
- Rust: Implementazione principale in Rust per prestazioni e sicurezza
- Python: Binding ufficiali tramite PyPI
- JavaScript/Node.js:
@huggingface/safetensorspacchetto npm - C/C++: Disponibile tramite FFI alla libreria Rust
- Go: Implementazioni comunitarie disponibili
L’implementazione in Rust è quella di riferimento canonica. I binding Python ne incapsulano questa implementazione, ereditandone le caratteristiche prestazionali.
Domande frequenti
Posso usare safetensors con modelli PyTorch esistenti senza modificare il codice?
Sì, se utilizzi le librerie Hugging Face. Per modelli personalizzati, devi sostituire torch.load() a load_file() da safetensors e torch.save() a save_file(). I dati dei tensori e l’architettura del modello rimangono identici: cambia soltanto il formato di serializzazione. La conversione di checkpoint esistenti è un’operazione unica che richiede pochi secondi.
I file safetensors funzionano con diverse versioni di PyTorch?
Sì. A differenza dei file pickle, che possono risultare incompatibili tra diverse versioni di Python o PyTorch, safetensors memorizza dati binari grezzi senza alcuna serializzazione dipendente dalla versione. Un file safetensors creato con PyTorch 1.12 viene caricato correttamente anche con PyTorch 2.x, e viceversa. Ciò rende safetensors superiore per l’archiviazione a lungo termine e la distribuzione dei modelli.
Perché alcuni modelli sull’Hugging Face Hub sono ancora distribuiti come file .bin?
I modelli più vecchi, caricati prima del 2023, potrebbero contenere esclusivamente file basati su pickle. Hugging Face sta convertendo progressivamente il model hub, ma alcuni modelli restano disponibili solo in formato pickle qualora l’uploader originale non abbia fornito versioni in formato safetensors. Quando entrambi i formati sono presenti, safetensors viene scelto automaticamente. Puoi convertirli localmente utilizzando il metodo illustrato nella sezione di conversione sopra.
I file safetensors occupano più spazio rispetto ai file PyTorch .bin?
No. Le dimensioni dei file sono tipicamente identiche o differiscono di appena l’1–2%, poiché entrambi i formati memorizzano gli stessi dati grezzi dei tensori. Safetensors aggiunge un sovraccarico minimo (un’intestazione JSON di pochi kilobyte), mentre pickle introduce un sovraccarico legato alla serializzazione degli oggetti Python. Per un modello da 7 miliardi di parametri, entrambi i formati producono file di circa 13–14 GB. La differenza riguarda la velocità di caricamento e la sicurezza, non l’efficienza di archiviazione.
Posso ispezionare i file safetensors senza caricare l’intero modello in memoria?
Sì, ed è uno dei principali vantaggi di safetensors. Utilizza safe_open() per leggere i metadati e caricare selettivamente tensori specifici. Puoi elencare tutti i nomi dei tensori, verificarne forma e tipo di dato ed estrarre singoli strati senza caricare l’intero file da diversi gigabyte. Questo è particolarmente utile per l’analisi, il debug e l’estrazione di componenti del modello.
GGUF e safetensors sono la stessa cosa?
No. GGUF (GPT-Generated Unified Format) è un formato diverso, utilizzato principalmente da llama.cpp per l’inferenza quantizzata. GGUF include schemi di quantizzazione ottimizzati per l’inferenza su CPU, che safetensors non supporta. Safetensors è progettato per l’addestramento e la distribuzione generica dei modelli, mentre GGUF è ottimizzato per un’inferenza efficiente su hardware consumer. Molti strumenti, come Ollama, accettano safetensors come input e li convertono internamente in GGUF per l’inferenza.

