ベクトル検索
すべてのEspobaseプロジェクトにpgvectorが含まれています。データの隣に埋め込みを保存し、インデックスを作成して、最も類似した行を見つけられます。セマンティック検索、レコメンデーション、自社コンテンツに関する質問への回答などに使えます。
仕組み
- 埋め込みとは、テキストや画像の意味を表す数値のリストです。アプリはAIプロバイダーから埋め込みを取得します(例:OpenAIのtext-embedding-3-small、1536個の数値)。Espobaseは埋め込みを保存・検索しますが、作成はしません。
vector(1536)カラムには1行につき1つの埋め込みが入ります。意味が似ているほど距離が小さくなるため、最も近い行が最も一致する行です。- pgvectorはすべてのプロジェクトで設定済みです。インストールする拡張機能も設定もありません。SQLエディタ、テーブルエディタ(カラム型
vector)、AIビルダーで使えます。
1. テーブルを作成する
プロジェクトのSQLエディタで:
create table documents ( id bigint generated always as identity primary key, content text not null, embedding vector(1536) not null ); -- Fast similarity search (cosine distance) create index on documents using hnsw (embedding vector_cosine_ops); -- Who may read: row level security is on for every table create policy "Anyone can read documents" on documents for select using (true);
または、AIビルダーに頼むこともできます。例:「セマンティック検索用の埋め込みを持つdocumentsテーブル」。レビュー用に、vectorカラムと類似度インデックスを提案します。
2. 検索関数を追加する
類似度検索は小さなSQL関数です。一度作成すれば、アプリからREST APIを通じて呼び出せます。
create function match_documents(query_embedding vector(1536), match_count int) returns table (id bigint, content text, similarity float) language sql stable as $$ select id, content, 1 - (embedding <=> query_embedding) as similarity from documents order by embedding <=> query_embedding limit match_count $$;
関数は呼び出したユーザーとして実行されるため、行レベルセキュリティが適用されます。ログイン中のユーザーは、ポリシーで許可された行だけを見つけられます。
3. アプリから保存・検索する
import { createClient } from "@espobase/client";
const espobase = createClient(PROJECT_URL, PUBLISHABLE_KEY);
// Store: your app gets the embedding from its AI provider (1536 numbers).
await espobase.from("documents").insert({
content: "How to reset your password",
embedding: JSON.stringify(embedding),
});
// Search: the 5 most similar documents to the user's question.
const { data } = await espobase.rpc("match_documents", {
query_embedding: JSON.stringify(questionEmbedding),
match_count: 5,
});ベクトルは[0.12,-0.03,…]のようなテキストとして送受信されます。REST APIを直接使う場合は、同じJSON本文でPOST /rest/v1/rpc/match_documentsを呼び出します。
知っておくと便利なこと
- 距離:
<=>はコサイン、<->はユークリッド(L2)、<#>は負の内積です。クエリに合ったインデックスの演算子クラス(vector_cosine_ops、vector_l2_ops、vector_ip_ops)を使ってください。 - HNSWインデックスは最大2,000次元までサポートします。
- 既存の多数の行に対するインデックスの作成には時間がかかります。先にインデックスを作成するか、大きなインデックスはデータベースへの直接接続で作成してください。
- 埋め込みはプランのデータベースストレージにカウントされます(1536次元 ≈ 1行あたり6 KB)。