149 lines
2.7 KiB
Go
149 lines
2.7 KiB
Go
package llm
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"io"
|
|
"slices"
|
|
)
|
|
|
|
type containerGGLA struct {
|
|
version uint32
|
|
}
|
|
|
|
func (c *containerGGLA) Name() string {
|
|
return "ggla"
|
|
}
|
|
|
|
func (c *containerGGLA) Decode(rs io.ReadSeeker) (model, error) {
|
|
if err := binary.Read(rs, binary.LittleEndian, &c.version); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch c.version {
|
|
case 1:
|
|
default:
|
|
return nil, errors.New("invalid version")
|
|
}
|
|
|
|
model := newGGLA(c)
|
|
err := model.decode(rs)
|
|
return model, err
|
|
}
|
|
|
|
type ggla struct {
|
|
*containerGGLA
|
|
|
|
kv KV
|
|
tensors []*Tensor
|
|
|
|
tensorOffset uint64
|
|
}
|
|
|
|
func newGGLA(container *containerGGLA) *ggla {
|
|
return &ggla{
|
|
containerGGLA: container,
|
|
kv: make(KV),
|
|
}
|
|
}
|
|
|
|
func (llm *ggla) KV() KV {
|
|
return llm.kv
|
|
}
|
|
|
|
func (llm *ggla) Tensors() Tensors {
|
|
return Tensors{
|
|
Items: llm.tensors,
|
|
Offset: llm.tensorOffset,
|
|
}
|
|
}
|
|
|
|
func (llm *ggla) decode(rs io.ReadSeeker) (retErr error) {
|
|
var r uint32
|
|
if err := binary.Read(rs, binary.LittleEndian, &r); err != nil {
|
|
return err
|
|
}
|
|
llm.kv["r"] = r
|
|
|
|
var alpha uint32
|
|
if err := binary.Read(rs, binary.LittleEndian, &alpha); err != nil {
|
|
return err
|
|
}
|
|
llm.kv["alpha"] = alpha
|
|
|
|
offset, err := rs.Seek(0, io.SeekCurrent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
llm.tensorOffset = uint64(offset)
|
|
|
|
for {
|
|
var dims uint32
|
|
if err := binary.Read(rs, binary.LittleEndian, &dims); err != nil {
|
|
if errors.Is(err, io.EOF) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
defer func() {
|
|
if errors.Is(retErr, io.EOF) {
|
|
retErr = io.ErrUnexpectedEOF
|
|
}
|
|
}()
|
|
|
|
var namesize uint32
|
|
if err := binary.Read(rs, binary.LittleEndian, &namesize); err != nil {
|
|
return err
|
|
}
|
|
|
|
var t Tensor
|
|
if err := binary.Read(rs, binary.LittleEndian, &t.Kind); err != nil {
|
|
return err
|
|
}
|
|
|
|
t.Shape = make([]uint64, dims)
|
|
for i := 0; uint32(i) < dims; i++ {
|
|
var shape32 uint32
|
|
if err := binary.Read(rs, binary.LittleEndian, &shape32); err != nil {
|
|
return err
|
|
}
|
|
|
|
t.Shape[i] = uint64(shape32)
|
|
}
|
|
|
|
// ggla tensor shape is reversed
|
|
// ref: https://github.com/ggerganov/llama.cpp/blob/29ae62d2ae163e2b68aa0ad3bf2ab4636de0c957/convert-lora-to-ggml.py#L44
|
|
slices.Reverse(t.Shape)
|
|
|
|
name := make([]byte, namesize)
|
|
if err := binary.Read(rs, binary.LittleEndian, &name); err != nil {
|
|
return err
|
|
}
|
|
|
|
t.Name = string(name)
|
|
|
|
offset, err := rs.Seek(0, io.SeekCurrent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := rs.Seek((offset+31)&-32-offset, io.SeekCurrent); err != nil {
|
|
return err
|
|
}
|
|
|
|
offset, err = rs.Seek(0, io.SeekCurrent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
t.Offset = uint64(offset)
|
|
|
|
if _, err := rs.Seek(int64(t.Size()), io.SeekCurrent); err != nil {
|
|
return err
|
|
}
|
|
|
|
llm.tensors = append(llm.tensors, &t)
|
|
}
|
|
}
|