flax.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import os
  2. from typing import Dict, Optional, Union
  3. import numpy as np
  4. import jax.numpy as jnp
  5. from jax import Array
  6. from safetensors import numpy, safe_open
  7. def save(tensors: Dict[str, Array], metadata: Optional[Dict[str, str]] = None) -> bytes:
  8. """
  9. Saves a dictionary of tensors into raw bytes in safetensors format.
  10. Args:
  11. tensors (`Dict[str, Array]`):
  12. The incoming tensors. Tensors need to be contiguous and dense.
  13. metadata (`Dict[str, str]`, *optional*, defaults to `None`):
  14. Optional text only metadata you might want to save in your header.
  15. For instance it can be useful to specify more about the underlying
  16. tensors. This is purely informative and does not affect tensor loading.
  17. Returns:
  18. `bytes`: The raw bytes representing the format
  19. Example:
  20. ```python
  21. from safetensors.flax import save
  22. from jax import numpy as jnp
  23. tensors = {"embedding": jnp.zeros((512, 1024)), "attention": jnp.zeros((256, 256))}
  24. byte_data = save(tensors)
  25. ```
  26. """
  27. np_tensors = _jnp2np(tensors)
  28. return numpy.save(np_tensors, metadata=metadata)
  29. def save_file(
  30. tensors: Dict[str, Array],
  31. filename: Union[str, os.PathLike],
  32. metadata: Optional[Dict[str, str]] = None,
  33. ) -> None:
  34. """
  35. Saves a dictionary of tensors into raw bytes in safetensors format.
  36. Args:
  37. tensors (`Dict[str, Array]`):
  38. The incoming tensors. Tensors need to be contiguous and dense.
  39. filename (`str`, or `os.PathLike`)):
  40. The filename we're saving into.
  41. metadata (`Dict[str, str]`, *optional*, defaults to `None`):
  42. Optional text only metadata you might want to save in your header.
  43. For instance it can be useful to specify more about the underlying
  44. tensors. This is purely informative and does not affect tensor loading.
  45. Returns:
  46. `None`
  47. Example:
  48. ```python
  49. from safetensors.flax import save_file
  50. from jax import numpy as jnp
  51. tensors = {"embedding": jnp.zeros((512, 1024)), "attention": jnp.zeros((256, 256))}
  52. save_file(tensors, "model.safetensors")
  53. ```
  54. """
  55. np_tensors = _jnp2np(tensors)
  56. return numpy.save_file(np_tensors, filename, metadata=metadata)
  57. def load(data: bytes) -> Dict[str, Array]:
  58. """
  59. Loads a safetensors file into flax format from pure bytes.
  60. Args:
  61. data (`bytes`):
  62. The content of a safetensors file
  63. Returns:
  64. `Dict[str, Array]`: dictionary that contains name as key, value as `Array` on cpu
  65. Example:
  66. ```python
  67. from safetensors.flax import load
  68. file_path = "./my_folder/bert.safetensors"
  69. with open(file_path, "rb") as f:
  70. data = f.read()
  71. loaded = load(data)
  72. ```
  73. """
  74. flat = numpy.load(data)
  75. return _np2jnp(flat)
  76. def load_file(filename: Union[str, os.PathLike]) -> Dict[str, Array]:
  77. """
  78. Loads a safetensors file into flax format.
  79. Args:
  80. filename (`str`, or `os.PathLike`)):
  81. The name of the file which contains the tensors
  82. Returns:
  83. `Dict[str, Array]`: dictionary that contains name as key, value as `Array`
  84. Example:
  85. ```python
  86. from safetensors.flax import load_file
  87. file_path = "./my_folder/bert.safetensors"
  88. loaded = load_file(file_path)
  89. ```
  90. """
  91. result = {}
  92. with safe_open(filename, framework="flax") as f:
  93. for k in f.offset_keys():
  94. result[k] = f.get_tensor(k)
  95. return result
  96. def _np2jnp(numpy_dict: Dict[str, np.ndarray]) -> Dict[str, Array]:
  97. for k, v in numpy_dict.items():
  98. numpy_dict[k] = jnp.array(v)
  99. return numpy_dict
  100. def _jnp2np(jnp_dict: Dict[str, Array]) -> Dict[str, np.array]:
  101. for k, v in jnp_dict.items():
  102. jnp_dict[k] = np.asarray(v)
  103. return jnp_dict