programa
Si has descargado un modelo de Hugging Face últimamente, seguramente habrás visto un archivo .safetensors en lugar de un .bin o .pkl. Es un cambio más importante de lo que parece.
Durante años, la mayoría de frameworks de ML confiaron en la serialización basada en pickle para guardar checkpoints de modelos. Funcionaba, pero conllevaba un coste oculto: al cargar un checkpoint podía ejecutarse código Python arbitrario durante la deserialización, abriendo la puerta a ataques a la cadena de suministro y cargas maliciosas camufladas en archivos de modelo aparentemente inocentes.
SafeTensors nació para cerrar esa brecha. Solo almacena los pesos numéricos brutos de los tensores y no ejecuta ningún código al cargarse, por lo que se ha convertido en el formato predeterminado en Hugging Face Hub. En abril de 2026, pasó a formar parte oficialmente de la PyTorch Foundation, bajo la Linux Foundation, junto a proyectos como PyTorch, vLLM, DeepSpeed y Ray.
Sigue leyendo para entender cómo funciona el formato por dentro y cómo se compara con otros formatos.
¿Qué es SafeTensors?
SafeTensors es un formato de archivo diseñado específicamente para guardar los pesos de los modelos de forma segura.
El formato separa los datos numéricos brutos de los tensores del código ejecutable y almacena únicamente los pesos. Aquí es donde SafeTensors se diferencia de los formatos basados en pickle.
Proyectos de aprendizaje automático
El formato también encaja de forma natural en los flujos de trabajo modernos de ML porque se centra en lo que la mayoría de checkpoints ya contienen:
- Tensores
- Formas
- Tipos de datos
- Valores de los pesos
En lugar de comportarse como un sistema de serialización genérico de Python, SafeTensors actúa como una capa de almacenamiento dedicada para los parámetros del modelo.
Aunque Hugging Face desarrolló originalmente SafeTensors para su ecosistema, el formato en sí es independiente del framework. Se unió a la PyTorch Foundation recientemente (en abril de 2026) y es compatible con PyTorch, TensorFlow, JAX, Flax, NumPy y otros frameworks de ML.
El problema de Pickle: por qué hacía falta un nuevo formato
El formato Pickle de Python se creó para aplicaciones generales en Python, donde a menudo se necesita guardar y restaurar objetos completos junto con su estado interno, métodos y lógica de reconstrucción.
Los checkpoints de machine learning no suelen requerir ese nivel de almacenamiento. La mayoría de archivos de modelos guardan principalmente tensores: matrices de pesos, embeddings, sesgos y otros parámetros numéricos. En la práctica, el checkpoint es sobre todo datos numéricos estructurados.
Pero un archivo .pkl hace más que almacenar datos. También puede incluir instrucciones para que Python reconstruya objetos durante la carga. Eso significa que la deserialización no es una lectura pasiva; puede ejecutar código. Y si ese código es malicioso, se convierte en un problema de seguridad serio.
Cómo permite pickle la ejecución de código arbitrario
Python reconstruye objetos durante la deserialización con pickle usando métodos especiales como __reduce__(). Las clases pueden definir este método para indicar a pickle exactamente cómo debe reconstruirse el objeto al cargarlo en memoria.
Por ejemplo, __reduce__() puede devolver una función invocable junto con los argumentos para esa función. Durante la deserialización, Python ejecuta esa función para reconstruir el objeto. Código de ejemplo:
import pickle
import os
class Demo:
def __reduce__(self):
return (os.system, ("echo 'Code executed during deserialization'",))
payload = pickle.dumps(Demo())
pickle.loads(payload)
Cuando se ejecuta pickle.loads(), Python ejecuta la función devuelta por __reduce__(). En este ejemplo, la deserialización lanza un comando de shell mediante os.system().
El problema no es el comando de shell en sí. __reduce__() puede devolver cualquier callable con argumentos arbitrarios según su lógica. Eso significa que un archivo Pickle puede llamar a otras funciones, descargar archivos, modificar el entorno o ejecutar código malicioso al cargarse. Por eso la documentación de Python advierte explícitamente de no cargar datos pickle de fuentes no confiables.
El riesgo en la era de compartir modelos
Plataformas como Hugging Face Hub alojan ya más de un millón de modelos compartidos por investigadores, startups, aficionados y contribuyentes anónimos. El ecosistema avanza rápido porque los desarrolladores pueden descargar y probar modelos al instante. Pero la mayoría de checkpoints subidos no se auditan individualmente antes de su distribución.
Muchos checkpoints de PyTorch siguen usando serialización basada en pickle mediante formatos como .pt o .bin. Al cargar uno de esos archivos, Python puede ejecutar la lógica de deserialización incrustada en el checkpoint. Si el checkpoint es malicioso, esa lógica puede robar credenciales, leer variables de entorno, descargar cargas o ejecutar código remoto durante la carga.

Este es exactamente el problema que SafeTensors vino a resolver. En lugar de serializar objetos arbitrarios de Python, almacena solo los datos de los tensores y la metainformación necesaria para cargarlos correctamente. Cargar un archivo .safetensors no requiere ejecutar lógica de reconstrucción en Python, lo que reduce significativamente la superficie de ataque.
Cómo funciona el formato SafeTensors
Ahora que sabemos qué es SafeTensors y por qué existe, veamos su estructura y cómo trabaja.
La estructura de cabecera y datos
Un archivo SafeTensors tiene dos partes: una cabecera JSON seguida de los datos brutos de los tensores.
La cabecera guarda la metainformación de cada tensor, incluyendo
- Nombres de tensores
- Formas
- Tipos de datos
- Desplazamientos en bytes
Tras la cabecera, el archivo almacena contiguamente los bytes brutos de los tensores.
La cabecera funciona como un índice. Indica al cargador qué tensores existen y dónde están en el archivo, del mismo modo que el índice de una base de datos señala a los registros almacenados. SafeTensors limita el tamaño de esta cabecera a 100 MB para evitar cargas de metadatos sobredimensionadas.
Carga cero copias y mapeo de memoria
SafeTensors mejora la velocidad de carga mediante mapeo de memoria. En lugar de reconstruir objetos de Python durante la deserialización, los frameworks pueden mapear los datos de los tensores directamente del disco a la memoria. Eso reduce copias innecesarias y baja la carga de CPU durante la carga.
Según benchmarks de Hugging Face, SafeTensors cargó pesos unas 76 veces más rápido que PyTorch en CPU y alrededor de 2 veces más rápido en cargas de trabajo con GPU. Por supuesto, la mejora exacta depende del hardware y del tamaño del checkpoint, pero evitar la deserialización en Python mejora de forma consistente el rendimiento de carga.
Carga perezosa y deserialización parcial
SafeTensors carga tensores concretos por nombre en lugar de leer todo el checkpoint en memoria de una vez.
Esto es útil con modelos grandes distribuidos en varias GPU. Toma como ejemplo el modelo BLOOM de 176B parámetros. Con checkpoints estándar de PyTorch, el sistema primero tenía que deserializar todos los pesos del modelo antes de repartirlos entre dispositivos, lo que tardaba unos 10 minutos.
Con SafeTensors, cada GPU cargó solo los fragmentos de tensor que realmente necesitaba. Eso redujo el tiempo de arranque del modelo a unos 45 segundos en 8 GPU.
SafeTensors frente a otros formatos de serialización
SafeTensors funciona muy bien para guardar y cargar pesos de modelos de forma segura y eficiente, pero eso no lo convierte en un sustituto universal para todos los formatos. La elección adecuada depende de qué estás almacenando y en qué punto del pipeline está el modelo.
Ya hemos hablado mucho de pickle, así que me centraré en otros formatos.
SafeTensors vs GGUF
SafeTensors y GGUF resuelven problemas diferentes.
GGUF, siglas de GGML Unified Format, se diseñó para inferencia cuantizada en runtimes como llama.cpp. El formato se centra en el despliegue eficiente de modelos comprimidos, especialmente para inferencia en CPU y dispositivos edge.
SafeTensors está antes en el pipeline. La mayoría de checkpoints en SafeTensors guardan tensores en precisión completa o listos para entrenamiento, usados para entrenar, afinar, fusionar o inferencia distribuida. El formato prioriza la carga segura, la compatibilidad con frameworks como PyTorch y el acceso eficiente a tensores durante el entrenamiento y el servicio.
Pueden complementarse en lugar de competir. Flujo de trabajo de ejemplo:
- Entrena o afina el modelo con PyTorch y checkpoints en SafeTensors
- Cuantiza el modelo final
- Expórtalo a GGUF para desplegarlo en llama.cpp o en runtimes de inferencia en edge
SafeTensors vs ONNX
SafeTensors se centra en guardar los pesos de forma segura y cargarlos con eficiencia dentro de frameworks como PyTorch. Solo almacena tensores y metadatos, lo que lo hace ligero y rápido para compartir checkpoints, fine-tuning y flujos de entrenamiento.
ONNX adopta un enfoque más amplio. Almacena el grafo de cómputo completo junto con los parámetros del modelo. Eso hace que ONNX sea útil cuando quieres exportar un modelo de un framework y ejecutarlo en otro distinto.
Por ejemplo, los equipos que entrenan y afinán LLMs con PyTorch suelen preferir checkpoints en SafeTensors porque cargan rápido e integran directamente en sus flujos. Pero si ese mismo equipo necesita desplegar el modelo en TensorRT, ONNX Runtime o un motor de inferencia en edge, tiene más sentido exportarlo a ONNX.
Usar SafeTensors en la práctica
Una de las razones por las que SafeTensors se extendió rápido en el ecosistema PyTorch es que su API resulta familiar. Sigues trabajando con diccionarios de estado y tensores como siempre.
Guardar y cargar tensores
El flujo básico se parece al manejo estándar de checkpoints en PyTorch. Aquí tienes el ejemplo:
import torch
from safetensors.torch import save_file, load_file
tensors = {
"weights": torch.randn(2, 2),
"bias": torch.zeros(2)
}
save_file(tensors, "model.safetensors")
loaded_tensors = load_file("model.safetensors")
print(loaded_tensors["weights"])
save_file() escribe los tensores en formato .safetensors, mientras que load_file() los carga de vuelta en memoria.
SafeTensors también admite carga selectiva con safe_open(), que resulta útil con checkpoints grandes cuando solo necesitas unos pocos tensores.
from safetensors import safe_open
with safe_open("model.safetensors", framework="pt") as f:
weights = f.get_tensor("weights")
print(weights)
En lugar de cargar todo el checkpoint, get_tensor() lee solo el tensor que pides.
Convertir modelos existentes a safetensors
El patrón estándar es:
- Carga el modelo existente
- Extrae el diccionario de estado
- Guárdalo con
save_file()
from transformers import AutoModel
from safetensors.torch import save_file
model = AutoModel.from_pretrained("bert-base-uncased")
save_file(model.state_dict(), "model.safetensors")
state_dict() devuelve los pesos del modelo como tensores, que SafeTensors puede almacenar directamente.
Si el modelo ya está en Hugging Face Hub, puede que ni siquiera necesites código local de conversión. Hugging Face ofrece conversión integrada de checkpoints para muchos modelos alojados a través de la propia interfaz del Hub.
Formatos de serialización: tabla comparativa
| Función | SafeTensors | Pickle (.pkl/.bin/.pt) |
GGUF | ONNX |
|---|---|---|---|---|
| Ejecución de código arbitrario | No | Sí | No | No |
| Caso de uso principal | Entrenamiento, fine-tuning, compartición de checkpoints | Serialización general de Python | Inferencia cuantizada en edge/CPU | Despliegue entre frameworks |
| Almacena el grafo de cómputo | No | No | No | Sí |
| Carga con mapeo de memoria | Sí | No | Sí | No |
| Carga perezosa/parcial de tensores | Sí | No | Sí | No |
| Compatibilidad con frameworks | PyTorch, TF, JAX, Flax, NumPy | Python (todos los frameworks) | llama.cpp, runtimes edge | ONNX Runtime, TensorRT, edge |
| Compatibilidad con cuantización | En expansión (FP8, GPTQ, AWQ) | No | Sí (nativa) | Sí |
| Predeterminado en Hugging Face Hub | Sí | No | No | No |
SafeTensors en 2026: la PyTorch Foundation y lo que viene
En abril de 2026, Hugging Face contribuyó SafeTensors a la PyTorch Foundation bajo la Linux Foundation. El proyecto ahora se sienta junto a PyTorch, vLLM, DeepSpeed y Ray bajo la gobernanza de la fundación.
Ese movimiento indica que SafeTensors ya no es solo un proyecto de Hugging Face. Se está convirtiendo en infraestructura compartida para el ecosistema de ML.
El anuncio también apunta hacia dónde se dirige el formato.
Carga consciente del dispositivo
Una prioridad clave es la carga consciente del dispositivo. Hoy, muchos flujos aún cargan tensores en memoria de CPU antes de transferirlos a dispositivos CUDA o ROCm. Ese paso intermedio aumenta la latencia de arranque, especialmente en sistemas distribuidos grandes.
El equipo de SafeTensors trabaja en rutas de carga directa al dispositivo que reduzcan copias innecesarias en CPU y muevan los tensores directamente a los aceleradores.
Carga distribuida
La compatibilidad con carga distribuida también está evolucionando. Los sistemas modernos de inferencia rara vez ejecutan modelos en una sola GPU. El paralelismo de tensores y el paralelismo por etapas son ya patrones estándar para modelos grandes, pero las APIs de carga de checkpoints siguen fragmentadas entre frameworks.
SafeTensors está ampliando el soporte para carga consciente de fragmentos y disposiciones de tensores distribuidas, de modo que los frameworks coordinen la carga de checkpoints con más eficiencia entre dispositivos.
Flujos modernos de cuantización
El formato también se está adaptando a flujos de cuantización más recientes. Cada vez más, los sistemas de inferencia dependen de FP8, GPTQ y AWQ para reducir el uso de memoria y abaratar el servicio.
En lugar de forzar a los frameworks a gestionar esto con lógica de serialización a medida, SafeTensors está añadiendo soporte formal para formatos de tensores de menor precisión y cuantización por bloques directamente en el propio formato.
Ahora mismo, los desarrolladores todavía tienen que optar manualmente por SafeTensors cambiando sus flujos de guardado y carga. Pero hay trabajo en marcha para integrarlo más profundamente con el sistema nativo de serialización de PyTorch. Si eso llega a buen puerto, SafeTensors podría dejar de ser un formato alternativo y convertirse en la forma predeterminada en la que PyTorch guarda modelos.
Reflexiones finales
Durante años, los desarrolladores compartieron checkpoints con sistemas de serialización que podían ejecutar código Python arbitrario al cargarse. Cuando los hubs públicos de modelos empezaron a alojar millones de checkpoints, los riesgos de seguridad se hicieron imposibles de ignorar.
SafeTensors cambió eso al acotar el alcance del formato. En lugar de intentar serializar objetos completos de Python, se centra solo en guardar tensores y la metainformación necesaria para cargarlos. Ese diseño más simple elimina los riesgos de deserialización de los checkpoints basados en pickle y, además, mejora la velocidad de carga y la eficiencia de memoria.
Así que, cuando lo único que necesitas son los pesos del modelo, no tiene sentido ejecutar código arbitrario durante la deserialización: en esos casos es mejor utilizar SafeTensors.
Si quieres profundizar en las herramientas modernas de ML, los formatos de modelo y los flujos de trabajo de Hugging Face, nuestros cursos Deep Learning in Python y Working with Hugging Face son un buen siguiente paso. Cubren flujos prácticos para entrenar, afinar y desplegar modelos con las herramientas que usa hoy el ecosistema de IA.
Preguntas frecuentes sobre SafeTensors
¿Puedo convertir modelos .bin o .pt existentes a SafeTensors?
Sí. Puedes cargar el modelo normalmente en PyTorch o Transformers, extraer el state_dict() y guardarlo usando save_file() de la librería safetensors. Hugging Face Hub también admite conversión automática para muchos modelos alojados.
¿Puede SafeTensors almacenar modelos cuantizados?
Sí. SafeTensors ya es compatible con varios tipos de tensores de menor precisión, y el soporte para formatos como FP8, GPTQ y AWQ está creciendo a medida que la inferencia cuantizada se generaliza.
¿Puedo inspeccionar el contenido de un archivo SafeTensors sin cargar el modelo completo?
Sí. El formato guarda la metainformación de los tensores por separado en la cabecera, por lo que puedes inspeccionar nombres, formas y tipos sin cargar por completo el checkpoint en memoria.
¿Usar SafeTensors afecta a la exactitud del modelo?
No. SafeTensors cambia cómo se guardan y cargan los pesos, no los valores numéricos en sí. El modelo se comporta igual tras la carga.
¿SafeTensors solo es útil para cargas de inferencia?
También se utiliza durante el entrenamiento, el fine-tuning, el intercambio de checkpoints y en flujos de carga distribuida.
Srujana es una redactora técnica autónoma con una licenciatura de cuatro años en Informática. Escribir sobre diversos temas, como la ciencia de datos, la computación en la nube, el desarrollo, la programación, la seguridad y muchos otros, le resulta natural. Le encanta la literatura clásica y explorar nuevos destinos.

