safetensors 0.7.0__pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
safetensors/torch.py ADDED
@@ -0,0 +1,550 @@
1
+ import os
2
+ import sys
3
+ from collections import defaultdict
4
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union
5
+ from packaging.version import Version
6
+
7
+ import torch
8
+
9
+ from safetensors import deserialize, safe_open, serialize, serialize_file
10
+
11
+
12
+ def storage_ptr(tensor: torch.Tensor) -> int:
13
+ try:
14
+ return tensor.untyped_storage().data_ptr()
15
+ except Exception:
16
+ # Fallback for torch==1.10
17
+ try:
18
+ return tensor.storage().data_ptr()
19
+ except NotImplementedError:
20
+ # Fallback for meta storage
21
+ return 0
22
+
23
+
24
+ def _end_ptr(tensor: torch.Tensor) -> int:
25
+ if tensor.nelement():
26
+ stop = tensor.view(-1)[-1].data_ptr() + _SIZE[tensor.dtype]
27
+ else:
28
+ stop = tensor.data_ptr()
29
+ return stop
30
+
31
+
32
+ def storage_size(tensor: torch.Tensor) -> int:
33
+ try:
34
+ return tensor.untyped_storage().nbytes()
35
+ except AttributeError:
36
+ # Fallback for torch==1.10
37
+ try:
38
+ return tensor.storage().size() * _SIZE[tensor.dtype]
39
+ except NotImplementedError:
40
+ # Fallback for meta storage
41
+ # On torch >=2.0 this is the tensor size
42
+ return tensor.nelement() * _SIZE[tensor.dtype]
43
+
44
+
45
+ def _filter_shared_not_shared(
46
+ tensors: List[Set[str]], state_dict: Dict[str, torch.Tensor]
47
+ ) -> List[Set[str]]:
48
+ filtered_tensors = []
49
+ for shared in tensors:
50
+ if len(shared) < 2:
51
+ filtered_tensors.append(shared)
52
+ continue
53
+
54
+ areas = []
55
+ for name in shared:
56
+ tensor = state_dict[name]
57
+ areas.append((tensor.data_ptr(), _end_ptr(tensor), name))
58
+ areas.sort()
59
+
60
+ _, last_stop, last_name = areas[0]
61
+ filtered_tensors.append({last_name})
62
+ for start, stop, name in areas[1:]:
63
+ if start >= last_stop:
64
+ filtered_tensors.append({name})
65
+ else:
66
+ filtered_tensors[-1].add(name)
67
+ last_stop = stop
68
+
69
+ return filtered_tensors
70
+
71
+
72
+ def _find_shared_tensors(state_dict: Dict[str, torch.Tensor]) -> List[Set[str]]:
73
+ tensors = defaultdict(set)
74
+ for k, v in state_dict.items():
75
+ if (
76
+ v.device != torch.device("meta")
77
+ and storage_ptr(v) != 0
78
+ and storage_size(v) != 0
79
+ ):
80
+ # Need to add device as key because of multiple GPU.
81
+ tensors[(v.device, storage_ptr(v), storage_size(v))].add(k)
82
+ tensors = list(sorted(tensors.values()))
83
+ tensors = _filter_shared_not_shared(tensors, state_dict)
84
+ return tensors
85
+
86
+
87
+ def _is_complete(tensor: torch.Tensor) -> bool:
88
+ return tensor.data_ptr() == storage_ptr(tensor) and tensor.nelement() * _SIZE[
89
+ tensor.dtype
90
+ ] == storage_size(tensor)
91
+
92
+
93
+ def _remove_duplicate_names(
94
+ state_dict: Dict[str, torch.Tensor],
95
+ *,
96
+ preferred_names: Optional[List[str]] = None,
97
+ discard_names: Optional[List[str]] = None,
98
+ ) -> Dict[str, List[str]]:
99
+ if preferred_names is None:
100
+ preferred_names = []
101
+ preferred_names = set(preferred_names)
102
+ if discard_names is None:
103
+ discard_names = []
104
+ discard_names = set(discard_names)
105
+
106
+ shareds = _find_shared_tensors(state_dict)
107
+ to_remove = defaultdict(list)
108
+ for shared in shareds:
109
+ complete_names = set(
110
+ [name for name in shared if _is_complete(state_dict[name])]
111
+ )
112
+ if not complete_names:
113
+ raise RuntimeError(
114
+ "Error while trying to find names to remove to save state dict, but found no suitable name to keep"
115
+ f" for saving amongst: {shared}. None is covering the entire storage.Refusing to save/load the model"
116
+ " since you could be storing much more memory than needed. Please refer to"
117
+ " https://huggingface.co/docs/safetensors/torch_shared_tensors for more information. Or open an"
118
+ " issue."
119
+ )
120
+
121
+ keep_name = sorted(list(complete_names))[0]
122
+
123
+ # Mechanism to preferentially select keys to keep
124
+ # coming from the on-disk file to allow
125
+ # loading models saved with a different choice
126
+ # of keep_name
127
+ preferred = complete_names.difference(discard_names)
128
+ if preferred:
129
+ keep_name = sorted(list(preferred))[0]
130
+
131
+ if preferred_names:
132
+ preferred = preferred_names.intersection(complete_names)
133
+ if preferred:
134
+ keep_name = sorted(list(preferred))[0]
135
+ for name in sorted(shared):
136
+ if name != keep_name:
137
+ to_remove[keep_name].append(name)
138
+ return to_remove
139
+
140
+
141
+ def save_model(
142
+ model: torch.nn.Module,
143
+ filename: str,
144
+ metadata: Optional[Dict[str, str]] = None,
145
+ force_contiguous: bool = True,
146
+ ):
147
+ """
148
+ Saves a given torch model to specified filename.
149
+ This method exists specifically to avoid tensor sharing issues which are
150
+ not allowed in `safetensors`. [More information on tensor sharing](../torch_shared_tensors)
151
+
152
+ Args:
153
+ model (`torch.nn.Module`):
154
+ The model to save on disk.
155
+ filename (`str`):
156
+ The filename location to save the file
157
+ metadata (`Dict[str, str]`, *optional*):
158
+ Extra information to save along with the file.
159
+ Some metadata will be added for each dropped tensors.
160
+ This information will not be enough to recover the entire
161
+ shared structure but might help understanding things
162
+ force_contiguous (`boolean`, *optional*, defaults to True):
163
+ Forcing the state_dict to be saved as contiguous tensors.
164
+ This has no effect on the correctness of the model, but it
165
+ could potentially change performance if the layout of the tensor
166
+ was chosen specifically for that reason.
167
+ """
168
+ state_dict = model.state_dict()
169
+ to_removes = _remove_duplicate_names(state_dict)
170
+
171
+ for kept_name, to_remove_group in to_removes.items():
172
+ for to_remove in to_remove_group:
173
+ if metadata is None:
174
+ metadata = {}
175
+
176
+ if to_remove not in metadata:
177
+ # Do not override user data
178
+ metadata[to_remove] = kept_name
179
+ del state_dict[to_remove]
180
+ if force_contiguous:
181
+ state_dict = {k: v.contiguous() for k, v in state_dict.items()}
182
+ try:
183
+ save_file(state_dict, filename, metadata=metadata)
184
+ except ValueError as e:
185
+ msg = str(e)
186
+ msg += " Or use save_model(..., force_contiguous=True), read the docs for potential caveats."
187
+ raise ValueError(msg)
188
+
189
+
190
+ def load_model(
191
+ model: torch.nn.Module,
192
+ filename: Union[str, os.PathLike],
193
+ strict: bool = True,
194
+ device: Union[str, int] = "cpu",
195
+ ) -> Tuple[List[str], List[str]]:
196
+ """
197
+ Loads a given filename onto a torch model.
198
+ This method exists specifically to avoid tensor sharing issues which are
199
+ not allowed in `safetensors`. [More information on tensor sharing](../torch_shared_tensors)
200
+
201
+ Args:
202
+ model (`torch.nn.Module`):
203
+ The model to load onto.
204
+ filename (`str`, or `os.PathLike`):
205
+ The filename location to load the file from.
206
+ strict (`bool`, *optional*, defaults to True):
207
+ Whether to fail if you're missing keys or having unexpected ones.
208
+ When false, the function simply returns missing and unexpected names.
209
+ device (`Union[str, int]`, *optional*, defaults to `cpu`):
210
+ The device where the tensors need to be located after load.
211
+ available options are all regular torch device locations.
212
+
213
+ Returns:
214
+ `(missing, unexpected): (List[str], List[str])`
215
+ `missing` are names in the model which were not modified during loading
216
+ `unexpected` are names that are on the file, but weren't used during
217
+ the load.
218
+ """
219
+ state_dict = load_file(filename, device=device)
220
+ model_state_dict = model.state_dict()
221
+ to_removes = _remove_duplicate_names(
222
+ model_state_dict, preferred_names=state_dict.keys()
223
+ )
224
+ missing, unexpected = model.load_state_dict(state_dict, strict=False)
225
+ missing = set(missing)
226
+ for to_remove_group in to_removes.values():
227
+ for to_remove in to_remove_group:
228
+ if to_remove not in missing:
229
+ unexpected.append(to_remove)
230
+ else:
231
+ missing.remove(to_remove)
232
+ if strict and (missing or unexpected):
233
+ missing_keys = ", ".join([f'"{k}"' for k in sorted(missing)])
234
+ unexpected_keys = ", ".join([f'"{k}"' for k in sorted(unexpected)])
235
+ error = f"Error(s) in loading state_dict for {model.__class__.__name__}:"
236
+ if missing:
237
+ error += f"\n Missing key(s) in state_dict: {missing_keys}"
238
+ if unexpected:
239
+ error += f"\n Unexpected key(s) in state_dict: {unexpected_keys}"
240
+ raise RuntimeError(error)
241
+ return missing, unexpected
242
+
243
+
244
+ def save(
245
+ tensors: Dict[str, torch.Tensor], metadata: Optional[Dict[str, str]] = None
246
+ ) -> bytes:
247
+ """
248
+ Saves a dictionary of tensors into raw bytes in safetensors format.
249
+
250
+ Args:
251
+ tensors (`Dict[str, torch.Tensor]`):
252
+ The incoming tensors. Tensors need to be contiguous and dense.
253
+ metadata (`Dict[str, str]`, *optional*, defaults to `None`):
254
+ Optional text only metadata you might want to save in your header.
255
+ For instance it can be useful to specify more about the underlying
256
+ tensors. This is purely informative and does not affect tensor loading.
257
+
258
+ Returns:
259
+ `bytes`: The raw bytes representing the format
260
+
261
+ Example:
262
+
263
+ ```python
264
+ from safetensors.torch import save
265
+ import torch
266
+
267
+ tensors = {"embedding": torch.zeros((512, 1024)), "attention": torch.zeros((256, 256))}
268
+ byte_data = save(tensors)
269
+ ```
270
+ """
271
+ serialized = serialize(_flatten(tensors), metadata=metadata)
272
+ result = bytes(serialized)
273
+ return result
274
+
275
+
276
+ def save_file(
277
+ tensors: Dict[str, torch.Tensor],
278
+ filename: Union[str, os.PathLike],
279
+ metadata: Optional[Dict[str, str]] = None,
280
+ ):
281
+ """
282
+ Saves a dictionary of tensors into raw bytes in safetensors format.
283
+
284
+ Args:
285
+ tensors (`Dict[str, torch.Tensor]`):
286
+ The incoming tensors. Tensors need to be contiguous and dense.
287
+ filename (`str`, or `os.PathLike`)):
288
+ The filename we're saving into.
289
+ metadata (`Dict[str, str]`, *optional*, defaults to `None`):
290
+ Optional text only metadata you might want to save in your header.
291
+ For instance it can be useful to specify more about the underlying
292
+ tensors. This is purely informative and does not affect tensor loading.
293
+
294
+ Returns:
295
+ `None`
296
+
297
+ Example:
298
+
299
+ ```python
300
+ from safetensors.torch import save_file
301
+ import torch
302
+
303
+ tensors = {"embedding": torch.zeros((512, 1024)), "attention": torch.zeros((256, 256))}
304
+ save_file(tensors, "model.safetensors")
305
+ ```
306
+ """
307
+ serialize_file(_flatten(tensors), filename, metadata=metadata)
308
+
309
+
310
+ def load_file(
311
+ filename: Union[str, os.PathLike], device: Union[str, int] = "cpu"
312
+ ) -> Dict[str, torch.Tensor]:
313
+ """
314
+ Loads a safetensors file into torch format.
315
+
316
+ Args:
317
+ filename (`str`, or `os.PathLike`):
318
+ The name of the file which contains the tensors
319
+ device (`Union[str, int]`, *optional*, defaults to `cpu`):
320
+ The device where the tensors need to be located after load.
321
+ available options are all regular torch device locations.
322
+
323
+ Returns:
324
+ `Dict[str, torch.Tensor]`: dictionary that contains name as key, value as `torch.Tensor`
325
+
326
+ Example:
327
+
328
+ ```python
329
+ from safetensors.torch import load_file
330
+
331
+ file_path = "./my_folder/bert.safetensors"
332
+ loaded = load_file(file_path)
333
+ ```
334
+ """
335
+ result = {}
336
+ with safe_open(filename, framework="pt", device=device) as f:
337
+ for k in f.offset_keys():
338
+ result[k] = f.get_tensor(k)
339
+ return result
340
+
341
+
342
+ def load(data: bytes) -> Dict[str, torch.Tensor]:
343
+ """
344
+ Loads a safetensors file into torch format from pure bytes.
345
+
346
+ Args:
347
+ data (`bytes`):
348
+ The content of a safetensors file
349
+
350
+ Returns:
351
+ `Dict[str, torch.Tensor]`: dictionary that contains name as key, value as `torch.Tensor` on cpu
352
+
353
+ Example:
354
+
355
+ ```python
356
+ from safetensors.torch import load
357
+
358
+ file_path = "./my_folder/bert.safetensors"
359
+ with open(file_path, "rb") as f:
360
+ data = f.read()
361
+
362
+ loaded = load(data)
363
+ ```
364
+ """
365
+ flat = deserialize(data)
366
+ return _view2torch(flat)
367
+
368
+
369
+ # torch.float8 formats require 2.1; we do not support these dtypes on earlier versions
370
+ _float8_e4m3fn = getattr(torch, "float8_e4m3fn", None)
371
+ _float8_e5m2 = getattr(torch, "float8_e5m2", None)
372
+ _float8_e8m0 = getattr(torch, "float8_e8m0fnu", None)
373
+ _float4_e2m1_x2 = getattr(torch, "float4_e2m1fn_x2", None)
374
+
375
+ _SIZE = {
376
+ torch.int64: 8,
377
+ torch.float32: 4,
378
+ torch.int32: 4,
379
+ torch.bfloat16: 2,
380
+ torch.float16: 2,
381
+ torch.int16: 2,
382
+ torch.uint8: 1,
383
+ torch.int8: 1,
384
+ torch.bool: 1,
385
+ torch.float64: 8,
386
+ torch.complex64: 8,
387
+ _float8_e4m3fn: 1,
388
+ _float8_e5m2: 1,
389
+ _float8_e8m0: 1,
390
+ _float4_e2m1_x2: 1,
391
+ }
392
+ if Version(torch.__version__) >= Version("2.3.0"):
393
+ _SIZE.update(
394
+ {
395
+ torch.uint64: 8,
396
+ torch.uint32: 4,
397
+ torch.uint16: 2,
398
+ }
399
+ )
400
+
401
+ _TYPES = {
402
+ "F64": torch.float64,
403
+ "F32": torch.float32,
404
+ "F16": torch.float16,
405
+ "BF16": torch.bfloat16,
406
+ "I64": torch.int64,
407
+ "I32": torch.int32,
408
+ "I16": torch.int16,
409
+ "I8": torch.int8,
410
+ "U8": torch.uint8,
411
+ "BOOL": torch.bool,
412
+ "F8_E4M3": _float8_e4m3fn,
413
+ "F8_E5M2": _float8_e5m2,
414
+ "C64": torch.complex64,
415
+ }
416
+ if Version(torch.__version__) >= Version("2.3.0"):
417
+ _TYPES.update(
418
+ {
419
+ "U64": torch.uint64,
420
+ "U32": torch.uint32,
421
+ "U16": torch.uint16,
422
+ }
423
+ )
424
+
425
+
426
+ def _getdtype(dtype_str: str) -> torch.dtype:
427
+ return _TYPES[dtype_str]
428
+
429
+
430
+ def _view2torch(safeview) -> Dict[str, torch.Tensor]:
431
+ result = {}
432
+ for k, v in safeview:
433
+ dtype = _getdtype(v["dtype"])
434
+ if len(v["data"]) == 0:
435
+ # Workaround because frombuffer doesn't accept zero-size tensors
436
+ assert any(x == 0 for x in v["shape"])
437
+ arr = torch.empty(v["shape"], dtype=dtype)
438
+ else:
439
+ arr = torch.frombuffer(v["data"], dtype=dtype).reshape(v["shape"])
440
+ if sys.byteorder == "big":
441
+ arr = torch.from_numpy(arr.numpy().byteswap(inplace=False))
442
+ result[k] = arr
443
+
444
+ return result
445
+
446
+
447
+ def _tobytes(tensor: torch.Tensor, name: str) -> bytes:
448
+ if tensor.layout != torch.strided:
449
+ raise ValueError(
450
+ f"You are trying to save a sparse tensor: `{name}` which this library does not support."
451
+ " You can make it a dense tensor before saving with `.to_dense()` but be aware this might"
452
+ " make a much larger file than needed."
453
+ )
454
+
455
+ if not tensor.is_contiguous():
456
+ raise ValueError(
457
+ f"You are trying to save a non contiguous tensor: `{name}` which is not allowed. It either means you"
458
+ " are trying to save tensors which are reference of each other in which case it's recommended to save"
459
+ " only the full tensors, and reslice at load time, or simply call `.contiguous()` on your tensor to"
460
+ " pack it before saving."
461
+ )
462
+ if tensor.device.type != "cpu":
463
+ # Moving tensor to cpu before saving
464
+ tensor = tensor.to("cpu")
465
+
466
+ import ctypes
467
+
468
+ import numpy as np
469
+
470
+ # When shape is empty (scalar), np.prod returns a float
471
+ # we need a int for the following calculations
472
+ length = int(np.prod(tensor.shape).item())
473
+ bytes_per_item = _SIZE[tensor.dtype]
474
+
475
+ total_bytes = length * bytes_per_item
476
+
477
+ ptr = tensor.data_ptr()
478
+ if ptr == 0:
479
+ return b""
480
+ newptr = ctypes.cast(ptr, ctypes.POINTER(ctypes.c_ubyte))
481
+ data = np.ctypeslib.as_array(newptr, (total_bytes,)) # no internal copy
482
+ if sys.byteorder == "big":
483
+ NPDTYPES = {
484
+ torch.int64: np.int64,
485
+ torch.float32: np.float32,
486
+ torch.int32: np.int32,
487
+ # XXX: This is ok because both have the same width
488
+ torch.bfloat16: np.float16,
489
+ torch.float16: np.float16,
490
+ torch.int16: np.int16,
491
+ torch.uint8: np.uint8,
492
+ torch.int8: np.int8,
493
+ torch.bool: bool,
494
+ torch.float64: np.float64,
495
+ # XXX: This is ok because both have the same width and byteswap is a no-op anyway
496
+ _float8_e4m3fn: np.uint8,
497
+ _float8_e5m2: np.uint8,
498
+ torch.complex64: np.complex64,
499
+ }
500
+ npdtype = NPDTYPES[tensor.dtype]
501
+ # Not in place as that would potentially modify a live running model
502
+ data = data.view(npdtype).byteswap(inplace=False)
503
+ return data.tobytes()
504
+
505
+
506
+ def _flatten(tensors: Dict[str, torch.Tensor]) -> Dict[str, Dict[str, Any]]:
507
+ if not isinstance(tensors, dict):
508
+ raise ValueError(
509
+ f"Expected a dict of [str, torch.Tensor] but received {type(tensors)}"
510
+ )
511
+
512
+ invalid_tensors = []
513
+ for k, v in tensors.items():
514
+ if not isinstance(v, torch.Tensor):
515
+ raise ValueError(
516
+ f"Key `{k}` is invalid, expected torch.Tensor but received {type(v)}"
517
+ )
518
+
519
+ if v.layout != torch.strided:
520
+ invalid_tensors.append(k)
521
+ if invalid_tensors:
522
+ raise ValueError(
523
+ f"You are trying to save a sparse tensors: `{invalid_tensors}` which this library does not support."
524
+ " You can make it a dense tensor before saving with `.to_dense()` but be aware this might"
525
+ " make a much larger file than needed."
526
+ )
527
+
528
+ shared_pointers = _find_shared_tensors(tensors)
529
+ failing = []
530
+ for names in shared_pointers:
531
+ if len(names) > 1:
532
+ failing.append(names)
533
+
534
+ if failing:
535
+ raise RuntimeError(
536
+ f"""
537
+ Some tensors share memory, this will lead to duplicate memory on disk and potential differences when loading them again: {failing}.
538
+ A potential way to correctly save your model is to use `save_model`.
539
+ More information at https://huggingface.co/docs/safetensors/torch_shared_tensors
540
+ """
541
+ )
542
+
543
+ return {
544
+ k: {
545
+ "dtype": str(v.dtype).split(".")[-1],
546
+ "shape": v.shape,
547
+ "data": _tobytes(v, k),
548
+ }
549
+ for k, v in tensors.items()
550
+ }
@@ -0,0 +1,133 @@
1
+ Metadata-Version: 2.4
2
+ Name: safetensors
3
+ Version: 0.7.0
4
+ Classifier: Development Status :: 5 - Production/Stable
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: Intended Audience :: Education
7
+ Classifier: Intended Audience :: Science/Research
8
+ Classifier: License :: OSI Approved :: Apache Software License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Typing :: Typed
17
+ Requires-Dist: numpy>=1.21.6 ; extra == 'numpy'
18
+ Requires-Dist: packaging ; extra == 'torch'
19
+ Requires-Dist: safetensors[numpy] ; extra == 'torch'
20
+ Requires-Dist: torch>=1.10 ; extra == 'torch'
21
+ Requires-Dist: safetensors[numpy] ; extra == 'tensorflow'
22
+ Requires-Dist: tensorflow>=2.11.0 ; extra == 'tensorflow'
23
+ Requires-Dist: safetensors[numpy] ; extra == 'pinned-tf'
24
+ Requires-Dist: tensorflow==2.18.0 ; extra == 'pinned-tf'
25
+ Requires-Dist: safetensors[numpy] ; extra == 'jax'
26
+ Requires-Dist: flax>=0.6.3 ; extra == 'jax'
27
+ Requires-Dist: jax>=0.3.25 ; extra == 'jax'
28
+ Requires-Dist: jaxlib>=0.3.25 ; extra == 'jax'
29
+ Requires-Dist: mlx>=0.0.9 ; extra == 'mlx'
30
+ Requires-Dist: safetensors[numpy] ; extra == 'paddlepaddle'
31
+ Requires-Dist: paddlepaddle>=2.4.1 ; extra == 'paddlepaddle'
32
+ Requires-Dist: ruff ; extra == 'quality'
33
+ Requires-Dist: safetensors[numpy] ; extra == 'testing'
34
+ Requires-Dist: h5py>=3.7.0 ; extra == 'testing'
35
+ Requires-Dist: huggingface-hub>=0.12.1 ; extra == 'testing'
36
+ Requires-Dist: setuptools-rust>=1.5.2 ; extra == 'testing'
37
+ Requires-Dist: pytest>=7.2.0 ; extra == 'testing'
38
+ Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'testing'
39
+ Requires-Dist: hypothesis>=6.70.2 ; extra == 'testing'
40
+ Requires-Dist: safetensors[numpy] ; extra == 'testingfree'
41
+ Requires-Dist: huggingface-hub>=0.12.1 ; extra == 'testingfree'
42
+ Requires-Dist: setuptools-rust>=1.5.2 ; extra == 'testingfree'
43
+ Requires-Dist: pytest>=7.2.0 ; extra == 'testingfree'
44
+ Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'testingfree'
45
+ Requires-Dist: hypothesis>=6.70.2 ; extra == 'testingfree'
46
+ Requires-Dist: safetensors[torch] ; extra == 'all'
47
+ Requires-Dist: safetensors[numpy] ; extra == 'all'
48
+ Requires-Dist: safetensors[pinned-tf] ; extra == 'all'
49
+ Requires-Dist: safetensors[jax] ; extra == 'all'
50
+ Requires-Dist: safetensors[paddlepaddle] ; extra == 'all'
51
+ Requires-Dist: safetensors[quality] ; extra == 'all'
52
+ Requires-Dist: safetensors[testing] ; extra == 'all'
53
+ Requires-Dist: safetensors[all] ; extra == 'dev'
54
+ Provides-Extra: numpy
55
+ Provides-Extra: torch
56
+ Provides-Extra: tensorflow
57
+ Provides-Extra: pinned-tf
58
+ Provides-Extra: jax
59
+ Provides-Extra: mlx
60
+ Provides-Extra: paddlepaddle
61
+ Provides-Extra: quality
62
+ Provides-Extra: testing
63
+ Provides-Extra: testingfree
64
+ Provides-Extra: all
65
+ Provides-Extra: dev
66
+ License-File: LICENSE
67
+ Author-email: Nicolas Patry <patry.nicolas@protonmail.com>
68
+ Requires-Python: >=3.9
69
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
70
+ Project-URL: Homepage, https://github.com/huggingface/safetensors
71
+ Project-URL: Source, https://github.com/huggingface/safetensors
72
+
73
+ ## Installation
74
+
75
+ ```
76
+ pip install safetensors
77
+ ```
78
+
79
+
80
+ ## Usage
81
+
82
+ ### Numpy
83
+
84
+ ```python
85
+ from safetensors.numpy import save_file, load_file
86
+ import numpy as np
87
+
88
+ tensors = {
89
+ "a": np.zeros((2, 2)),
90
+ "b": np.zeros((2, 3), dtype=np.uint8)
91
+ }
92
+
93
+ save_file(tensors, "./model.safetensors")
94
+
95
+
96
+ # Now loading
97
+ loaded = load_file("./model.safetensors")
98
+ ```
99
+
100
+ ### Torch
101
+
102
+ ```python
103
+ from safetensors.torch import save_file, load_file
104
+ import torch
105
+
106
+ tensors = {
107
+ "a": torch.zeros((2, 2)),
108
+ "b": torch.zeros((2, 3), dtype=torch.uint8)
109
+ }
110
+
111
+ save_file(tensors, "./model.safetensors")
112
+
113
+
114
+ # Now loading
115
+ loaded = load_file("./model.safetensors")
116
+ ```
117
+
118
+ ### Developing
119
+
120
+ ```
121
+ # inside ./safetensors/bindings/python
122
+ pip install .[dev]
123
+ ```
124
+ Should be enough to install this library locally.
125
+
126
+ ### Testing
127
+
128
+ ```
129
+ # inside ./safetensors/bindings/python
130
+ pip install .[dev]
131
+ pytest -sv tests/
132
+ ```
133
+
@@ -0,0 +1,14 @@
1
+ safetensors-0.7.0.dist-info/METADATA,sha256=aAkyb78XRE3VIKsZ8KVbehhHbb5SpDBGa79TiZZ8Kqo,4125
2
+ safetensors-0.7.0.dist-info/WHEEL,sha256=3F5VznDq_Vi0CKqJxZ1jyFKUwn3JTkRfUKdIM_SAO4k,163
3
+ safetensors-0.7.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
4
+ safetensors/__init__.py,sha256=wbzKZlAVgnAsjHmqryuSJCiADvpDZxNGCfj8VzY0At0,194
5
+ safetensors/__init__.pyi,sha256=IpwsrzRWJA2yR8TxMEC3RHgM_5TiDgSFqyvrAxAa15U,4019
6
+ safetensors/_safetensors_rust.pypy310-pp73-aarch64-linux-gnu.so,sha256=ZlAijaE70EHVCLTEnXwBKYKEkDf8i8pD-sOry8sP1lY,1201536
7
+ safetensors/flax.py,sha256=T59elUqzVDyGYGdR78QzNEuwyAc8KrEO0EuLBSKOnUs,3853
8
+ safetensors/mlx.py,sha256=IR51jRpcJq6epb0Agj8VsxI9xqBS6NjeAJnr-Ny0jJU,3850
9
+ safetensors/numpy.py,sha256=rit_12-IfZtRgip_VLd8nPAcCXyeM2fPrCDZ7OiyxSY,5028
10
+ safetensors/paddle.py,sha256=LrDwqQbwFnQXiY3M601IU7G6FBctX6tyHHK3_UH6lxE,8721
11
+ safetensors/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ safetensors/tensorflow.py,sha256=AZ-O7-gM-JqTfjczZyCUAHm3Er-GSQnQWaFyY7mAIQc,3903
13
+ safetensors/torch.py,sha256=U0acZVahLsxvqPa1GitMRiaByu6XVbmiBITGtuznBEY,18610
14
+ safetensors-0.7.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: pp310-pypy310_pp73-manylinux_2_17_aarch64
5
+ Tag: pp310-pypy310_pp73-manylinux2014_aarch64