1+ from __future__ import annotations
12import struct
2- from typing import List , Tuple
3+ from typing import List
34
45
56class VectorQuantizer :
67 @staticmethod
7- def to_int8 (raw_embedding : List [float ]) -> bytes :
8+ def to_int8 (raw_embedding : List [float ]) -> List [ int ] :
89 """
9- Converts a list of floats to a packed byte array of signed 8-bit integers (int8).
10- The maximum absolute value is appended as a 4-byte float at the end.
10+ Converts a list of floats to a list of signed 8-bit integers (int8).
11+ The returned list contains the quantized values followed by the
12+ max_component float encoded as 4 signed bytes.
1113
1214 Args:
1315 raw_embedding (List[float]): List of floating-point numbers to be quantized.
1416
1517 Returns:
16- bytes: Packed byte array containing the quantized int8 values and the max component.
18+ List[int]: List of signed integers (-128 to 127) representing the quantized vector.
19+ Includes both the quantized values and the 4 bytes of the max_component float.
1720 """
1821 if not raw_embedding :
19- return b""
22+ return []
2023
2124 # Find the maximum absolute value in the input array
2225 max_component : float = max (abs (x ) for x in raw_embedding )
@@ -35,21 +38,24 @@ def to_int8(raw_embedding: List[float]) -> bytes:
3538 # Append the max_component as a little-endian float
3639 packed += struct .pack ("<f" , max_component )
3740
38- return packed
41+ # Convert to list of signed integers
42+ return VectorQuantizer ._bytes_to_int8_list (packed )
3943
4044 @staticmethod
41- def to_int1 (raw_embedding : List [float ]) -> bytes :
45+ def to_int1 (raw_embedding : List [float ]) -> List [ int ] :
4246 """
43- Converts a list of floats to a packed byte array of binary values (int1).
44- Each byte represents 8 consecutive float values, where each bit corresponds to
45- whether the float is non-negative (1) or negative (0).
47+ Converts a list of floats to a list of binary values (0 or 1).
48+ Each value in the input is converted to 1 if non-negative, 0 if negative.
4649
4750 Args:
4851 raw_embedding (List[float]): List of floating-point numbers to be quantized.
4952
5053 Returns:
51- bytes: Packed byte array containing the binary-packed values .
54+ List[int]: List of 0s and 1s representing the binary-quantized vector .
5255 """
56+ if not raw_embedding :
57+ return []
58+
5359 # Calculate the number of bytes needed to store the binary-packed values
5460 output_length : int = (len (raw_embedding ) + 7 ) // 8
5561
@@ -63,4 +69,43 @@ def to_int1(raw_embedding: List[float]) -> bytes:
6369 bit_pos : int = 7 - (i % 8 ) # Determine the bit position within the byte
6470 bytes_list [byte_index ] |= 1 << bit_pos # Set the bit to 1 if the value is non-negative
6571
66- return bytes (bytes_list )
72+ # Convert to list of 0s and 1s
73+ return VectorQuantizer ._bytes_to_int1_list (bytes (bytes_list ), len (raw_embedding ))
74+
75+ @staticmethod
76+ def _bytes_to_int8_list (packed_bytes : bytes ) -> List [int ]:
77+ """
78+ Protected method to convert packed bytes to a list of signed int8 values.
79+ Includes all bytes (quantized values + max_component float bytes).
80+
81+ Args:
82+ packed_bytes (bytes): Packed byte array from to_int8().
83+
84+ Returns:
85+ List[int]: List of signed integers (-128 to 127).
86+ """
87+ if not packed_bytes :
88+ return []
89+
90+ # Unpack ALL bytes as signed int8 (including the 4-byte max_component)
91+ return list (struct .unpack ("b" * len (packed_bytes ), packed_bytes ))
92+
93+ @staticmethod
94+ def _bytes_to_int1_list (packed_bytes : bytes , original_length : int ) -> List [int ]:
95+ """
96+ Protected method to convert packed binary bytes to a list of 0s and 1s.
97+
98+ Args:
99+ packed_bytes (bytes): Packed byte array from to_int1().
100+ original_length (int): Original number of float values (to trim padding).
101+
102+ Returns:
103+ List[int]: List of 0s and 1s.
104+ """
105+ result = []
106+ for byte_val in packed_bytes :
107+ for bit_pos in range (7 , - 1 , - 1 ):
108+ result .append (1 if (byte_val & (1 << bit_pos )) else 0 )
109+
110+ # Trim to original length (remove padding bits)
111+ return result [:original_length ]
0 commit comments