Containers · .safetensors

safetensors

Hugging Face's safe, mmap-friendly tensor container. An 8-byte little-endian header length N, an N-byte UTF-8 JSON header mapping tensor names to {dtype, shape, data_offsets}, plus an optional "__metadata__" string->string map, then one contiguous byte buffer. Tensors are dense, little-endian, C-order, with no strides. Loading cannot execute code. It is the default format for HF Transformers / Diffusers checkpoints; large models are sharded with a JSON index file.

.safetensors

What it is
many tensors
Byte order
little
Dimension order
row major
Compression
none
Metadata
string map
Loading
Loading it into a library does not execute code.

How to read it

[N: u64 LE][header: N bytes UTF-8 JSON, space padded][byte buffer]. File size = 8 + N + buffer length.

N
u64le. header length in bytes
header
utf8[N]. JSON Header object, optionally followed by 0x20 padding
buffer
bytes[*]. tensor bytes back to back, in data_offsets order, without gaps
0        8                    8+N                                    EOF
+--------+--------------------+--------------------------------------+
| N u64  | {"__metadata__":..,| t0 bytes | t1 bytes | ... | tk bytes |
|   LE   |  "t0":{...},...}   |                                      |
|        |  + ' ' padding     |  offsets are relative to byte 8+N    |
+--------+--------------------+--------------------------------------+

One tensor

name
header key
dtype
TensorInfo.dtype -> dtypes[].canonical
shape
TensorInfo.shape (already row-major, outermost first)
data_offset
8 + N + data_offsets[0] (absolute in file)
nbytes
data_offsets[1] - data_offsets[0]
order
always C
strides
implicit C-contiguous

Example

The specs test vector. The header is one JSON object. The header below is spaced for reading; the file pads that JSON with spaces out to a multiple of 8.

small.safetensors1,464 bytes

NameDtypeShapeBytes
s_f32F32float32[]4
w_f32F32float324 × 641,024
i_i32I32int323 × 224
e_bf16BF16bfloat162 × 312
b_f16F16float16816

Header

{
  "__metadata__": {
    "source": "tensor-format-specs test vector"
  },
  "s_f32": {
    "dtype": "F32",
    "shape": [],
    "data_offsets": [
      0,
      4
    ]
  },
  "w_f32": {
    "dtype": "F32",
    "shape": [
      4,
      64
    ],
    "data_offsets": [
      4,
      1028
    ]
  },
  "i_i32": {
    "dtype": "I32",
    "shape": [
      3,
      2
    ],
    "data_offsets": [
      1028,
      1052
    ]
  },
  "e_bf16": {
    "dtype": "BF16",
    "shape": [
      2,
      3
    ],
    "data_offsets": [
      1052,
      1064
    ]
  },
  "b_f16": {
    "dtype": "F16",
    "shape": [
      8
    ],
    "data_offsets": [
      1064,
      1080
    ]
  }
}

Number formats

The name in the file, and the canonical dtype it maps to.

In the fileCanonicalBits
BOOLbool8
F4float4_e2m1fn4
F6_E2M3float6_e2m3fn6
F6_E3M2float6_e3m2fn6
U8uint88
I8int88
F8_E5M2float8_e5m28
F8_E4M3float8_e4m3fn8
F8_E8M0float8_e8m0fnu8
F8_E4M3FNUZfloat8_e4m3fnuz8
F8_E5M2FNUZfloat8_e5m2fnuz8
I16int1616
U16uint1616
F16float1616
BF16bfloat1616
I32int3232
U32uint3232
F32float3232
C64complex6464
F64float6464
I64int6464
U64uint6464

Sources

Nick Reynolds · @goldnode · nicks.net · rev 0.1