pgvector-semantic-search
PostgreSQLでのベクトル類似検索をpgvectorを用いて構築する際に使用するスキルです。ベクトル埋め込みの保存・検索、セマンティック検索やRAGアプリケーションの実装、HNSWおよびIVFFlatインデックスの作成、バイナリ量子化による大規模データセットの最適化など、pgvector関連のあらゆる用途に対応し、インデックスパラメータのチューニングやフィルタリング検索、バルクロードのパフォーマンス改善まで幅広くサポートします。
description の原文を見る
| Use this skill for setting up vector similarity search with pgvector for AI/ML embeddings, RAG applications, or semantic search. **Trigger when user asks to:** - Store or search vector embeddings in PostgreSQL - Set up semantic search, similarity search, or nearest neighbor search - Create HNSW or IVFFlat indexes for vectors - Implement RAG (Retrieval Augmented Generation) with PostgreSQL - Optimize pgvector performance, recall, or memory usage - Use binary quantization for large vector datasets **Keywords:** pgvector, embeddings, semantic search, vector similarity, HNSW, IVFFlat, halfvec, cosine distance, nearest neighbor, RAG, LLM, AI search Covers: halfvec storage, HNSW index configuration (m, ef_construction, ef_search), quantization strategies, filtered search, bulk loading, and performance tuning.
SKILL.md 本文
セマンティック検索用 pgvector
セマンティック検索は、正確なキーワードではなく意味に基づいてコンテンツを検索します。埋め込みモデルはテキストを高次元ベクトルに変換し、似た意味は近い点にマップされます。pgvectorはこれらのベクトルをPostgreSQLに保存し、近似最近傍(ANN)インデックスを使用して最も近いマッチを迅速に検出します。データベースを離れることなく、数百万行にスケールします。テキストをその埋め込みと一緒に保存し、検索テキストをベクトルに変換して最小距離の行を返すことでクエリします。
このガイドはpgvectorのセットアップとチューニングをカバーしています。埋め込みモデルの選択またはテキストチャンキングについてはカバーしていません。これらは検索品質に大きく影響します。すべての機能に pgvector 0.8.0+ が必要です(halfvec、binary_quantize、反復的スキャン)。
ゴールデンパス(デフォルト設定)
特別な理由がない限り、この設定を使用してください。
- 埋め込みカラムのデータ型:
halfvec(N)(N は埋め込み次元。すべての場所で一致する必要があります)。例では 1536 を使用し、あなたの次元 N に置き換えます。 - 距離:コサイン(
<=>) - インデックス:HNSW(
m = 16、ef_construction = 64)。halfvec_cosine_opsを使用し、<=>でクエリします。 - クエリ時のリコール:
SET hnsw.ef_search = 100(公開されているベンチマークからの良い出発点、より高いリコールが必要な場合は増加) - クエリパターン:
ORDER BY embedding <=> $1::halfvec(N) LIMIT k
このセットアップは、ほとんどのテキスト埋め込みワークロードに対して強力な速度–リコールトレードオフを提供します。
基本ルール
- 各データベースで拡張機能を有効にする:
CREATE EXTENSION IF NOT EXISTS vector; - デフォルトでHNSWインデックスを使用。優れた速度–リコールトレードオフを実現でき、空のテーブルに作成でき、トレーニングステップは不要です。書き込み が多いまたはメモリが限定されるワークロードの場合のみ IVFFlat を検討してください。
- デフォルトで
halfvecを使用。ストレージとインデックスをhalfvecとして保存し、50% 小さいストレージとインデックスを実現し、リコール損失は最小限です。 - 初期データの一括ロード後にインデックスを作成し、最高のビルドパフォーマンスを実現します。
- 本番環境で同時にインデックスを作成:
CREATE INDEX CONCURRENTLY ... - デフォルトではコサイン距離を使用(
<=>):正規化されていない埋め込みについてはコサインを使用します。単位正規化された埋め込みについては、コサインと内積は同一のランキングを生成するため、デフォルトはコサインです。 - クエリ演算子をインデックス ops と一致:
halfvec_cosine_opsでインデックスされたものは、クエリで<=>が必要です。halfvec_l2_opsは<->が必要です。一致しない演算子はインデックスを使用しません。 - クエリベクトルを常に明示的にキャスト(
$1::halfvec(N))。プリペアドステートメントの暗黙的キャスト失敗を回避するため。 - データとクエリに常に同じ埋め込みモデルを使用。類似度検索はベクトルを生成するモデルが同じときのみ機能します。
タイプ ルール
- 埋め込みを
halfvec(N)として保存 - クエリベクトルを
halfvec(N)にキャスト - バイナリ量子化ベクトルを生成カラムの
bit(N)として保存 - 明示的なキャストなしで
vector/halfvec/bitを混在しない ORDER BY内のテーブルカラムでbinary_quantize()を呼び出さない。代わりに保存してください- 次元は一致する必要があります。
halfvec(1536)カラムはクエリベクトルを::halfvec(1536)としてキャストする必要があります。
標準パターン
-- halfvec として保存およびインデックス
CREATE TABLE items (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
contents TEXT NOT NULL,
embedding halfvec(1536) NOT NULL -- NOT NULL は埋め込みが挿入前に生成される必要があります。非同期ではありません。
);
CREATE INDEX ON items USING hnsw (embedding halfvec_cosine_ops);
-- クエリ:最も近い 10 項目を返します。$1 は検索テキストの埋め込みです。
SELECT id, contents FROM items ORDER BY embedding <=> $1::halfvec(1536) LIMIT 10;
その他の距離演算子(L2、内積など)については、pgvector README を参照してください。
HNSWインデックス
推奨されるインデックスタイプ。優れた速度–リコールトレードオフを備えた多層ナビゲート可能グラフを作成します。空のテーブルに作成でき、トレーニングステップは不要です。
CREATE INDEX ON items USING hnsw (embedding halfvec_cosine_ops);
-- チューニング パラメータを使用
CREATE INDEX ON items USING hnsw (embedding halfvec_cosine_ops) WITH (m = 16, ef_construction = 64);
HNSWパラメータ
| パラメータ | デフォルト | 説明 |
|---|---|---|
m | 16 | レイヤーあたりの最大接続数。高いほど = より良いリコール、より多くのメモリ |
ef_construction | 64 | ビルドタイム候補リスト。高いほど = より良いグラフ品質、より遅いビルド |
hnsw.ef_search | 40 | クエリタイム候補リスト。高いほど = より良いリコール、より遅いクエリ。LIMIT 以上である必要があります。 |
ef_search チューニング(大雑把なガイドライン。実際の結果はデータセットによって異なります):
| ef_search | 概算リコール | 相対速度 |
|---|---|---|
| 40 | 低い(約95%、いくつかのベンチマーク) | 1x(ベースライン) |
| 100 | 高い | 約2倍遅い |
| 200 | 非常に高い | 約4倍遅い |
| 400 | ほぼ正確 | 約8倍遅い |
-- セッションの検索パラメータを設定
SET hnsw.ef_search = 100;
-- 単一クエリのために設定
BEGIN;
SET LOCAL hnsw.ef_search = 100;
SELECT id, contents FROM items ORDER BY embedding <=> $1::halfvec(1536) LIMIT 10;
COMMIT;
IVFFlatインデックス(一般的には推奨されません)
デフォルトは HNSW です。HNSWの運用コストがピークリコールよりも重要な場合のみ、IVFFlatを使用してください。
以下の場合、IVFFlat を選択します:
- 書き込み が多いまたは常に変更されるデータであり、頻繁にインデックスを再構築することが厭わない
- インデックスを頻繁に再構築し、予測可能なビルド時間とメモリ使用量が必要
- メモリが限定されており、HNSWグラフをほぼ常駐させることができない
- データが分割またはティアられており、このインデックスが より冷たいパーティション上にある
以下が必要な場合、IVFFlat を避けてください:
- 低レイテンシでの最高のリコール
- 最小限のチューニング
- 「設定して忘れる」インデックス
注:
- IVFFlatはインデックス作成前にデータが存在する必要があります。
- リコールは
listsとivfflat.probesに依存します。プローブが多いほど = より良いリコール、より遅いクエリ。
スターター設定:
CREATE INDEX ON items
USING ivfflat (embedding halfvec_cosine_ops)
WITH (lists = 1000);
SET ivfflat.probes = 10;
量子化戦略
- 量子化はリコール決定ではなく、メモリ決定です。
- ストレージとインデックスにはデフォルトで
halfvecを使用します。 - HNSWインデックスのフットプリント を推定します。1536次元の
halfvec(m=16)あたり約4~6KB(オーダーオブマグニチュード)。3072次元は約2倍。m=32 はHNSWリンク/グラフオーバーヘッドをおおよそ2倍にします。 - p95/p99レイテンシが上がりながら CPU がほぼアイドルの場合、HNSWインデックスはおそらくメモリに常駐していません。
halfvecが適合しない場合は、バイナリ量子化 + 再ランキングを使用します。
1536次元ベクトルのガイドライン
m=16、1536次元の halfvec 容量を推定します(RAMはほぼインデックスキャッシングに利用可能と仮定):
| RAM | 概算最大 halfvec ベクトル |
|---|---|
| 16 GB | 約2~3Mベクトル |
| 32 GB | 約4~6Mベクトル |
| 64 GB | 約8~12Mベクトル |
| 128 GB | 約16~25Mベクトル |
3072次元の埋め込みの場合、これらの数値を約2で割ります。
m=32 の場合、容量も約2で割ります。
インデックスがこのスケールでメモリに適合しない場合は、バイナリ量子化を使用します。
これらは範囲であり、保証ではありません。負荷下でキャッシュ常駐性とp95/p99レイテンシを監視して検証します。
バイナリ量子化(非常に大規模なデータセット向け)
32倍のメモリ削減。受け入れ可能なリコールのために再ランキングと共に使用します。
-- バイナリ量子化用の生成カラムを含むテーブル
CREATE TABLE items (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
contents TEXT NOT NULL,
embedding halfvec(1536) NOT NULL,
embedding_bq bit(1536) GENERATED ALWAYS AS (binary_quantize(embedding)::bit(1536)) STORED
);
CREATE INDEX ON items USING hnsw (embedding_bq bit_hamming_ops);
-- より良いリコールのための再ランキングを伴うクエリ
-- ef_search は内部 LIMIT 以上である必要があり、十分な候補を取得します
SET hnsw.ef_search = 800;
WITH q AS (
SELECT binary_quantize($1::halfvec(1536))::bit(1536) AS qb
)
SELECT *
FROM (
SELECT i.id, i.contents, i.embedding
FROM items i, q
ORDER BY i.embedding_bq <~> q.qb -- インデックスを使用してバイナリ距離を計算
LIMIT 800
) candidates
ORDER BY candidates.embedding <=> $1::halfvec(1536) -- halfvec 距離を計算(インデックスなし、より正確)
LIMIT 10;
800候補から10結果への80倍オーバーサンプリング比率は、妥当な出発点です。バイナリ量子化は精度を失うため、再ランキング中に真の最近傍を見つけるにはより多くの候補が必要です。リコールが不十分な場合は増加させ、再ランキングレイテンシが高すぎる場合は減少させます。
データセットサイズ別のパフォーマンス
| スケール | ベクトル | 設定 | 注 |
|---|---|---|---|
| 小 | <100K | デフォルト | インデックスはオプションですが、テールレイテンシを改善します |
| 中 | 100K~5M | デフォルト | p95レイテンシを監視します。最も一般的な本番環境の範囲 |
| 大 | 5M+ | ef_construction=100+ | メモリ常駐が重要 |
| 非常に大きい | 10M+ | バイナリ量子化 + 再ランキング | 可能な場合は RAM を追加するか、最初に分割します |
リコール向けに ef_search を最初にチューニングします。リコールがプラトーに達して、メモリが許す場合のみ m を増加させます。同時実行下では、インデックスがメモリに適合しない場合、テールレイテンシスパイクします。バイナリ量子化はエスケープハッチです。最初に RAM を追加するか、分割することを選びます。
フィルタリングのベストプラクティス
フィルタリングされたベクトル検索には注意が必要です。フィルタ選択性とクエリ形状に応じて、フィルタは早期終了(行が少なすぎる、結果がない)または増加した作業(レイテンシ)を引き起こす可能性があります。
反復的スキャン(フィルタが選択的な場合に推奨)
デフォルトでは、WHERE句が存在する場合、HNSWは早期に停止して、予期した結果が得られない可能性があります。反復的スキャンにより、HNSWは十分なフィルタリング行が見つかるまで検索を続けることができます。
フィルタが結果セットを実質的に削減する場合、反復的スキャンを有効にします。
-- フィルタリング クエリの反復的スキャンを有効にします
SET hnsw.iterative_scan = relaxed_order;
SELECT id, contents
FROM items
WHERE category_id = 123
ORDER BY embedding <=> $1::halfvec(1536)
LIMIT 10;
結果が依然としてまばらな場合は、スキャン予算を増加させます:
SET hnsw.max_scan_tuples = 50000;
トレードオフ:hnsw.max_scan_tuples を増やすとリコールが改善されますが、レイテンシが大幅に増加する可能性があります。
反復的スキャンが不要な場合:
- フィルタが テーブルの大部分と一致します(低選択性)
- B-tree インデックス経由で事前フィルタリングしています
- 単一パーティションまたは部分インデックスをクエリしています
正しいフィルタリング戦略を選択
非常に選択的なフィルタ(約10k行未満) フィルタカラムの B-tree インデックスを使用し、Postgres が ANN の前に事前フィルタリングできるようにします。
CREATE INDEX ON items (category_id);
低カーディナリティフィルタ(異なる値が少ない) フィルタ値ごとに部分 HNSW インデックスを使用します。
CREATE INDEX ON items
USING hnsw (embedding halfvec_cosine_ops)
WHERE category_id = 11;
多くのフィルタ値または大規模なデータセット フィルタキーで分割して、各 ANN インデックスを小さく保ちます。
CREATE TABLE items (
embedding halfvec(1536),
category_id int
) PARTITION BY LIST (category_id);
重要なルール
- 少数の行に一致するフィルタは、事前フィルタリング、分割、または反復的スキャンが必要です。
- 実際の負荷下で p95/p99 レイテンシと訪問したタプルを測定してフィルタリング クエリを常に検証します。
代替案:ラベルベースのフィルタリング向けの pgvectorscale
ラベルベースのフィルタを備えた大規模なデータセットの場合、pgvectorscale の StreamingDiskANN インデックスは smallint[] カラムのフィルタリングされたインデックスをサポートします。ラベルはベクトルと共にインデックスされ、HNSW事後フィルタリングの精度トレードオフなしで効率的なフィルタリング検索を実現します。セットアップの詳細については、pgvectorscale ドキュメントを参照してください。
一括ロード
-- COPY は最も速く、バイナリ形式はより速いですが、適切なエンコーディングが必要です。
-- テキスト形式:'[0.1, 0.2, ...]'
COPY items (contents, embedding) FROM STDIN;
-- バイナリ形式(クライアントがサポートする場合):
COPY items (contents, embedding) FROM STDIN WITH (FORMAT BINARY);
-- ロード AFTER でインデックスを追加
SET maintenance_work_mem = '4GB';
SET max_parallel_maintenance_workers = 7;
CREATE INDEX ON items USING hnsw (embedding halfvec_cosine_ops);
メンテナンス
- 更新/削除後に定期的に VACUUM を実行。stale エントリはクリーンアップされるまで残る可能性があります
- 高チャーン後にパフォーマンスが低下した場合は REINDEX を実行。グラフをスクラッチから再構築します
- 頻繁な削除を伴う書き込み が多いワークロードの場合は、IVFFlat または hypertable を使用した時間による分割を検討してください
監視とデバッグ
-- インデックスサイズをチェック
SELECT pg_size_pretty(pg_relation_size('items_embedding_idx'));
-- クエリパフォーマンスをデバッグ
EXPLAIN (ANALYZE, BUFFERS) SELECT id, contents FROM items ORDER BY embedding <=> $1::halfvec(1536) LIMIT 10;
-- インデックスビルド進捗を監視
SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%"
FROM pg_stat_progress_create_index;
-- 近似と正確なリコールを比較
BEGIN;
SET LOCAL enable_indexscan = off; -- 正確な検索を強制
SELECT id, contents FROM items ORDER BY embedding <=> $1::halfvec(1536) LIMIT 10;
COMMIT;
-- デバッグ用にインデックス使用を強制
BEGIN;
SET LOCAL enable_seqscan = off;
SELECT id, contents FROM items ORDER BY embedding <=> $1::halfvec(1536) LIMIT 10;
COMMIT;
一般的な問題(症状 → 修正)
| 症状 | 考えられる原因 | 修正 |
|---|---|---|
| クエリが ANN インデックスを使用しない | ORDER BY + LIMIT が不足、演算子の不一致、または暗黙的なキャスト | インデックス ops と一致する距離演算子で ORDER BY を使用します。クエリベクトルを明示的にキャストします |
| 結果が期待より少ない(フィルタリングされたクエリ) | フィルタにより HNSW が早期に停止 | 反復的スキャンを有効にします。hnsw.max_scan_tuples を増加させます。または事前フィルタリング(B-tree)、部分インデックス、または分割を使用します |
| 結果が期待より少ない(フィルタリングされていないクエリ) | ANN リコール が低すぎる | hnsw.ef_search を増加させます |
| 高レイテンシ、低 CPU 使用量 | HNSW インデックスがメモリに常駐していない | halfvec を使用、m/ef_construction を削減、RAM を追加、分割、またはバイナリ量子化を使用 |
| インデックスビルドが遅い | 不十分なビルドメモリまたは並列処理 | maintenance_work_mem と max_parallel_maintenance_workers を増加させます。一括ロード後にビルドします |
| メモリ不足エラー | インデックスがアクセス可能な RAM に対して大きすぎる | halfvec を使用、インデックスパラメータを削減、またはバイナリ量子化に切り替えて再ランキングを実行 |
| ゼロまたは欠落している結果 | NULL またはゼロベクトル | NULL 埋め込みを避けます。コサイン距離でゼロベクトルを使用しないでください |
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- timescale
- リポジトリ
- timescale/pg-aiguide
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/timescale/pg-aiguide / ライセンス: Apache-2.0
関連スキル
agent-browser
AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。
anyskill
AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。
engram
AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。
skyvern
AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。
pinchbench
PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。
openui
OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。