Track
Если вы недавно скачивали модель с Hugging Face, вы, вероятно, заметили файл .safetensors вместо .bin или .pkl. Это более серьёзное изменение, чем кажется.
Много лет большинство ML-фреймворков полагались на сериализацию на базе pickle для хранения контрольных точек моделей. Это работало достаточно хорошо, но имело скрытую цену: при загрузке контрольной точки во время десериализации мог выполняться произвольный Python-код, что открывало дверь для атак на цепочку поставок и вредоносных полезных нагрузок, спрятанных в безобидных на вид файлах моделей.
SafeTensors создан, чтобы закрыть этот пробел. Он хранит только «сырые» веса тензоров и не выполняет код при загрузке, поэтому стал форматом по умолчанию на Hugging Face Hub. В апреле 2026 года проект официально вошёл в состав PyTorch Foundation под эгидой Linux Foundation вместе с такими проектами, как PyTorch, vLLM, DeepSpeed и Ray.
Читайте дальше, чтобы понять, как работает этот формат «под капотом» и как он соотносится с другими форматами.
Что такое SafeTensors?
SafeTensors — это файловый формат, специально разработанный для безопасного хранения весов моделей.
Формат отделяет «сырые» числовые данные тензоров от исполняемого кода и хранит только веса. В этом SafeTensors отличается от форматов на базе pickle.
Формат органично вписывается в современные ML-конвейеры, потому что фокусируется на том, что и так содержит большинство контрольных точек:
- Тензоры
- Формы
- Типы данных
- Значения весов
Вместо того чтобы вести себя как универсальная система сериализации Python, SafeTensors работает как специализированный слой хранения параметров модели.
Хотя Hugging Face изначально разработал SafeTensors для своей экосистемы, сам формат не привязан к конкретным фреймворкам. Он недавно (в апреле 2026) вошёл в PyTorch Foundation и поддерживает PyTorch, TensorFlow, JAX, Flax, NumPy и другие ML-фреймворки.
Проблема Pickle: почему понадобился новый формат
Формат Pickle в Python создавался для общих приложений на Python, где разработчикам часто нужно сохранять и восстанавливать целые объекты вместе с их внутренним состоянием, методами и логикой реконструкции.
Контрольным точкам машинного обучения обычно не требуется такой уровень хранения. Большинство файлов моделей содержат главным образом тензоры: матрицы весов, эмбеддинги, смещения и другие числовые параметры. На практике это значит, что контрольная точка — это, по сути, структурированные числовые данные.
Но файл .pkl делает больше, чем просто хранит данные. Он также может содержать инструкции для Python о том, как воссоздать объекты при загрузке. Это означает, что десериализация — не пассивное чтение; при этом может выполняться код. И если код вредоносный, это становится серьёзной проблемой безопасности.
Как pickle позволяет выполнять произвольный код
Во время десериализации pickle Python реконструирует объекты с помощью специальных методов, таких как __reduce__(). Классы могут определять этот метод, чтобы указать pickle, как именно следует восстанавливать объект при загрузке в память.
Например, __reduce__() может вернуть вызываемую функцию вместе с аргументами. Во время десериализации Python выполнит эту функцию, чтобы восстановить объект. Пример кода:
import pickle
import os
class Demo:
def __reduce__(self):
return (os.system, ("echo 'Code executed during deserialization'",))
payload = pickle.dumps(Demo())
pickle.loads(payload)
Когда вызывается pickle.loads(), Python исполняет функцию, возвращённую __reduce__(). В этом примере десериализация запускает команду оболочки через os.system().
Проблема не в самой командной строке. __reduce__() может вернуть любую вызываемую сущность с произвольными аргументами. Это значит, что файл Pickle может вызывать другие функции, скачивать файлы, менять окружение или выполнять вредоносный код при загрузке. Поэтому в документации Python прямо предупреждается о недопустимости загрузки pickle-данных из недоверенных источников.
Риск в эпоху обмена моделями
На таких платформах, как Hugging Face Hub, сейчас размещено более миллиона моделей, которыми делятся исследователи, стартапы, энтузиасты и анонимные авторы. Экосистема развивается быстро, потому что разработчики могут мгновенно скачивать и тестировать модели. Но большинство загруженных контрольных точек не проходит индивидуальный аудит перед распространением.
Многие контрольные точки PyTorch всё ещё полагаются на сериализацию на базе pickle в форматах .pt или .bin. Когда кто-то загружает такой файл, Python может исполнить логику десериализации, встроенную в контрольную точку. Если контрольная точка вредоносна, эта логика способна украсть учётные данные, прочитать переменные окружения, загрузить полезную нагрузку или выполнить удалённый код в процессе загрузки.

Именно эту проблему призван решить SafeTensors. Вместо сериализации произвольных Python-объектов он хранит только данные тензоров и метаданные, необходимые для их корректной загрузки. Для чтения файла .safetensors не требуется выполнять логику реконструкции Python, что существенно снижает поверхность атаки.
Как работает формат SafeTensors
Теперь, когда мы понимаем, что такое SafeTensors и зачем он нужен, посмотрим на его структуру и принципы работы.
Структура «заголовок — данные»
Файл SafeTensors состоит из двух частей: JSON-заголовка и следующих за ним «сырых» данных тензоров.
В заголовке хранятся метаданные для каждого тензора, включая
- Имена тензоров
- Формы
- Типы данных
- Смещения в байтах
После заголовка файл хранит байты тензоров последовательно, без разрывов.
Заголовок работает как оглавление. Он сообщает загрузчику, какие тензоры существуют и где они расположены в файле, подобно тому, как индекс базы данных указывает на сохранённые записи. SafeTensors ограничивает размер заголовка 100 МБ, чтобы предотвратить чрезмерно большие метаданные.
Загрузка без копирования и с отображением в память
SafeTensors ускоряет загрузку за счёт memory-mapped-загрузки. Вместо реконструкции Python-объектов при десериализации фреймворки могут напрямую отображать данные тензоров с диска в память. Это сокращает лишние копирования и снижает нагрузку на CPU при загрузке.
Согласно бенчмаркам Hugging Face, SafeTensors загружал веса примерно в 76 раз быстрее, чем PyTorch на CPU, и примерно в 2 раза быстрее на GPU-нагрузках. Конечно, точный выигрыш зависит от «железа» и размера контрольной точки, но избегание Python-десериализации стабильно улучшает время загрузки.
Ленивая загрузка и частичная десериализация
SafeTensors загружает конкретные тензоры по имени вместо чтения всей контрольной точки целиком в память.
Это полезно для больших распределённых моделей, работающих на нескольких GPU. Например, у модели BLOOM с 176 млрд параметров. В стандартных контрольных точках PyTorch системе сначала приходилось десериализовать все веса модели, а затем распределять их по устройствам, что занимало около 10 минут.
С SafeTensors каждый GPU загружал только те фрагменты тензоров, которые ему действительно нужны. Это сократило время запуска модели до примерно 45 секунд на 8 GPU.
SafeTensors и другие форматы сериализации
SafeTensors отлично подходит для безопасного и эффективного хранения и загрузки весов моделей, но это не означает, что он заменяет все форматы. Правильный выбор зависит от того, что вы храните и на каком этапе конвейера находится модель.
Мы уже много говорили о pickle, поэтому сосредоточимся на других форматах.
SafeTensors vs GGUF
SafeTensors и GGUF решают разные задачи.
GGUF (GGML Unified Format) создан для квантованных инференс-нагрузок в рантаймах вроде llama.cpp. Формат ориентирован на эффективное развёртывание сжатых моделей, особенно для инференса на CPU и на периферийных устройствах.
SafeTensors располагается раньше по конвейеру. Большинство контрольных точек SafeTensors хранят тензоры с полной точностью или готовые к обучению, используемые для обучения, дообучения, слияния или распределённого инференса. Формат ставит во главу угла безопасную загрузку, совместимость с фреймворками вроде PyTorch и эффективный доступ к тензорам во время обучения и сервинга.
Они могут дополнять друг друга, а не конкурировать напрямую. Пример рабочего процесса:
- Обучите или дообучите модель с использованием PyTorch и контрольных точек SafeTensors
- Квантованйте итоговую модель
- Экспортируйте её в GGUF для развёртывания в llama.cpp или периферийных рантаймах инференса
SafeTensors vs ONNX
SafeTensors фокусируется на безопасном хранении весов моделей и их быстрой загрузке внутри фреймворков вроде PyTorch. Он хранит только тензоры и метаданные, что делает его лёгким и быстрым для обмена контрольными точками, дообучения и рабочих процессов обучения.
ONNX подходит шире. Он хранит полный вычислительный граф вместе с параметрами модели. Это делает ONNX полезным, когда вы хотите экспортировать модель из одного фреймворка и запускать её в совершенно другом окружении.
Например, команды, которые обучают и дообучают LLM в PyTorch, обычно предпочитают контрольные точки SafeTensors, потому что они быстро загружаются и напрямую интегрируются в существующие рабочие процессы. Но если той же команде нужно развернуть модель в TensorRT, ONNX Runtime или на периферийном движке инференса, логичнее экспортировать модель в ONNX.
Практическое использование SafeTensors
Одна из причин, по которой SafeTensors быстро распространился в экосистеме PyTorch, — знакомое API. Вы по-прежнему работаете со словарями состояний и тензорами так же, как обычно.
Сохранение и загрузка тензоров
Базовый рабочий процесс выглядит так же, как при работе со стандартными контрольными точками PyTorch. Пример:
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() записывает тензоры в формат .safetensors, а load_file() загружает их обратно в память.
SafeTensors также поддерживает выборочную загрузку через safe_open(), что полезно для больших контрольных точек, когда вам нужны лишь несколько тензоров.
from safetensors import safe_open
with safe_open("model.safetensors", framework="pt") as f:
weights = f.get_tensor("weights")
print(weights)
Вместо загрузки всей контрольной точки get_tensor() читает только запрошенный тензор.
Конвертация существующих моделей в safetensors
Стандартный шаблон такой:
- Загрузите существующую модель
- Извлеките словарь состояний
- Сохраните его с помощью
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() возвращает веса модели как тензоры, которые SafeTensors может сохранять напрямую.
Если модель уже размещена на Hugging Face Hub, локальный код для конвертации может и не понадобиться. Hugging Face предоставляет встроенную поддержку преобразования контрольных точек для размещённых моделей через интерфейс Hub.
Форматы сериализации: сравнительная таблица
| Возможность | SafeTensors | Pickle (.pkl/.bin/.pt) |
GGUF | ONNX |
|---|---|---|---|---|
| Произвольное выполнение кода | Нет | Да | Нет | Нет |
| Основное назначение | Обучение, дообучение, обмен контрольными точками | Универсальная сериализация Python | Квантованный инференс на периферии/CPU | Кросс-фреймворк-развёртывание |
| Хранит вычислительный граф | Нет | Нет | Нет | Да |
| Загрузка с отображением в память | Да | Нет | Да | Нет |
| Ленивая/частичная загрузка тензоров | Да | Нет | Да | Нет |
| Поддержка фреймворков | PyTorch, TF, JAX, Flax, NumPy | Python (все фреймворки) | llama.cpp, периферийные рантаймы | ONNX Runtime, TensorRT, периферия |
| Поддержка квантизации | Расширяется (FP8, GPTQ, AWQ) | Нет | Да (нативно) | Да |
| Формат по умолчанию на Hugging Face Hub | Да | Нет | Нет | Нет |
SafeTensors в 2026 году: PyTorch Foundation и что дальше
В апреле 2026 года Hugging Face передал SafeTensors в PyTorch Foundation под эгидой Linux Foundation. Теперь проект располагается рядом с PyTorch, vLLM, DeepSpeed и Ray в рамках управления фондом.
Этот шаг означает, что SafeTensors больше не просто проект Hugging Face. Он становится общей инфраструктурой для ML-экосистемы.
В объявлении также намечены направления дальнейшего развития формата.
Загрузка с учётом устройства
Один из ключевых фокусов — загрузка с учётом устройства. Сегодня многие рабочие процессы всё ещё загружают тензоры в память CPU перед переносом на устройства CUDA или ROCm. Этот дополнительный этап увеличивает задержку запуска, особенно в больших распределённых системах.
Мейнтейнеры SafeTensors работают над прямыми путями загрузки на устройство, которые сокращают ненужные копирования через CPU и переносят тензоры сразу на ускорители.
Распределённая загрузка
Поддержка распределённой загрузки тоже развивается. Современные системы инференса редко запускают модели на одном GPU. Тензорный и конвейерный параллелизм стали стандартными паттернами для больших моделей, но API загрузки контрольных точек в разных фреймворках всё ещё фрагментированы.
SafeTensors расширяет поддержку загрузки с учётом шардов и распределённых раскладок тензоров, чтобы фреймворки могли эффективнее координировать загрузку контрольных точек на нескольких устройствах.
Современные рабочие процессы квантизации
Формат также адаптируется к новым рабочим процессам квантизации. Системы инференса всё чаще опираются на форматы FP8, GPTQ и AWQ, чтобы сократить потребление памяти и снизить стоимость сервинга.
Вместо того чтобы заставлять фреймворки обрабатывать это через кастомную логику сериализации, SafeTensors добавляет формальную поддержку низкой точности и блочно-квантованных форматов тензоров прямо в сам формат.
Сейчас разработчикам всё ещё приходится явно выбирать SafeTensors, переключаясь между сценариями сохранения и загрузки. Но ведётся работа по более глубокой интеграции с нативной системой сериализации PyTorch. Если это в итоге произойдёт, SafeTensors может перестать быть альтернативным форматом контрольных точек и стать способом хранения моделей по умолчанию в PyTorch.
Итоги
Много лет разработчики делились контрольными точками моделей с помощью систем сериализации, которые могли выполнять произвольный Python-код при загрузке. Когда публичные хабы моделей начали размещать миллионы контрольных точек, риски для безопасности стало гораздо труднее игнорировать.
SafeTensors изменил ситуацию, сузив область применения формата. Вместо попыток сериализовать целые Python-объекты он фокусируется лишь на хранении тензоров и метаданных, необходимых для их загрузки. Такой более простой дизайн убирает риски десериализации, присущие контрольным точкам на базе pickle, а также улучшает скорость загрузки и эффективность использования памяти.
Поэтому, когда вам нужны только веса модели, нет смысла выполнять произвольный код при десериализации — в таких случаях лучше использовать SafeTensors.
Если вы хотите глубже погрузиться в современные ML-инструменты, форматы моделей и рабочие процессы Hugging Face, наши курсы Deep Learning in Python и Working with Hugging Face — хороший следующий шаг. В них рассматриваются практические рабочие процессы для обучения, дообучения и развёртывания моделей с использованием инструментов, применяемых в современной экосистеме ИИ.
Частые вопросы о SafeTensors
Могу ли я конвертировать существующие модели .bin или .pt в SafeTensors?
Да. Вы можете стандартно загрузить модель в PyTorch или Transformers, извлечь state_dict() и сохранить его с помощью save_file() из библиотеки safetensors. Hugging Face Hub также поддерживает автоматическую конвертацию для многих размещённых моделей.
Может ли SafeTensors хранить квантованные модели?
Да. SafeTensors уже поддерживает несколько типов тензоров пониженной точности, а поддержка форматов, таких как FP8, GPTQ и AWQ, расширяется по мере распространения квантованного инференса.
Могу ли я просмотреть содержимое файла SafeTensors без загрузки всей модели?
Да. Формат хранит метаданные тензоров отдельно в заголовке, поэтому вы можете просмотреть имена тензоров, их формы и типы данных без полной загрузки контрольной точки в память.
Влияет ли использование SafeTensors на точность модели?
Нет. SafeTensors меняет способ хранения и загрузки весов, а не численные значения. Поведение модели после загрузки остаётся прежним.
Полезен ли SafeTensors только для инференса?
Его используют и во время обучения, дообучения, обмена контрольными точками, а также при распределённой загрузке.
