Convert a ggml tensor to a numpy array. If the tensor isn't quantized, the returned numpy array will be a view over its data. If it is quantized (and allow_copy is True), the copy will involve dequantization and the returned array will be a copy of the original tensor
(tensor: ffi.CData, allow_copy: Union[bool, np.ndarray] = False, allow_requantize=False)
| 51 | __set_floats(to_tensor, __get_floats(from_tensor)) |
| 52 | |
| 53 | def numpy(tensor: ffi.CData, allow_copy: Union[bool, np.ndarray] = False, allow_requantize=False) -> np.ndarray: |
| 54 | """ |
| 55 | Convert a ggml tensor to a numpy array. |
| 56 | If the tensor isn't quantized, the returned numpy array will be a view over its data. |
| 57 | |
| 58 | If it is quantized (and allow_copy is True), the copy will involve dequantization and the returned array will |
| 59 | be a copy of the original tensor (any changes to the numpy array won't then be reflected back to the tensor). |
| 60 | |
| 61 | Parameters |
| 62 | ---------- |
| 63 | tensor : ffi.CData |
| 64 | The tensor to convert to a numpy array |
| 65 | allow_copy : bool or np.ndarray |
| 66 | If False, will throw an error if the tensor is quantized (since dequantization requires extra memory). |
| 67 | If True, will dequantize the tensor and return a copy of the data in a new float32 numpy array. |
| 68 | If an np.ndarray, will copy the data into the given array (which must be the same shape as the tensor) when dequantization is needed |
| 69 | allow_requantize : bool |
| 70 | If allow_copy is a tensor with a different quantization type than the source tensor, will throw an error unless allow_requantize is True. |
| 71 | """ |
| 72 | shape = __get_shape(tensor) |
| 73 | |
| 74 | if lib.ggml_is_quantized(tensor.type): |
| 75 | if allow_copy == False: |
| 76 | raise ValueError(f"{__describe(tensor)} is quantized, conversion to numpy requires a copy (pass allow_copy=True; changes to the numpy array won't affect the original).") |
| 77 | elif isinstance(allow_copy, np.ndarray): |
| 78 | __expect_same_layout("source tensor", tensor, "dequantization output tensor", allow_copy) |
| 79 | destination = allow_copy |
| 80 | else: |
| 81 | destination = np.empty(shape, dtype=np.float32) |
| 82 | |
| 83 | copy(tensor, destination, allow_requantize=allow_requantize) |
| 84 | return destination |
| 85 | else: |
| 86 | dtype = __type_to_dtype(tensor.type) |
| 87 | if not dtype: |
| 88 | raise NotImplementedError(f'Cannot convert {__describe(tensor)} to numpy') |
| 89 | |
| 90 | assert __is_contiguous(tensor), f"Cannot convert {__describe(tensor)} to numpy (support contiguous tensors only)" |
| 91 | nbytes = lib.ggml_nelements(tensor) * lib.ggml_type_size(tensor.type) |
| 92 | array = np.frombuffer(ffi.buffer(lib.ggml_get_data(tensor), nbytes), dtype=dtype) |
| 93 | array.shape = shape |
| 94 | return array |
| 95 | |
| 96 | def __type_name(type: int) -> str: |
| 97 | name = lib.ggml_type_name(type) |