投票AI埋め込みモデルは、柔軟な次元と数量化をサポートし、ベクトルベースのアプリケーションのストレージと検索コストを最適化します。このページでは、これらの機能を使用して高い検索品質を維持しつつコストを削減する方法について説明します。
Google Colas のインタラクティブ チュートリアルで、柔軟な次元と数量化について学びます。
Overview
大規模なリポジトリにわたるコード取得など、大規模なベクトル検索アプリケーションを扱う場合、ストレージと計算のコストが重要になる可能性があります。これらのコストは、次の要因に応じて直線的に増やす。
埋め込み次元: 各ベクトルの次元数
精度:ベクトル内の各数値をエンコードするのに使用されるビット数
これらの要因のいずれかを削減することで、取得品質に大きな影響を与えずにコストを大幅に削減できます。投票AIモデルは、これを実現するための 2 つの補完的な手法をサポートしています。
これらの手法は、次元や量子化された値が削減されても品質を維持するようにモデルを訓練する、Matrishka 学習と量子化対応の訓練によって有効になっています。
Atlaska 埋め込み
マトロール埋め込みは、単一のベクトル内にネストされた異なるサイズの複数の有効な埋め込みを含む特殊なタイプのベクトル埋め込みです。これにより、パフォーマンスとコスト要件の最もバランスが取れた次元を柔軟に選択できます。
最新のステージの埋め込みモデルは、Matryshka 埋め込みを生成し、output_dimension パラメーターを直接サポートします。詳しくは、「 モデルの概要 」を参照してください。
マテリアライズド埋め込みの仕組み
マテリアライズド学習では、1 つの埋め込みにさまざまな長さの埋め込みのネストされたファミリーが含まれます。例、2048 次元の Vyage 埋め込みには、複数の短い長さの有効な埋め込みが含まれています。
最初の 256 次元は有効な 256 次元埋め込みを形成します
最初の 512 次元は有効な 512 次元埋め込みを形成します
最初の 1024 次元は有効な 1024 次元埋め込みを形成します
すべての 2048 次元はフル忠実度埋め込みを形成します
短いバージョンごとに、完全な埋め込みよりも取得の品質は若干低下しますが、必要なストレージと計算リソースは少なくなります。
マトロール埋め込みを切り捨てる方法
先頭の次元サブセットを保持して、MongoDB Atlas 埋め込みを切り捨てます。次の例では、1024 次元ベクトルを 256 次元に切り捨てる方法を示しています。
import voyageai import numpy as np def embd_normalize(v: np.ndarray) -> np.ndarray: # Normalize rows of a 2D array to unit vectors row_norms = np.linalg.norm(v, axis=1, keepdims=True) if np.any(row_norms == 0): raise ValueError("Cannot normalize rows with a norm of zero.") return v / row_norms vo = voyageai.Client() # Generate 1024-dimensional embeddings embd = vo.embed(['Sample text 1', 'Sample text 2'], model='voyage-4-large').embeddings # Truncate to 256 dimensions and normalize short_dim = 256 resized_embd = embd_normalize(np.array(embd)[:, :short_dim]).tolist()
量子化
量子化により、高精度の浮動小数点数が低精度の形式に変換されるため、埋め込みの精度が低下します。このプロセスにより、ストレージとコンピューティングのコストを大幅に削減できると同時に、強力な検索品質を維持できます。
最新の 使用量の埋め込みモデルは、量子化対応の訓練を使用して訓練されているため、量子化されても高い取得品質が維持されます。詳細については、「 モデルの概要 」を参照してください。
注意
ベクトルストレージと検索をサポートする多くのデータベースは、 MongoDBを含む量子化された埋め込みもサポートしています。 MongoDB ベクトル検索での量子化の詳細については、「 ベクトル量子化 」を参照してください。
量化の仕組み
量子化により、各次元を標準の 32 ビット浮動小数点形式よりも少ないビットで表現することで、埋め込みの精度が低下します。次元ごとに 4 バイトを使用する代わりに、量子化された埋め込みは次の値を使用します。
8ビット整数(次元ごとに1 バイト):ストレージを4 x ずつ削減します
バイナリ(次元ごとに1 ビット):ストレージを32 x ずつ削減します
サイズは大幅に縮小されているにもかかわらず、Valage のような量子化対応の訓練されたモデルは高い検索品質を維持します。サポートされている投票モデルでは、output_dtype パラメーターで出力データ型を指定することで量子化が可能になります。
データ型 | 説明 |
|---|---|
| |
| 返される各埋め込みは、それぞれ -128 から 127 まで、および 0 から 255 までの 8 ビット(1 バイト)整数のリストです。 |
| 8返される各埋め込みは、ビット圧縮され、量化された単一ビット埋め込み値を表す |
例
バイナリ量子化の理解
次の埋め込み値について考えてみましょう。
-0.0396, 0.0062, -0.0745, -0.0390, 0.0046, 0.0003, -0.0850, 0.0399 バイナリ量子化では、次のルールを使用して各値を単一のビットに変換します。
0未満の値は0に変換されます0以上の値は1に変換されます
0, 1, 0, 0, 1, 1, 0, 1 8 ビットを 1 つの 8 ビット整数、
01001101に圧縮します。この整数は 10 進数では77に変換されます。最終出力型に変換するには、次の変換を適用します。
出力タイプ変換方法結果ubinaryuint8: 値を符号なし整数として直接使用します。77binaryint8: を減算してオフセット バイナリ128メソッドを適用します。-51(77 - 128に等しい)
オフセット バイナリ
オフセット バイナリは、符号付き整数をバイナリ形式で表現する方法です。投票AI は、 出力タイプにこのメソッドを使用して、ビット圧縮されたバイナリ埋め込みを符号付き整数(binary int8)としてエンコードします。
オフセット バイナリ メソッドは、オフセット値を追加または減算することで機能します。
バイナリに変換する場合:
128エンコードする前に、符号付き整数に を追加しますバイナリから変換する場合:
128デコード後に整数から を減算
8 ビット符号付き整数(範囲 -128 から 127)の場合、オフセットは常に 128 になります。
例
符号付き整数からバイナリへ
-32 を 8 ビットのバイナリ数として表すには、次のようにします。
オフセット(
128)を-32に追加すると、96が得られます。96をバイナリに変換します:01100000。
例
バイナリから符号付き整数へ
8 ビットのバイナリ数 01010101 から符号付き整数を決定するには、次の手順に従います。
整数に直接変換します:
85。85からオフセット(128)を減算すると、-43が得られます。
投票AIでの量化の使用方法
浮動小数埋め込みをバイナリ形式に手動で変換することも、バイナリ埋め込みを個々のビットに解凍して戻すこともできます。次の例は、両方の操作を示しています。
import numpy as np import voyageai vo = voyageai.Client() # Generate float embeddings embd_float = vo.embed('Sample text 1', model='voyage-4-large', output_dimension=2048).embeddings[0] # Compute 512-dimensional bit-packed binary and ubinary embeddings from 2048-dimensional float embeddings embd_binary_calc = (np.packbits(np.array(embd_float) > 0, axis=0) - 128).astype(np.int8).tolist() # Quantize, binary offset embd_binary_512_calc = embd_binary_calc[0:64] # Truncate. Binary is 1/8 length of embedding dimension. embd_ubinary_calc = (np.packbits(np.array(embd_float) > 0, axis=0)).astype(np.uint8).tolist() # Quantize, binary offset embd_ubinary_512_calc = embd_ubinary_calc[0:64] # Truncate. Binary is 1/8 length of embedding dimension.
import numpy as np import voyageai vo = voyageai.Client() # Generate binary embeddings embd_binary = vo.embed('Sample text 1', model='voyage-4-large', output_dtype='binary', output_dimension=2048).embeddings[0] embd_ubinary = vo.embed('Sample text 1', model='voyage-4-large', output_dtype='ubinary', output_dimension=2048).embeddings[0] # Unpack bits embd_binary_bits = [format(x, f'08b') for x in np.array(embd_binary) + 128] # List of (bits) strings embd_binary_unpacked = [bit == '1' for bit in ''.join(embd_binary_bits)] # List of booleans embd_ubinary_bits = [format(x, f'08b') for x in np.array(embd_ubinary)] # List of (bits) strings embd_ubinary_unpacked = [bit == '1' for bit in ''.join(embd_ubinary_bits)] # List of booleans