GGUF is the file format of the ggml tensor library for storing machine learning models, used for example by llama.cpp for inference. It replaced the older GGML, GGMF and GGJT formats.
A GGUF file consists of a header with metadata as key-value pairs (model architecture, hyperparameters, tokenizer, etc.), a description of each tensor (name, dimensions, type and offset), and finally the tensor data.
This page hosts a formal specification of GGUF (GGML Universal File) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All Python code generated by Kaitai Struct depends on the Kaitai Struct runtime library for Python. You must add this dependency to your project before you can parse or serialize any data.
The Python runtime library can be installed from PyPI:
python3 -m pip install kaitaistruct
Parse a local file and get structure in memory:
data = Gguf.from_file("path/to/local/file.gguf")
Or parse structure from a bytes:
from kaitaistruct import KaitaiStream, BytesIO
raw = b"\x00\x01\x02..."
data = Gguf(KaitaiStream(BytesIO(raw)))
After that, one can get various attributes from the structure by invoking getter methods like:
data.magic # => GGUF file magic
data.len_file # => Length of the file (computed from the header), including the padding after
the last tensor's data.
This Kaitai Struct implementation stops parsing where the tensor data
starts (which is read lazily, i.e. only on demand). Without reading the
tensor data, you can use this expected file size to check whether the file
has been truncated, to carve the file out of a larger one, etc.
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
# type: ignore
import kaitaistruct
from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
from enum import IntEnum
if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
class Gguf(KaitaiStruct):
"""GGUF is the file format of the [ggml](https://github.com/ggml-org/ggml)
tensor library for storing machine learning models, used for example by
[llama.cpp](https://github.com/ggml-org/llama.cpp) for inference. It
replaced the older GGML, GGMF and GGJT formats.
A GGUF file consists of a header with metadata as key-value pairs (model
architecture, hyperparameters, tokenizer, etc.), a description of each
tensor (name, dimensions, type and offset), and finally the tensor data.
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md
"""
class GgmlType(IntEnum):
f32 = 0
f16 = 1
q4_0 = 2
q4_1 = 3
q4_2 = 4
q4_3 = 5
q5_0 = 6
q5_1 = 7
q8_0 = 8
q8_1 = 9
q2_k = 10
q3_k = 11
q4_k = 12
q5_k = 13
q6_k = 14
q8_k = 15
iq2_xxs = 16
iq2_xs = 17
iq3_xxs = 18
iq1_s = 19
iq4_nl = 20
iq3_s = 21
iq2_s = 22
iq4_xs = 23
i8 = 24
i16 = 25
i32 = 26
i64 = 27
f64 = 28
iq1_m = 29
bf16 = 30
q4_0_4_4 = 31
q4_0_4_8 = 32
q4_0_8_8 = 33
tq1_0 = 34
tq2_0 = 35
iq4_nl_4_4 = 36
iq4_nl_4_8 = 37
iq4_nl_8_8 = 38
mxfp4 = 39
nvfp4 = 40
q1_0 = 41
q2_0 = 42
class GgufType(IntEnum):
uint8 = 0
int8 = 1
uint16 = 2
int16 = 3
uint32 = 4
int32 = 5
float32 = 6
bool = 7
string = 8
array = 9
uint64 = 10
int64 = 11
float64 = 12
def __init__(self, _io, _parent=None, _root=None):
super(Gguf, self).__init__(_io)
self._parent = _parent
self._root = _root or self
self._read()
def _read(self):
self.magic = self._io.read_bytes(4)
if not self.magic == b"\x47\x47\x55\x46":
raise kaitaistruct.ValidationNotEqualError(b"\x47\x47\x55\x46", self.magic, self._io, u"/seq/0")
self.body = Gguf.GgufBody(self._io, self, self._root)
def _fetch_instances(self):
pass
self.body._fetch_instances()
_ = self.version_le
if hasattr(self, '_m_version_le'):
pass
class GgufBody(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None):
super(Gguf.GgufBody, self).__init__(_io)
self._parent = _parent
self._root = _root
self._read()
def _read(self):
_on = self._root.is_big_endian
if _on == True:
pass
self._is_le = False
elif _on == False:
pass
self._is_le = True
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.version = self._io.read_u4le()
if not self.version >= 2:
raise kaitaistruct.ValidationLessThanError(2, self.version, self._io, u"/types/gguf_body/seq/0")
if not self.version <= 3:
raise kaitaistruct.ValidationGreaterThanError(3, self.version, self._io, u"/types/gguf_body/seq/0")
self.num_tensor_infos = self._io.read_u8le()
self.num_kv_pairs = self._io.read_u8le()
self.kv_pairs = []
for i in range(self.num_kv_pairs):
self.kv_pairs.append(Gguf.GgufBody.GgufKv((self.kv_pairs[i - 1].alignment if i != 0 else 32), self._io, self, self._root, self._is_le))
self.tensor_infos = []
for i in range(self.num_tensor_infos):
self.tensor_infos.append(Gguf.GgufBody.GgufTensorInfo((self.tensor_infos[i - 1].expected_next_offset if i != 0 else 0), self._io, self, self._root, self._is_le))
if self.num_tensor_infos != 0:
pass
self.padding = self._io.read_bytes((self.alignment - self._io.pos() % self.alignment) % self.alignment)
if self.ofs_tensor_data < 0:
pass
self._unnamed6 = self._io.read_bytes(0)
def _read_be(self):
self.version = self._io.read_u4be()
if not self.version >= 2:
raise kaitaistruct.ValidationLessThanError(2, self.version, self._io, u"/types/gguf_body/seq/0")
if not self.version <= 3:
raise kaitaistruct.ValidationGreaterThanError(3, self.version, self._io, u"/types/gguf_body/seq/0")
self.num_tensor_infos = self._io.read_u8be()
self.num_kv_pairs = self._io.read_u8be()
self.kv_pairs = []
for i in range(self.num_kv_pairs):
self.kv_pairs.append(Gguf.GgufBody.GgufKv((self.kv_pairs[i - 1].alignment if i != 0 else 32), self._io, self, self._root, self._is_le))
self.tensor_infos = []
for i in range(self.num_tensor_infos):
self.tensor_infos.append(Gguf.GgufBody.GgufTensorInfo((self.tensor_infos[i - 1].expected_next_offset if i != 0 else 0), self._io, self, self._root, self._is_le))
if self.num_tensor_infos != 0:
pass
self.padding = self._io.read_bytes((self.alignment - self._io.pos() % self.alignment) % self.alignment)
if self.ofs_tensor_data < 0:
pass
self._unnamed6 = self._io.read_bytes(0)
def _fetch_instances(self):
pass
for i in range(len(self.kv_pairs)):
pass
self.kv_pairs[i]._fetch_instances()
for i in range(len(self.tensor_infos)):
pass
self.tensor_infos[i]._fetch_instances()
if self.num_tensor_infos != 0:
pass
if self.ofs_tensor_data < 0:
pass
class GgufArray(KaitaiStruct):
"""Nested arrays are supported. Although ggml (v0.27.0) doesn't support them,
they are explicitly allowed by `gguf.md` - see
<https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L221>.
"""
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufArray, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_array")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.type = KaitaiStream.resolve_enum(Gguf.GgufType, self._io.read_u4le())
if not isinstance(self.type, Gguf.GgufType):
raise kaitaistruct.ValidationNotInEnumError(self.type, self._io, u"/types/gguf_body/types/gguf_array/seq/0")
self.num_elems = self._io.read_u8le()
self.elems = []
for i in range(self.num_elems):
self.elems.append(Gguf.GgufBody.GgufValue(self.type, self._io, self, self._root, self._is_le))
def _read_be(self):
self.type = KaitaiStream.resolve_enum(Gguf.GgufType, self._io.read_u4be())
if not isinstance(self.type, Gguf.GgufType):
raise kaitaistruct.ValidationNotInEnumError(self.type, self._io, u"/types/gguf_body/types/gguf_array/seq/0")
self.num_elems = self._io.read_u8be()
self.elems = []
for i in range(self.num_elems):
self.elems.append(Gguf.GgufBody.GgufValue(self.type, self._io, self, self._root, self._is_le))
def _fetch_instances(self):
pass
for i in range(len(self.elems)):
pass
self.elems[i]._fetch_instances()
class GgufBool(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufBool, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_bool")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value_raw = self._io.read_u1()
if not self.value_raw <= 1:
raise kaitaistruct.ValidationGreaterThanError(1, self.value_raw, self._io, u"/types/gguf_body/types/gguf_bool/seq/0")
def _read_be(self):
self.value_raw = self._io.read_u1()
if not self.value_raw <= 1:
raise kaitaistruct.ValidationGreaterThanError(1, self.value_raw, self._io, u"/types/gguf_body/types/gguf_bool/seq/0")
def _fetch_instances(self):
pass
@property
def value(self):
"""
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L321
"""
if hasattr(self, '_m_value'):
return self._m_value
self._m_value = self.value_raw != 0
return getattr(self, '_m_value', None)
class GgufFloat32(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufFloat32, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_float32")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_f4le()
def _read_be(self):
self.value = self._io.read_f4be()
def _fetch_instances(self):
pass
class GgufFloat64(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufFloat64, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_float64")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_f8le()
def _read_be(self):
self.value = self._io.read_f8be()
def _fetch_instances(self):
pass
class GgufInt16(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufInt16, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_int16")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_s2le()
def _read_be(self):
self.value = self._io.read_s2be()
def _fetch_instances(self):
pass
class GgufInt32(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufInt32, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_int32")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_s4le()
def _read_be(self):
self.value = self._io.read_s4be()
def _fetch_instances(self):
pass
class GgufInt64(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufInt64, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_int64")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_s8le()
def _read_be(self):
self.value = self._io.read_s8be()
def _fetch_instances(self):
pass
class GgufInt8(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufInt8, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_int8")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_s1()
def _read_be(self):
self.value = self._io.read_s1()
def _fetch_instances(self):
pass
class GgufKv(KaitaiStruct):
"""
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L262-L275
"""
def __init__(self, prev_alignment, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufKv, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self.prev_alignment = prev_alignment
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_kv")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.key = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
_ = self.key
if not _.len_value != 0:
raise kaitaistruct.ValidationExprError(self.key, self._io, u"/types/gguf_body/types/gguf_kv/seq/0")
self.type = KaitaiStream.resolve_enum(Gguf.GgufType, self._io.read_u4le())
if not isinstance(self.type, Gguf.GgufType):
raise kaitaistruct.ValidationNotInEnumError(self.type, self._io, u"/types/gguf_body/types/gguf_kv/seq/1")
self.value = Gguf.GgufBody.GgufValue(self.type, self._io, self, self._root, self._is_le)
_ = self.value
if not ( ((self.type == Gguf.GgufType.uint32) and (_.value.value != 0) and (_.value.value & _.value.value - 1 == 0)) if self.key.value == u"general.alignment" else True):
raise kaitaistruct.ValidationExprError(self.value, self._io, u"/types/gguf_body/types/gguf_kv/seq/2")
def _read_be(self):
self.key = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
_ = self.key
if not _.len_value != 0:
raise kaitaistruct.ValidationExprError(self.key, self._io, u"/types/gguf_body/types/gguf_kv/seq/0")
self.type = KaitaiStream.resolve_enum(Gguf.GgufType, self._io.read_u4be())
if not isinstance(self.type, Gguf.GgufType):
raise kaitaistruct.ValidationNotInEnumError(self.type, self._io, u"/types/gguf_body/types/gguf_kv/seq/1")
self.value = Gguf.GgufBody.GgufValue(self.type, self._io, self, self._root, self._is_le)
_ = self.value
if not ( ((self.type == Gguf.GgufType.uint32) and (_.value.value != 0) and (_.value.value & _.value.value - 1 == 0)) if self.key.value == u"general.alignment" else True):
raise kaitaistruct.ValidationExprError(self.value, self._io, u"/types/gguf_body/types/gguf_kv/seq/2")
def _fetch_instances(self):
pass
self.key._fetch_instances()
self.value._fetch_instances()
@property
def alignment(self):
if hasattr(self, '_m_alignment'):
return self._m_alignment
self._m_alignment = (self.value.value.value if self.key.value == u"general.alignment" else self.prev_alignment)
return getattr(self, '_m_alignment', None)
class GgufStr(KaitaiStruct):
"""
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L232-L237
"""
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufStr, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_str")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.len_value = self._io.read_u8le()
self.value = (self._io.read_bytes(self.len_value)).decode(u"UTF-8")
def _read_be(self):
self.len_value = self._io.read_u8be()
self.value = (self._io.read_bytes(self.len_value)).decode(u"UTF-8")
def _fetch_instances(self):
pass
class GgufTensorInfo(KaitaiStruct):
"""
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L305-L325
"""
def __init__(self, expected_offset, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufTensorInfo, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self.expected_offset = expected_offset
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_tensor_info")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.name = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
_ = self.name
if not _.len_value < 64:
raise kaitaistruct.ValidationExprError(self.name, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/0")
self.num_dims = self._io.read_u4le()
if not self.num_dims <= 4:
raise kaitaistruct.ValidationGreaterThanError(4, self.num_dims, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/1")
self.dims = []
for i in range(self.num_dims):
self.dims.append(self._io.read_s8le())
if not self.dims[i] >= 0:
raise kaitaistruct.ValidationLessThanError(0, self.dims[i], self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/2")
self.type = KaitaiStream.resolve_enum(Gguf.GgmlType, self._io.read_u4le())
_ = self.type
if not ((int(_) < 43) and (self.num_elements_per_block != 0) and ((self.dims[0] if self.num_dims > 0 else 1) % self.num_elements_per_block == 0)) :
raise kaitaistruct.ValidationExprError(self.type, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/3")
self.offset = self._io.read_u8le()
if not self.offset == self.expected_offset:
raise kaitaistruct.ValidationNotEqualError(self.expected_offset, self.offset, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/4")
def _read_be(self):
self.name = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
_ = self.name
if not _.len_value < 64:
raise kaitaistruct.ValidationExprError(self.name, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/0")
self.num_dims = self._io.read_u4be()
if not self.num_dims <= 4:
raise kaitaistruct.ValidationGreaterThanError(4, self.num_dims, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/1")
self.dims = []
for i in range(self.num_dims):
self.dims.append(self._io.read_s8be())
if not self.dims[i] >= 0:
raise kaitaistruct.ValidationLessThanError(0, self.dims[i], self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/2")
self.type = KaitaiStream.resolve_enum(Gguf.GgmlType, self._io.read_u4be())
_ = self.type
if not ((int(_) < 43) and (self.num_elements_per_block != 0) and ((self.dims[0] if self.num_dims > 0 else 1) % self.num_elements_per_block == 0)) :
raise kaitaistruct.ValidationExprError(self.type, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/3")
self.offset = self._io.read_u8be()
if not self.offset == self.expected_offset:
raise kaitaistruct.ValidationNotEqualError(self.expected_offset, self.offset, self._io, u"/types/gguf_body/types/gguf_tensor_info/seq/4")
def _fetch_instances(self):
pass
self.name._fetch_instances()
for i in range(len(self.dims)):
pass
_ = self.data
if hasattr(self, '_m_data'):
pass
_ = self.padding
if hasattr(self, '_m_padding'):
pass
@property
def data(self):
if hasattr(self, '_m_data'):
return self._m_data
_pos = self._io.pos()
self._io.seek(self._parent.ofs_tensor_data + self.offset)
if self._is_le:
self._m_data = self._io.read_bytes(self.len_data)
else:
self._m_data = self._io.read_bytes(self.len_data)
self._io.seek(_pos)
return getattr(self, '_m_data', None)
@property
def dump_dims(self):
"""`dims` joined with the string `" x "`. This is necessary for
`-webide-representation`, which cannot format `dims` directly -
see <https://github.com/kaitai-io/kaitai_struct_webide/issues/160>.
"""
if hasattr(self, '_m_dump_dims'):
return self._m_dump_dims
self._m_dump_dims = (((str(self.dims[0]) if self.num_dims > 0 else u"") + (u" x " + str(self.dims[1]) if self.num_dims > 1 else u"")) + (u" x " + str(self.dims[2]) if self.num_dims > 2 else u"")) + (u" x " + str(self.dims[3]) if self.num_dims > 3 else u"")
return getattr(self, '_m_dump_dims', None)
@property
def expected_next_offset(self):
"""`offset` that the next tensor must have."""
if hasattr(self, '_m_expected_next_offset'):
return self._m_expected_next_offset
self._m_expected_next_offset = ((self.offset + self.len_data) + self.len_padding)
return getattr(self, '_m_expected_next_offset', None)
@property
def len_block(self):
"""Size of a block in bytes."""
if hasattr(self, '_m_len_block'):
return self._m_len_block
self._m_len_block = [4, 2, 18, 20, 0, 0, 22, 24, 34, 36, 84, 110, 144, 176, 210, 292, 66, 74, 98, 50, 18, 110, 82, 136, 1, 2, 4, 8, 8, 56, 2, 0, 0, 0, 54, 66, 0, 0, 0, 17, 36, 18, 18][int(self.type)]
return getattr(self, '_m_len_block', None)
@property
def len_data(self):
if hasattr(self, '_m_len_data'):
return self._m_len_data
self._m_len_data = (self.len_block * self.num_blocks)
return getattr(self, '_m_len_data', None)
@property
def len_padding(self):
"""Number of padding bytes after the data."""
if hasattr(self, '_m_len_padding'):
return self._m_len_padding
self._m_len_padding = (self._parent.alignment - self.len_data % self._parent.alignment) % self._parent.alignment
return getattr(self, '_m_len_padding', None)
@property
def num_blocks(self):
if hasattr(self, '_m_num_blocks'):
return self._m_num_blocks
self._m_num_blocks = (self.num_elements // self.num_elements_per_block)
return getattr(self, '_m_num_blocks', None)
@property
def num_elements(self):
if hasattr(self, '_m_num_elements'):
return self._m_num_elements
self._m_num_elements = ((((self.dims[0] if self.num_dims > 0 else 1) * (self.dims[1] if self.num_dims > 1 else 1)) * (self.dims[2] if self.num_dims > 2 else 1)) * (self.dims[3] if self.num_dims > 3 else 1))
return getattr(self, '_m_num_elements', None)
@property
def num_elements_per_block(self):
"""Number of elements in a block."""
if hasattr(self, '_m_num_elements_per_block'):
return self._m_num_elements_per_block
self._m_num_elements_per_block = [1, 1, 32, 32, 0, 0, 32, 32, 32, 32, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 32, 256, 256, 256, 1, 1, 1, 1, 1, 256, 1, 0, 0, 0, 256, 256, 0, 0, 0, 32, 64, 128, 64][int(self.type)]
return getattr(self, '_m_num_elements_per_block', None)
@property
def padding(self):
"""Padding after the data. ggml requires it even after the last tensor
when reading the tensor data.
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L884-L893
"""
if hasattr(self, '_m_padding'):
return self._m_padding
_pos = self._io.pos()
self._io.seek((self._parent.ofs_tensor_data + self.offset) + self.len_data)
if self._is_le:
self._m_padding = self._io.read_bytes(self.len_padding)
else:
self._m_padding = self._io.read_bytes(self.len_padding)
self._io.seek(_pos)
return getattr(self, '_m_padding', None)
class GgufUint16(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufUint16, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_uint16")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_u2le()
def _read_be(self):
self.value = self._io.read_u2be()
def _fetch_instances(self):
pass
class GgufUint32(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufUint32, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_uint32")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_u4le()
def _read_be(self):
self.value = self._io.read_u4be()
def _fetch_instances(self):
pass
class GgufUint64(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufUint64, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_uint64")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_u8le()
def _read_be(self):
self.value = self._io.read_u8be()
def _fetch_instances(self):
pass
class GgufUint8(KaitaiStruct):
def __init__(self, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufUint8, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_uint8")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
self.value = self._io.read_u1()
def _read_be(self):
self.value = self._io.read_u1()
def _fetch_instances(self):
pass
class GgufValue(KaitaiStruct):
"""
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L239-L260
"""
def __init__(self, type, _io, _parent=None, _root=None, _is_le=None):
super(Gguf.GgufBody.GgufValue, self).__init__(_io)
self._parent = _parent
self._root = _root
self._is_le = _is_le
self.type = type
self._read()
def _read(self):
if not hasattr(self, '_is_le'):
raise kaitaistruct.UndecidedEndiannessError("/types/gguf_body/types/gguf_value")
elif self._is_le == True:
self._read_le()
elif self._is_le == False:
self._read_be()
def _read_le(self):
_on = self.type
if _on == Gguf.GgufType.array:
pass
self.value = Gguf.GgufBody.GgufArray(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.bool:
pass
self.value = Gguf.GgufBody.GgufBool(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.float32:
pass
self.value = Gguf.GgufBody.GgufFloat32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.float64:
pass
self.value = Gguf.GgufBody.GgufFloat64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int16:
pass
self.value = Gguf.GgufBody.GgufInt16(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int32:
pass
self.value = Gguf.GgufBody.GgufInt32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int64:
pass
self.value = Gguf.GgufBody.GgufInt64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int8:
pass
self.value = Gguf.GgufBody.GgufInt8(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.string:
pass
self.value = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint16:
pass
self.value = Gguf.GgufBody.GgufUint16(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint32:
pass
self.value = Gguf.GgufBody.GgufUint32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint64:
pass
self.value = Gguf.GgufBody.GgufUint64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint8:
pass
self.value = Gguf.GgufBody.GgufUint8(self._io, self, self._root, self._is_le)
def _read_be(self):
_on = self.type
if _on == Gguf.GgufType.array:
pass
self.value = Gguf.GgufBody.GgufArray(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.bool:
pass
self.value = Gguf.GgufBody.GgufBool(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.float32:
pass
self.value = Gguf.GgufBody.GgufFloat32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.float64:
pass
self.value = Gguf.GgufBody.GgufFloat64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int16:
pass
self.value = Gguf.GgufBody.GgufInt16(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int32:
pass
self.value = Gguf.GgufBody.GgufInt32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int64:
pass
self.value = Gguf.GgufBody.GgufInt64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.int8:
pass
self.value = Gguf.GgufBody.GgufInt8(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.string:
pass
self.value = Gguf.GgufBody.GgufStr(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint16:
pass
self.value = Gguf.GgufBody.GgufUint16(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint32:
pass
self.value = Gguf.GgufBody.GgufUint32(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint64:
pass
self.value = Gguf.GgufBody.GgufUint64(self._io, self, self._root, self._is_le)
elif _on == Gguf.GgufType.uint8:
pass
self.value = Gguf.GgufBody.GgufUint8(self._io, self, self._root, self._is_le)
def _fetch_instances(self):
pass
_on = self.type
if _on == Gguf.GgufType.array:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.bool:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.float32:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.float64:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.int16:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.int32:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.int64:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.int8:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.string:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.uint16:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.uint32:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.uint64:
pass
self.value._fetch_instances()
elif _on == Gguf.GgufType.uint8:
pass
self.value._fetch_instances()
@property
def alignment(self):
"""Global alignment - from the `general.alignment` key, or 32 if there's no
such key.
.. seealso::
Git tag "v0.27.0" - https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L622-L630
"""
if hasattr(self, '_m_alignment'):
return self._m_alignment
self._m_alignment = (self.kv_pairs[-1].alignment if len(self.kv_pairs) != 0 else 32)
return getattr(self, '_m_alignment', None)
@property
def ofs_tensor_data(self):
"""Offset of the tensor data. Each tensor's `offset` is relative to this
position.
"""
if hasattr(self, '_m_ofs_tensor_data'):
return self._m_ofs_tensor_data
self._m_ofs_tensor_data = self._io.pos()
return getattr(self, '_m_ofs_tensor_data', None)
@property
def is_big_endian(self):
if hasattr(self, '_m_is_big_endian'):
return self._m_is_big_endian
self._m_is_big_endian = self.version_le & 65535 == 0
return getattr(self, '_m_is_big_endian', None)
@property
def len_file(self):
"""Length of the file (computed from the header), including the padding after
the last tensor's data.
This Kaitai Struct implementation stops parsing where the tensor data
starts (which is read lazily, i.e. only on demand). Without reading the
tensor data, you can use this expected file size to check whether the file
has been truncated, to carve the file out of a larger one, etc.
"""
if hasattr(self, '_m_len_file'):
return self._m_len_file
self._m_len_file = (self.body.ofs_tensor_data + (self.body.tensor_infos[-1].expected_next_offset if self.body.num_tensor_infos != 0 else 0))
return getattr(self, '_m_len_file', None)
@property
def version_le(self):
if hasattr(self, '_m_version_le'):
return self._m_version_le
_pos = self._io.pos()
self._io.seek(4)
self._m_version_le = self._io.read_u4le()
self._io.seek(_pos)
return getattr(self, '_m_version_le', None)