LoginSignup
1
0

象使いのための pgvector 入門 (3) 0.6.0 〜 0.7.0 追加機能について

Last updated at Posted at 2024-05-19

2023 年末の Advent Calendar の時期に、

の 2 本の記事を書きましたが、そこから半年が経過する間に追加された機能があるので、まとめてみました。

といいつつ中身はほぼ README からの抜粋です。

0.6.0 の追加機能

パラレル処理による HNSW インデックス作成の高速化

README の Index Build Time にあるように、CPU コアの数が多い環境で、処理の並列化により HNSW インデックス作成を高速化できるようになりました。

SET max_parallel_maintenance_workers = 【並列処理に使うワーカー数(デフォルト:2)】;で並列数を指定することができます。

max_parallel_maintenance_workersの数を増やすときは、パラレルワーカー自体の数(max_parallel_workers:デフォルトは8)の数も調整する必要があるかも知れません。

Supabase のブログ記事 に 0.5.x との比較がまとめられています。

0.7.0 の追加機能

主に、ベクトル計算やインデックス作成の負荷低減に有効な機能が追加されています。

こちらも、Supabase のブログ記事にまとめられています。

半精度ベクトル・半精度インデックス

これまでは 32 ビット(4 バイト)浮動小数点数によるベクトルデータをサポートしていましたが、16 ビット(2 バイト)浮動小数点数によるベクトルデータおよびインデックスもサポートしました。

READMEの例①テーブル定義
CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
READMEの例②インデックス
CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops);

次元あたりの容量が半減した分、インデックス作成可能な次元数が倍増しました(最大 4,000 次元)。

バイナリ(ビット)ベクトルおよびバイナリ量子化・バイナリインデックス

半精度だけではなくバイナリ(ビット)ベクトルおよびバイナリ量子化・バイナリインデックスもサポートしました。

READMEの例①テーブル定義とデータ投入
CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
INSERT INTO items (embedding) VALUES ('000'), ('111');

2 進表現の文字列でデータを投入するようです。

READMEの例②近傍探索
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;

近傍探索するときは、ハミング距離(<~>)またはジャッカード距離(ジャッカード類似度・<%>)を使います。

READMEの例③バイナリ量子化によるインデックス作成
CREATE INDEX ON items USING hnsw ((binary_quantize(embedding)::bit(3)) bit_hamming_ops);

こちらはハミング距離用のインデックス作成例です。

次元あたりの容量が減少した分、インデックス作成可能な次元数が増加しました(最大 64,000 次元)。

また、Cohere Embed のような、API でバイナリベクトルの出力をサポートしている埋め込みモデルを使わなくても、このバイナリ量子化関数を使って 32 ビットのベクトルからバイナリベクトルを生成することができます。

READMEの例④バイナリ量子化を使った Re-rank
SELECT * FROM (
    SELECT * FROM items ORDER BY binary_quantize(embedding)::bit(3) <~> binary_quantize('[1,-2,3]') LIMIT 20
) ORDER BY embedding <=> '[1,-2,3]' LIMIT 5;

最初にバイナリ量子化ベクトル(インデックス)による近傍探索によって 20 件の候補に絞り込んでおき、その中から 32 ビットのベクトルによって上位 5 件に絞り込むやり方です。

一定の精度は確保しつつ、ベクトルの距離比較の計算負荷を下げる手法ですね。


2024/5/24 追記:
Zenn に追加の記事を書きました。


疎ベクトル

0 が多く含まれるベクトルを扱う際に、疎ベクトルの機能(表現)を使うことで記憶容量の削減が可能になりました。

前述の Supabase のブログ記事を参照してください。

READMEの例:テーブル定義とデータ投入
CREATE TABLE items (id bigserial PRIMARY KEY, embedding sparsevec(5));
INSERT INTO items (embedding) VALUES ('{1:1,3:2,5:3}/5'), ('{1:4,3:5,5:6}/5');

サブベクトルのインデックス化

元のベクトルからサブベクトルを抽出してインデックスを作成することで、インデックス作成および検索時の計算負荷を低減できるようになりました。

READMEの例①サブベクトルインデックス(HNSW)作成
CREATE INDEX ON items USING hnsw ((subvector(embedding, 1, 3)::vector(3)) vector_cosine_ops);
READMEの例②サブベクトルインデックスを使った近傍探索
SELECT * FROM items ORDER BY subvector(embedding, 1, 3)::vector(3) <=> subvector('[1,2,3,4,5]'::vector, 1, 3) LIMIT 5;
READMEの例③サブベクトルインデックスを使った Re-rank
SELECT * FROM (
    SELECT * FROM items ORDER BY subvector(embedding, 1, 3)::vector(3) <=> subvector('[1,2,3,4,5]'::vector, 1, 3) LIMIT 20
) ORDER BY embedding <=> '[1,2,3,4,5]' LIMIT 5;

バイナリインデックスを使った Re-rank と同様のことができます。

その他

L1 距離(マンハッタン距離・<+>)による比較もサポートされました。

ベクトルデータの精度(タイプ)別に使用可能な関数などが README の Reference にまとめられています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0