До появления safetensors веса моделей раздавали в формате PyTorch — файлах .pt и .bin, построенных на механизме сериализации Python под названием pickle. У этого механизма есть свойство, о котором знали давно: распаковка pickle-файла может выполнить произвольный код. Не «в теории при уязвимости», а по устройству: формат умеет описывать вызовы функций, и загрузчик их выполняет.
То есть скачивание чужого файла с весами было равносильно запуску чужой программы.
#Что сделали вместо
Safetensors устроен нарочито скучно. Файл состоит из двух частей:
- Заголовок в JSON — список тензоров: имя, тип чисел, форма, смещение и длина в байтах.
- Сплошной блок чисел — собственно веса.
Всё. Загрузка — это разбор JSON и чтение байтов по смещениям. Выполнять там нечего, потому что описания вызовов в формате не предусмотрено.
Побочная выгода оказалась не менее важной: раз данные лежат сплошным блоком с известными смещениями, файл можно отобразить в память вместо полного чтения. Загрузка крупной модели ускоряется, а память не дублируется.
| Формат | Выполняет код при загрузке | Квантизация | Где встречается |
|---|---|---|---|
.pt / .bin (pickle) |
да | нет | старые репозитории, чекпоинты обучения |
.safetensors |
нет | нет (обычно 16 бит) | современные репозитории весов |
.gguf |
нет | да, десятки схем | локальный запуск через llama.cpp |
Из таблицы видно разделение труда: safetensors — формат исходных весов для дообучения и конвертации, GGUF — формат для локального запуска со сжатием. Разбор второго — в справке про формат GGUF, сравнение с универсальным форматом обмена — в справке про ONNX.
#Где путают
Заблуждение первое, главное: safetensors защищает модель. Не модель, а вас в момент загрузки файла. Он гарантирует, что чтение весов не превратится в исполнение кода. Что именно эти веса делают, когда модель уже запущена, формат не контролирует никак.
Заблуждение второе: safetensors — это шифрование. Ничего не зашифровано: заголовок читается текстовым редактором, веса лежат открыто. Формат про безопасность загрузки, а не про конфиденциальность содержимого.
Заблуждение третье: раз формат безопасный, модель можно скачивать откуда угодно. В весах может быть заложено нежелательное поведение — обученное, а не внедрённое кодом. Никакая проверка формата этого не поймает. Смотрите на автора репозитория и на карточку модели; что в ней должно быть — в справке про карточку модели.
Заблуждение четвёртое: в репозитории всё равно, какой файл брать. Не всё равно. Если рядом лежат и .bin, и .safetensors, берите второй. Современные загрузчики предпочитают его сами, но старые скрипты и старые примеры кода — нет.
#Частые вопросы
#Как понять, что репозиторий раздаёт safetensors?
По списку файлов: у крупной модели это model-00001-of-0000N.safetensors плюс индексный JSON, у небольшой — один model.safetensors. Что ещё лежит рядом и зачем — в справке про веса модели и Hugging Face.
#Можно ли конвертировать pickle-веса в safetensors?
Можно, конвертер стандартный. Но обратите внимание на порядок действий: чтобы сконвертировать, файл придётся сначала загрузить — то есть выполнить ровно ту операцию, из-за которой формат и небезопасен. Конвертировать имеет смысл свои файлы или проверенные, а не случайные из сети.
#Safetensors медленнее из-за проверок?
Наоборот, обычно быстрее: отображение в память вместо разбора сериализованной структуры. Разница особенно заметна на моделях в десятки гигабайт.
#Есть ли разница в качестве модели между форматами?
Нет. Это разные способы записать одни и те же числа. Качество меняет квантизация, а не контейнер — что именно она делает, разобрано в разборе конвертации в GGUF и запуска в Ollama.
Остальные термины — в глоссарии терминов ИИ.