buffered_ggml_writer.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # Copyright (c) Meta Platforms, Inc. and affiliates.
  2. # All rights reserved.
  3. # This source code is licensed under the license found in the
  4. # LICENSE file in the root directory of this source tree.
  5. import struct
  6. from io import BufferedWriter
  7. import torch
  8. from ggml.examples.unity.type_utils import to_ctype
  9. class BufferedGGMLWriter:
  10. buffer: BufferedWriter
  11. def __init__(self, buffer: BufferedWriter) -> None:
  12. self.buffer = buffer
  13. def write_magic_hex(self) -> None:
  14. """Write GGML Magic Number to internal buffer.
  15. This should be called at the start of your convert process.
  16. """
  17. self.buffer.write(struct.pack("i", 0x67676d6c))
  18. def write_hparams(self, hparams: dict) -> None:
  19. """Write hyper parameters to internal buffer.
  20. :params hparams:
  21. flattened dict containing model's hyper parameters.
  22. """
  23. for key in hparams.keys():
  24. try:
  25. value = hparams[key]
  26. ctype, cvalue = to_ctype(value)
  27. self.buffer.write(struct.pack(ctype, cvalue))
  28. except ValueError as e:
  29. # TODO use logger
  30. print(f"[Warning] {e}. Skipping config for key {key}")
  31. continue
  32. def write_state_dict(self, state_dict: dict) -> None:
  33. """Write pytorch state dict to internal buffer.
  34. :paras state_dict:
  35. state dict returned by pytorch model
  36. """
  37. for key, value in state_dict.items():
  38. self.write_string(key)
  39. self.write_tensor(value)
  40. def write_string(self, value: str) -> None:
  41. """Write string in utf-8 format to internal buffer.
  42. :params value:
  43. string value to dump.
  44. """
  45. str_ = value.encode("utf-8")
  46. self.buffer.write(struct.pack("i", len(str_)))
  47. self.buffer.write(str_)
  48. def write_tensor(self, value: torch.Tensor) -> None:
  49. """Write torch tensor in ggml format to internal buffer.
  50. First we save the number of dimensions and the dtype.
  51. Then we save the data as numpy array.
  52. :params value:
  53. Tensor to dump.
  54. """
  55. data = value.squeeze().numpy()
  56. n_dims = len(data.shape)
  57. # TODO: Convert to fp16 when necessary!
  58. ftype = 0
  59. self.buffer.write(struct.pack("ii", n_dims, ftype))
  60. for i in range(n_dims):
  61. self.buffer.write(struct.pack("i", data.shape[n_dims - 1 - i]))
  62. data.tofile(self.buffer)