1.8K Views
August 23, 24
スライド概要
第 48 回 PostgreSQL アンカンファレンス@オンライン 2024/8/29
Qiita や Zenn でいろいろ書いてます。 https://qiita.com/hmatsu47 https://zenn.dev/hmatsu47 MySQL 8.0 の薄い本 : https://github.com/hmatsu47/mysql80_no_usui_hon Aurora MySQL v1 → v3 移行計画 : https://zenn.dev/hmatsu47/books/aurora-mysql3-plan-book
pgvectorscale と pgai の話(ざっくり) 第 48 回 PostgreSQL アンカンファレンス@オンライン 2024/8/29 まつひさ(hmatsu47)
自己紹介 松久裕保(@hmatsu47) ● https://qiita.com/hmatsu47 ● 現在のステータス: ○ 名古屋で Web インフラのお守り係をしています ○ #pgunconf ゆるふわ勢 ○ 先月に引き続き発表参加です 2
本日のネタ(1/2) ● 新たに 2 つの(不人気)記事の内容を取り上げます ○ pgvectorscale を少しだけ試してみた(失敗編) https://zenn.dev/hmatsu47/articles/pgvectorscale ○ pgai を軽く試してみた https://zenn.dev/hmatsu47/articles/pgai-tried-a-little 3
本日のネタ(2/2) ● これです→ 4
まずは…ベクトル検索(ざっくり)おさらい ● 意味的に近いものを探すために使う(セマンティック検索) ○ 全文検索:文字列・単語そのものを探す(転置インデックスを使う) ■ 同義語・類義語を検索する場合は辞書が必要 ○ ベクトル検索:文章をベクトル化してベクトルの「近さ」を比較 ■ ベクトル(多次元)が「近い」ほど意味的に近い ● ベクトル化には LLM の埋め込み用モデル(など)を使う ○ マルチモーダルのモデルを使うと画像なども検索可能に 5
pgvector(ざっくり)おさらい ● PostgreSQL をベクトル対応にする extension ○ ベクトル型 ■ 32 ビット浮動小数点数(など)・多次元 ○ ベクトル関数・オペレーター ■ ベクトル間の距離(類似度)を計算(コサイン類似度・L1/L2 距離など) ○ ベクトルインデックス ■ ベクトル間の距離が「近い」データを素早く探索(IVFFlat・HNSW) 6
pgvector 0.7.0(ざっくり)おさらい ● 半精度・バイナリ(ビット)ベクトルに対応 ○ 16 ビット浮動小数点数と 1 ビットのベクトルに対応 ■ (それぞれ)インデックスも対応 ○ バイナリ量子化とバイナリ向けのベクトル関数に対応 ● 疎ベクトルとサブベクトルインデックス化にも対応 →データ容量(特にインデックス)の削減による検索の高速化を意図 7
pgvector 0.7.0 の弱点(1/4) ● HNSW インデックス作成時の性能問題 ○ ワークメモリ(maintenance_work_mem)から溢れると急激に劣化 出典 : https://www.pinecone.io/blog/pinecone-vs-pgvector/ 8
pgvector 0.7.0 の弱点(2/4) ● HNSW インデックス検索時の性能問題 ○ 階層構造のグラフ探索によるランダムアクセス発生 ■ 粗いグラフの階層から細かいグラフの階層へ辿っていく ■ ランダムアクセスになるのでディスクからのページ読み込みが非効率に 9
pgvector 0.7.0 の弱点(3/4) ● HNSW インデックス 検索時の精度問題 ○ セカンダリフィルター (WHERE 句)適用前の hnsw.ef_search カットオフ hnsw.ef_search = 5 のケース→ (「engineering」が取得できない) 出典 : https://www.timescale.com/blog/how-we-made-postgresql-as-fast-as-pinecone-for-vector-data/ 10
pgvector 0.7.0 の弱点(4/4) ● バイナリ量子化(BQ)使用時の精度問題 ○ 「0」と「1」の境界 ■ 元の値が「0.0」以下なら「0」、「0.0」より大きければ「1」 ■ しかし、大抵のケースで「0.0」は平均値ではない ○ 次元数が少ないときの精度低下 ■ 768 次元で 1 ビットに量子化したときの再現率が低い 11
pgvectorscale による改善(1/2) ● StreamingDiskANN インデックスを実装 ○ DiskANN アルゴリズム ■ Microsoft の研究によって開発 ■ 単層グラフ構造 ■ 遠く離れたノードを参照する隣接エッジを許容 ○ Streaming Filtering ■ hnsw.ef_search のようなカットオフをしない ■ 必要な数のインデックス行を継続的に参照できる仕組みを実装 12
pgvectorscale による改善(2/2) ● 統計的バイナリ量子化(SBQ)を実装 ちょっと疑問: 平均値を算出する タイミングはいつ? ○ 「0」と「1」の境界を各次元の平均値に ■ 平均値以下は「0」に、平均を超える値は「1」に変換 ○ 次元数が少ない(<900)場合のデフォルトを 2 ビット/次元に ■ Z スコア(※)を 3 つの領域に分割 ■ 隣接する領域の XOR 距離が 1 になるように 2 ビットにエンコード (「00」・「01」・「11」) (※)標準偏差で正規化された平均からの値の距離 13
使い方(pgvectorscale 0.3.0 : 2024/8/13 リリース) ● extension 有効化 CREATE EXTENSION IF NOT EXISTS vectorscale CASCADE; ● StreamingDiskANN インデックス作成 CREATE INDEX ON 【テーブル名】 USING diskann (embedding); ● デフォルトでは embedding が 900 次元未満なら 2 ビット/次元 900 次元以上なら 1 ビット/次元に量子化 ● 検索(比較)はコサイン類似度(コサイン距離)のみ対応(<=>) 14
pgai ● PostgreSQL から SQL 文で LLM の API コールを可能に ○ https://github.com/timescale/pgai ○ Python のストアドファンクションとして実装されている ■ Contribution のハードルは低そう ○ 機能のコンセプトとしては Amazon Aurora の ML 機能に近い ■ Aurora PostgreSQL の Bedrock 統合 https://aws.amazon.com/jp/about-aws/whats-new/2023/12/amazon-aurora-postgresql-int egration-bedrock-generative-ai/ 15
使い方(pgai 0.3.0 : 2024/7/10 リリース)
● extension 有効化
CREATE EXTENSION IF NOT EXISTS ai CASCADE;
● API キー登録(Cohere の例・複数方法あり)
SELECT set_config('ai.cohere_api_key', '【CohereのAPIキー】', false) is not null as set_config;
● API コール(Cohere Embed Multilingual v3.0 の例)
SELECT cohere_embed('embed-multilingual-v3.0', '【埋め込み対象文字列】', _input_type=>'search_document');
16
pgai 0.3.0 のサポート対象 API ● それぞれサポートしている機能は異なる ○ OpenAI ○ Ollama ○ Anthropic ○ Cohere →ドキュメントでは詳細がわからないのでテストコードを読むと良い ● https://github.com/timescale/pgai/tree/main/tests 17
まとめ ● pgvectorscale は pgvector の弱点を補う extension ○ データ量が多くなったときの性能・精度の低下を防ぐ ● pgai は PostgreSQL から LLM の API を呼ぶ extension ○ SQL 文で直接ベクトル埋め込みなどが可能に 18