gguf.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. package ggml
  2. import (
  3. "bytes"
  4. "cmp"
  5. "encoding/binary"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "log/slog"
  10. "maps"
  11. "slices"
  12. "strings"
  13. )
  14. type containerGGUF struct {
  15. ByteOrder binary.ByteOrder
  16. Version uint32
  17. V1 struct {
  18. NumTensor uint32
  19. NumKV uint32
  20. }
  21. V2 struct {
  22. NumTensor uint64
  23. NumKV uint64
  24. }
  25. V3 struct {
  26. NumTensor uint64
  27. NumKV uint64
  28. }
  29. maxArraySize int
  30. }
  31. func (c *containerGGUF) canCollectArray(size int) bool {
  32. return c.maxArraySize < 0 || size <= c.maxArraySize
  33. }
  34. func (c *containerGGUF) Name() string {
  35. return "gguf"
  36. }
  37. func (c *containerGGUF) Decode(rs io.ReadSeeker) (model, error) {
  38. if err := binary.Read(rs, c.ByteOrder, &c.Version); err != nil {
  39. return nil, err
  40. }
  41. var err error
  42. switch c.Version {
  43. case 1:
  44. err = binary.Read(rs, c.ByteOrder, &c.V1)
  45. case 2:
  46. err = binary.Read(rs, c.ByteOrder, &c.V2)
  47. default:
  48. err = binary.Read(rs, c.ByteOrder, &c.V3)
  49. }
  50. if err != nil {
  51. return nil, err
  52. }
  53. model := newGGUF(c)
  54. if err := model.Decode(rs); err != nil {
  55. return nil, err
  56. }
  57. return model, nil
  58. }
  59. const (
  60. ggufTypeUint8 uint32 = iota
  61. ggufTypeInt8
  62. ggufTypeUint16
  63. ggufTypeInt16
  64. ggufTypeUint32
  65. ggufTypeInt32
  66. ggufTypeFloat32
  67. ggufTypeBool
  68. ggufTypeString
  69. ggufTypeArray
  70. ggufTypeUint64
  71. ggufTypeInt64
  72. ggufTypeFloat64
  73. )
  74. type gguf struct {
  75. *containerGGUF
  76. kv KV
  77. tensors []*Tensor
  78. parameters uint64
  79. tensorOffset uint64
  80. scratch [16 << 10]byte
  81. }
  82. func newGGUF(container *containerGGUF) *gguf {
  83. return &gguf{
  84. containerGGUF: container,
  85. kv: make(KV),
  86. }
  87. }
  88. func (llm *gguf) KV() KV {
  89. return llm.kv
  90. }
  91. func (llm *gguf) Tensors() Tensors {
  92. return Tensors{
  93. items: llm.tensors,
  94. Offset: llm.tensorOffset,
  95. }
  96. }
  97. func (llm *gguf) numTensor() uint64 {
  98. switch llm.Version {
  99. case 1:
  100. return uint64(llm.V1.NumTensor)
  101. case 2:
  102. return llm.V2.NumTensor
  103. default:
  104. return llm.V3.NumTensor
  105. }
  106. }
  107. func (llm *gguf) numKV() uint64 {
  108. switch llm.Version {
  109. case 1:
  110. return uint64(llm.V1.NumKV)
  111. case 2:
  112. return llm.V2.NumKV
  113. default:
  114. return llm.V3.NumKV
  115. }
  116. }
  117. func (llm *gguf) Decode(rs io.ReadSeeker) error {
  118. // decode key-values
  119. for i := 0; uint64(i) < llm.numKV(); i++ {
  120. k, err := readGGUFString(llm, rs)
  121. if err != nil {
  122. return err
  123. }
  124. t, err := readGGUF[uint32](llm, rs)
  125. if err != nil {
  126. return err
  127. }
  128. var v any
  129. switch t {
  130. case ggufTypeUint8:
  131. v, err = readGGUF[uint8](llm, rs)
  132. case ggufTypeInt8:
  133. v, err = readGGUF[int8](llm, rs)
  134. case ggufTypeUint16:
  135. v, err = readGGUF[uint16](llm, rs)
  136. case ggufTypeInt16:
  137. v, err = readGGUF[int16](llm, rs)
  138. case ggufTypeUint32:
  139. v, err = readGGUF[uint32](llm, rs)
  140. case ggufTypeInt32:
  141. v, err = readGGUF[int32](llm, rs)
  142. case ggufTypeUint64:
  143. v, err = readGGUF[uint64](llm, rs)
  144. case ggufTypeInt64:
  145. v, err = readGGUF[int64](llm, rs)
  146. case ggufTypeFloat32:
  147. v, err = readGGUF[float32](llm, rs)
  148. case ggufTypeFloat64:
  149. v, err = readGGUF[float64](llm, rs)
  150. case ggufTypeBool:
  151. v, err = readGGUF[bool](llm, rs)
  152. case ggufTypeString:
  153. v, err = readGGUFString(llm, rs)
  154. case ggufTypeArray:
  155. v, err = readGGUFArray(llm, rs)
  156. default:
  157. return fmt.Errorf("invalid type: %d", t)
  158. }
  159. if err != nil {
  160. return err
  161. }
  162. llm.kv[k] = v
  163. }
  164. // decode tensors
  165. for range llm.numTensor() {
  166. name, err := readGGUFString(llm, rs)
  167. if err != nil {
  168. return fmt.Errorf("failed to read tensor name: %w", err)
  169. }
  170. // dims is the number of dimensions in the tensor
  171. dims, err := readGGUF[uint32](llm, rs)
  172. if err != nil {
  173. return fmt.Errorf("failed to read tensor dimensions: %w", err)
  174. }
  175. shape := make([]uint64, dims)
  176. for i := 0; uint32(i) < dims; i++ {
  177. shape[i], err = readGGUF[uint64](llm, rs)
  178. if err != nil {
  179. return fmt.Errorf("failed to read tensor shape: %w", err)
  180. }
  181. }
  182. kind, err := readGGUF[uint32](llm, rs)
  183. if err != nil {
  184. return fmt.Errorf("failed to read tensor kind: %w", err)
  185. }
  186. offset, err := readGGUF[uint64](llm, rs)
  187. if err != nil {
  188. return fmt.Errorf("failed to read tensor offset: %w", err)
  189. }
  190. tensor := Tensor{
  191. Name: name,
  192. Kind: kind,
  193. Offset: offset,
  194. Shape: shape[:],
  195. }
  196. llm.tensors = append(llm.tensors, &tensor)
  197. llm.parameters += tensor.parameters()
  198. }
  199. // patch KV with parameter count
  200. llm.kv["general.parameter_count"] = llm.parameters
  201. alignment, ok := llm.kv["general.alignment"].(uint32)
  202. if !ok {
  203. alignment = 32
  204. }
  205. offset, err := rs.Seek(0, io.SeekCurrent)
  206. if err != nil {
  207. return err
  208. }
  209. padding := ggufPadding(offset, int64(alignment))
  210. llm.tensorOffset = uint64(offset + padding)
  211. for _, tensor := range llm.tensors {
  212. offset, err := rs.Seek(0, io.SeekCurrent)
  213. if err != nil {
  214. return fmt.Errorf("failed to get current offset: %w", err)
  215. }
  216. padding := ggufPadding(offset, int64(alignment))
  217. if _, err := rs.Seek(padding, io.SeekCurrent); err != nil {
  218. return fmt.Errorf("failed to seek to init padding: %w", err)
  219. }
  220. if _, err := rs.Seek(int64(tensor.Size()), io.SeekCurrent); err != nil {
  221. return fmt.Errorf("failed to seek to tensor: %w", err)
  222. }
  223. }
  224. return nil
  225. }
  226. func readGGUF[T any](llm *gguf, r io.Reader) (T, error) {
  227. var t T
  228. err := binary.Read(r, llm.ByteOrder, &t)
  229. return t, err
  230. }
  231. func writeGGUF[V any](w io.Writer, t uint32, v V) error {
  232. if err := binary.Write(w, binary.LittleEndian, t); err != nil {
  233. return err
  234. }
  235. return binary.Write(w, binary.LittleEndian, v)
  236. }
  237. func readGGUFV1String(llm *gguf, r io.Reader) (string, error) {
  238. var length uint64
  239. if err := binary.Read(r, llm.ByteOrder, &length); err != nil {
  240. return "", err
  241. }
  242. var b bytes.Buffer
  243. if _, err := io.CopyN(&b, r, int64(length)); err != nil {
  244. return "", err
  245. }
  246. // gguf v1 strings are null-terminated
  247. b.Truncate(b.Len() - 1)
  248. return b.String(), nil
  249. }
  250. func discardGGUFString(llm *gguf, r io.Reader) error {
  251. buf := llm.scratch[:8]
  252. _, err := io.ReadFull(r, buf)
  253. if err != nil {
  254. return err
  255. }
  256. size := int(llm.ByteOrder.Uint64(buf))
  257. for size > 0 {
  258. n, err := r.Read(llm.scratch[:min(size, cap(llm.scratch))])
  259. if err != nil {
  260. return err
  261. }
  262. size -= n
  263. }
  264. return nil
  265. }
  266. func readGGUFString(llm *gguf, r io.Reader) (string, error) {
  267. if llm.Version == 1 {
  268. return readGGUFV1String(llm, r)
  269. }
  270. buf := llm.scratch[:8]
  271. _, err := io.ReadFull(r, buf)
  272. if err != nil {
  273. return "", err
  274. }
  275. length := int(llm.ByteOrder.Uint64(buf))
  276. if length > len(llm.scratch) {
  277. buf = make([]byte, length)
  278. } else {
  279. buf = llm.scratch[:length]
  280. }
  281. clear(buf)
  282. _, err = io.ReadFull(r, buf)
  283. if err != nil {
  284. return "", err
  285. }
  286. return string(buf), nil
  287. }
  288. func writeGGUFString(w io.Writer, s string) error {
  289. if err := binary.Write(w, binary.LittleEndian, ggufTypeString); err != nil {
  290. return err
  291. }
  292. if err := binary.Write(w, binary.LittleEndian, uint64(len(s))); err != nil {
  293. return err
  294. }
  295. _, err := io.Copy(w, strings.NewReader(s))
  296. return err
  297. }
  298. type array struct {
  299. size int
  300. values []any
  301. }
  302. func (a *array) MarshalJSON() ([]byte, error) {
  303. return json.Marshal(a.values)
  304. }
  305. func readGGUFV1Array(llm *gguf, r io.Reader) (*array, error) {
  306. t, err := readGGUF[uint32](llm, r)
  307. if err != nil {
  308. return nil, err
  309. }
  310. n, err := readGGUF[uint32](llm, r)
  311. if err != nil {
  312. return nil, err
  313. }
  314. a := &array{size: int(n)}
  315. if llm.canCollectArray(int(n)) {
  316. a.values = make([]any, 0, int(n))
  317. }
  318. for i := range n {
  319. var e any
  320. switch t {
  321. case ggufTypeUint8:
  322. e, err = readGGUF[uint8](llm, r)
  323. case ggufTypeInt8:
  324. e, err = readGGUF[int8](llm, r)
  325. case ggufTypeUint16:
  326. e, err = readGGUF[uint16](llm, r)
  327. case ggufTypeInt16:
  328. e, err = readGGUF[int16](llm, r)
  329. case ggufTypeUint32:
  330. e, err = readGGUF[uint32](llm, r)
  331. case ggufTypeInt32:
  332. e, err = readGGUF[int32](llm, r)
  333. case ggufTypeUint64:
  334. e, err = readGGUF[uint64](llm, r)
  335. case ggufTypeInt64:
  336. e, err = readGGUF[int64](llm, r)
  337. case ggufTypeFloat32:
  338. e, err = readGGUF[float32](llm, r)
  339. case ggufTypeFloat64:
  340. e, err = readGGUF[float64](llm, r)
  341. case ggufTypeBool:
  342. e, err = readGGUF[bool](llm, r)
  343. case ggufTypeString:
  344. e, err = readGGUFV1String(llm, r)
  345. default:
  346. return nil, fmt.Errorf("invalid array type: %d", t)
  347. }
  348. if err != nil {
  349. return nil, err
  350. }
  351. if a.values != nil {
  352. a.values[i] = e
  353. }
  354. }
  355. return a, nil
  356. }
  357. func readGGUFArray(llm *gguf, r io.Reader) (*array, error) {
  358. if llm.Version == 1 {
  359. return readGGUFV1Array(llm, r)
  360. }
  361. t, err := readGGUF[uint32](llm, r)
  362. if err != nil {
  363. return nil, err
  364. }
  365. n, err := readGGUF[uint64](llm, r)
  366. if err != nil {
  367. return nil, err
  368. }
  369. a := &array{size: int(n)}
  370. if llm.canCollectArray(int(n)) {
  371. a.values = make([]any, int(n))
  372. }
  373. for i := range n {
  374. var e any
  375. switch t {
  376. case ggufTypeUint8:
  377. e, err = readGGUF[uint8](llm, r)
  378. case ggufTypeInt8:
  379. e, err = readGGUF[int8](llm, r)
  380. case ggufTypeUint16:
  381. e, err = readGGUF[uint16](llm, r)
  382. case ggufTypeInt16:
  383. e, err = readGGUF[int16](llm, r)
  384. case ggufTypeUint32:
  385. e, err = readGGUF[uint32](llm, r)
  386. case ggufTypeInt32:
  387. e, err = readGGUF[int32](llm, r)
  388. case ggufTypeUint64:
  389. e, err = readGGUF[uint64](llm, r)
  390. case ggufTypeInt64:
  391. e, err = readGGUF[int64](llm, r)
  392. case ggufTypeFloat32:
  393. e, err = readGGUF[float32](llm, r)
  394. case ggufTypeFloat64:
  395. e, err = readGGUF[float64](llm, r)
  396. case ggufTypeBool:
  397. e, err = readGGUF[bool](llm, r)
  398. case ggufTypeString:
  399. if a.values != nil {
  400. e, err = readGGUFString(llm, r)
  401. } else {
  402. err = discardGGUFString(llm, r)
  403. }
  404. default:
  405. return nil, fmt.Errorf("invalid array type: %d", t)
  406. }
  407. if err != nil {
  408. return nil, err
  409. }
  410. if a.values != nil {
  411. a.values[i] = e
  412. }
  413. }
  414. return a, nil
  415. }
  416. // writeGGUFArray writes a slice s of type E to the write with a gguf type of t
  417. func writeGGUFArray[S ~[]E, E any](w io.Writer, t uint32, s S) error {
  418. if err := binary.Write(w, binary.LittleEndian, ggufTypeArray); err != nil {
  419. return err
  420. }
  421. if err := binary.Write(w, binary.LittleEndian, t); err != nil {
  422. return err
  423. }
  424. if err := binary.Write(w, binary.LittleEndian, uint64(len(s))); err != nil {
  425. return err
  426. }
  427. return binary.Write(w, binary.LittleEndian, s)
  428. }
  429. func WriteGGUF(ws io.WriteSeeker, kv KV, ts []Tensor) error {
  430. if err := binary.Write(ws, binary.LittleEndian, []byte("GGUF")); err != nil {
  431. return err
  432. }
  433. if err := binary.Write(ws, binary.LittleEndian, uint32(3)); err != nil {
  434. return err
  435. }
  436. if err := binary.Write(ws, binary.LittleEndian, uint64(len(ts))); err != nil {
  437. return err
  438. }
  439. if err := binary.Write(ws, binary.LittleEndian, uint64(len(kv))); err != nil {
  440. return err
  441. }
  442. keys := slices.Collect(maps.Keys(kv))
  443. slices.Sort(keys)
  444. for _, key := range keys {
  445. if err := ggufWriteKV(ws, key, kv[key]); err != nil {
  446. return err
  447. }
  448. }
  449. slices.SortStableFunc(ts, func(a, b Tensor) int {
  450. if i, j := a.block(), b.block(); i < 0 && j > 0 {
  451. return 1
  452. } else if i > 0 && j < 0 {
  453. return -1
  454. } else {
  455. return cmp.Compare(i, j)
  456. }
  457. })
  458. var s uint64
  459. for _, t := range ts {
  460. t.Offset = s
  461. if err := ggufWriteTensorInfo(ws, t); err != nil {
  462. return err
  463. }
  464. s += t.Size()
  465. }
  466. var alignment int64 = 32
  467. for _, t := range ts {
  468. if err := ggufWriteTensor(ws, t, alignment); err != nil {
  469. return err
  470. }
  471. }
  472. return nil
  473. }
  474. func ggufWriteKV(ws io.WriteSeeker, k string, v any) error {
  475. slog.Debug(k, "type", fmt.Sprintf("%T", v))
  476. if err := binary.Write(ws, binary.LittleEndian, uint64(len(k))); err != nil {
  477. return err
  478. }
  479. if err := binary.Write(ws, binary.LittleEndian, []byte(k)); err != nil {
  480. return err
  481. }
  482. var err error
  483. switch v := v.(type) {
  484. case uint32:
  485. err = writeGGUF(ws, ggufTypeUint32, v)
  486. case float32:
  487. err = writeGGUF(ws, ggufTypeFloat32, v)
  488. case bool:
  489. err = writeGGUF(ws, ggufTypeBool, v)
  490. case string:
  491. err = writeGGUFString(ws, v)
  492. case []int32:
  493. err = writeGGUFArray(ws, ggufTypeInt32, v)
  494. case []uint32:
  495. err = writeGGUFArray(ws, ggufTypeUint32, v)
  496. case []float32:
  497. err = writeGGUFArray(ws, ggufTypeFloat32, v)
  498. case []string:
  499. if err := binary.Write(ws, binary.LittleEndian, ggufTypeArray); err != nil {
  500. return err
  501. }
  502. if err := binary.Write(ws, binary.LittleEndian, ggufTypeString); err != nil {
  503. return err
  504. }
  505. if err := binary.Write(ws, binary.LittleEndian, uint64(len(v))); err != nil {
  506. return err
  507. }
  508. for _, e := range v {
  509. if err := binary.Write(ws, binary.LittleEndian, uint64(len(e))); err != nil {
  510. return err
  511. }
  512. if err := binary.Write(ws, binary.LittleEndian, []byte(e)); err != nil {
  513. return err
  514. }
  515. }
  516. default:
  517. return fmt.Errorf("improper type for '%s'", k)
  518. }
  519. return err
  520. }
  521. func ggufWriteTensorInfo(ws io.WriteSeeker, t Tensor) error {
  522. slog.Debug(t.Name, "kind", t.Kind, "shape", t.Shape, "offset", t.Offset)
  523. if err := binary.Write(ws, binary.LittleEndian, uint64(len(t.Name))); err != nil {
  524. return err
  525. }
  526. if err := binary.Write(ws, binary.LittleEndian, []byte(t.Name)); err != nil {
  527. return err
  528. }
  529. if err := binary.Write(ws, binary.LittleEndian, uint32(len(t.Shape))); err != nil {
  530. return err
  531. }
  532. for i := range len(t.Shape) {
  533. if err := binary.Write(ws, binary.LittleEndian, t.Shape[len(t.Shape)-i-1]); err != nil {
  534. return err
  535. }
  536. }
  537. if err := binary.Write(ws, binary.LittleEndian, t.Kind); err != nil {
  538. return err
  539. }
  540. return binary.Write(ws, binary.LittleEndian, t.Offset)
  541. }
  542. func ggufWriteTensor(ws io.WriteSeeker, t Tensor, alignment int64) error {
  543. offset, err := ws.Seek(0, io.SeekCurrent)
  544. if err != nil {
  545. return err
  546. }
  547. if err := binary.Write(ws, binary.LittleEndian, bytes.Repeat([]byte{0}, int(ggufPadding(offset, alignment)))); err != nil {
  548. return err
  549. }
  550. _, err = t.WriteTo(ws)
  551. return err
  552. }
  553. func ggufPadding(offset, align int64) int64 {
  554. return (align - offset%align) % align
  555. }