|
@@ -1,7 +1,7 @@
|
|
|
package convert
|
|
|
|
|
|
import (
|
|
|
- "encoding/binary"
|
|
|
+ "cmp"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"io"
|
|
@@ -10,10 +10,8 @@ import (
|
|
|
"regexp"
|
|
|
"strings"
|
|
|
|
|
|
- "github.com/nlpodyssey/gopickle/pytorch"
|
|
|
"github.com/pdevine/tensor"
|
|
|
"github.com/pdevine/tensor/native"
|
|
|
- "github.com/x448/float16"
|
|
|
|
|
|
"github.com/ollama/ollama/llm"
|
|
|
)
|
|
@@ -22,83 +20,6 @@ type LlamaModel struct {
|
|
|
ModelData
|
|
|
}
|
|
|
|
|
|
-func llamaTorchLayerHandler(w io.Writer, r torchWriterTo) error {
|
|
|
-
|
|
|
- var tData []uint16
|
|
|
- switch r.storage.(type) {
|
|
|
- case *pytorch.HalfStorage:
|
|
|
- data := r.storage.(*pytorch.HalfStorage).Data
|
|
|
- tData = make([]uint16, len(data))
|
|
|
- for cnt, v := range data {
|
|
|
- tData[cnt] = uint16(float16.Fromfloat32(v))
|
|
|
- }
|
|
|
- case *pytorch.BFloat16Storage:
|
|
|
- data := r.storage.(*pytorch.BFloat16Storage).Data
|
|
|
- tData = make([]uint16, len(data))
|
|
|
-
|
|
|
- for cnt, v := range data {
|
|
|
- tData[cnt] = uint16(float16.Fromfloat32(v))
|
|
|
- }
|
|
|
- default:
|
|
|
- return fmt.Errorf("unknown storage type for torch")
|
|
|
- }
|
|
|
-
|
|
|
- var err error
|
|
|
- var heads uint32
|
|
|
- if strings.Contains(r.t.Name, "attn_q") {
|
|
|
- heads = uint32(r.params.AttentionHeads)
|
|
|
- } else if strings.Contains(r.t.Name, "attn_k") {
|
|
|
- heads = uint32(r.params.KeyValHeads)
|
|
|
- if heads == 0 {
|
|
|
- heads = uint32(r.params.AttentionHeads)
|
|
|
- }
|
|
|
- } else {
|
|
|
- return fmt.Errorf("unknown layer type")
|
|
|
- }
|
|
|
-
|
|
|
- tData, err = llamaRepack(tData, int(heads), r.t.Shape)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- if err = binary.Write(w, r.bo, tData); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func llamaRepack(data []uint16, heads int, shape []uint64) ([]uint16, error) {
|
|
|
- n := tensor.New(tensor.WithShape(int(shape[0]), int(shape[1])), tensor.WithBacking(data))
|
|
|
- origShape := n.Shape().Clone()
|
|
|
-
|
|
|
- // reshape the tensor and swap axes 1 and 2 to unpack the layer for gguf
|
|
|
- if err := n.Reshape(heads, 2, origShape[0]/heads/2, origShape[1]); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if err := n.T(0, 2, 1, 3); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if err := n.Reshape(origShape...); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if err := n.Transpose(); err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- newN, err := native.SelectU16(n, 1)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- var fullTensor []uint16
|
|
|
- for _, v := range newN {
|
|
|
- fullTensor = append(fullTensor, v...)
|
|
|
- }
|
|
|
- return fullTensor, nil
|
|
|
-}
|
|
|
-
|
|
|
func (m *LlamaModel) GetTensors() error {
|
|
|
t, err := m.Format.GetTensors(m.Path, m.Params)
|
|
|
if err != nil {
|
|
@@ -117,11 +38,11 @@ func (m *LlamaModel) GetTensors() error {
|
|
|
switch m.Format.(type) {
|
|
|
case *TorchFormat:
|
|
|
wt := l.WriterTo.(torchWriterTo)
|
|
|
- wt.handler = llamaTorchLayerHandler
|
|
|
+ wt.repacker = m.Repack
|
|
|
l.WriterTo = wt
|
|
|
case *SafetensorFormat:
|
|
|
wt := l.WriterTo.(safetensorWriterTo)
|
|
|
- wt.handler = mistralLayerHandler
|
|
|
+ wt.repacker = m.Repack
|
|
|
l.WriterTo = wt
|
|
|
}
|
|
|
}
|
|
@@ -184,3 +105,54 @@ func (m *LlamaModel) WriteGGUF(ws io.WriteSeeker) error {
|
|
|
|
|
|
return llm.NewGGUFV3(m.Params.ByteOrder).Encode(ws, kv, m.Tensors)
|
|
|
}
|
|
|
+
|
|
|
+func (m *LlamaModel) Repack(name string, data []float32, shape []uint64) ([]float32, error) {
|
|
|
+ return llamaRepack(name, m.Params, data, shape)
|
|
|
+}
|
|
|
+
|
|
|
+func llamaRepack(name string, params *Params, data []float32, shape []uint64) ([]float32, error) {
|
|
|
+ var dims []int
|
|
|
+ for _, dim := range shape {
|
|
|
+ if dim != 0 {
|
|
|
+ dims = append(dims, int(dim))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var heads int
|
|
|
+ if strings.HasSuffix(name, "attn_q.weight") {
|
|
|
+ heads = params.AttentionHeads
|
|
|
+ } else if strings.HasSuffix(name, "attn_k.weight") {
|
|
|
+ heads = cmp.Or(params.KeyValHeads, params.AttentionHeads)
|
|
|
+ } else {
|
|
|
+ return nil, fmt.Errorf("unknown tensor name: %s", name)
|
|
|
+ }
|
|
|
+
|
|
|
+ n := tensor.New(tensor.WithShape(dims...), tensor.WithBacking(data))
|
|
|
+ if err := n.Reshape(append([]int{heads, 2, dims[0] / heads / 2}, dims[1:]...)...); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := n.T(0, 2, 1, 3); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := n.Reshape(dims...); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := n.Transpose(); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ ts, err := native.SelectF32(n, 1)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ var f32s []float32
|
|
|
+ for _, t := range ts {
|
|
|
+ f32s = append(f32s, t...)
|
|
|
+ }
|
|
|
+
|
|
|
+ return f32s, nil
|
|
|
+}
|