ベクトルデータベースへの埋め込みの保存
埋め込みを生成した後、ベクトル類似性検索をサポートするデータベースに保存する必要があります。Mastraは、さまざまなベクトルデータベース間で埋め込みを保存およびクエリするための一貫したインターフェースを提供します。
サポートされているデータベース
Pg Vector
import { PgVector } from '@mastra/pg';
const store = new PgVector({ connectionString: process.env.POSTGRES_CONNECTION_STRING })
await store.createIndex({
indexName: "myCollection",
dimension: 1536,
});
await store.upsert({
indexName: "myCollection",
vectors: embeddings,
metadata: chunks.map(chunk => ({ text: chunk.text })),
});
pgvectorを使用したPostgreSQLの利用
pgvector拡張機能を備えたPostgreSQLは、すでにPostgreSQLを使用しているチームがインフラの複雑さを最小限に抑えたい場合に適したソリューションです。 詳細なセットアップ手順とベストプラクティスについては、pgvectorの公式リポジトリ を参照してください。
ベクトルストレージの使用
初期化後、すべてのベクトルストアは、インデックスの作成、埋め込みのアップサート、およびクエリのための同じインターフェースを共有します。
インデックスの作成
埋め込みを保存する前に、埋め込みモデルに適切な次元サイズでインデックスを作成する必要があります:
// Create an index with dimension 1536 (for text-embedding-3-small)
await store.createIndex({
indexName: "myCollection",
dimension: 1536,
});
次元サイズは、選択した埋め込みモデルの出力次元と一致する必要があります。一般的な次元サイズは以下の通りです:
- OpenAI text-embedding-3-small: 1536次元(またはカスタム、例えば256)
- Cohere embed-multilingual-v3: 1024次元
- Google
text-embedding-004
: 768次元(またはカスタム)
重要: インデックスの次元は作成後に変更できません。異なるモデルを使用するには、インデックスを削除して新しい次元サイズで再作成してください。
データベースの命名規則
各ベクトルデータベースは、互換性を確保し競合を防ぐために、インデックスとコレクションに特定の命名規則を適用しています。
Pg Vector
インデックス名は以下の条件を満たす必要があります:
- 文字またはアンダースコアで始まる
- 文字、数字、アンダースコアのみを含む
- 例:
my_index_123
は有効 - 例:
my-index
は無効(ハイフンを含む)
埋め込みのアップサート
インデックスを作成した後、埋め込みとその基本的なメタデータを保存できます:
// Store embeddings with their corresponding metadata
await store.upsert({
indexName: "myCollection", // index name
vectors: embeddings, // array of embedding vectors
metadata: chunks.map((chunk) => ({
text: chunk.text, // The original text content
id: chunk.id, // Optional unique identifier
})),
});
upsert操作は以下を行います:
- 埋め込みベクトルとそれに対応するメタデータの配列を受け取ります
- 同じIDを持つ既存のベクトルを更新します
- 存在しないベクトルを新規作成します
- 大規模なデータセットのバッチ処理を自動的に処理します
異なるベクトルストアでの埋め込みのupsertの完全な例については、埋め込みのUpsertガイドを参照してください。
メタデータの追加
ベクトルストアはフィルタリングと整理のためのリッチなメタデータ(JSONシリアライズ可能なフィールド)をサポートしています。メタデータは固定されたスキーマなしで保存されるため、予期しないクエリ結果を避けるために一貫したフィールド命名を使用してください。
重要:メタデータはベクトルストレージにとって非常に重要です - これがなければ、数値的な埋め込みだけが残り、元のテキストを返したり結果をフィルタリングしたりする方法がなくなります。少なくとも元のテキストをメタデータとして常に保存してください。
// Store embeddings with rich metadata for better organization and filtering
await store.upsert({
indexName: "myCollection",
vectors: embeddings,
metadata: chunks.map((chunk) => ({
// Basic content
text: chunk.text,
id: chunk.id,
// Document organization
source: chunk.source,
category: chunk.category,
// Temporal metadata
createdAt: new Date().toISOString(),
version: "1.0",
// Custom fields
language: chunk.language,
author: chunk.author,
confidenceScore: chunk.score,
})),
});
メタデータに関する重要な考慮事項:
- フィールド命名に厳格であること - 「category」と「Category」のような不一致はクエリに影響します
- フィルタリングやソートに使用する予定のフィールドのみを含める - 余分なフィールドはオーバーヘッドを追加します
- コンテンツの鮮度を追跡するためのタイムスタンプ(例:「createdAt」、「lastUpdated」)を追加する
ベストプラクティス
- 大量挿入の前にインデックスを作成する
- 大量挿入にはバッチ操作を使用する(upsertメソッドは自動的にバッチ処理を行います)
- クエリを実行する予定のメタデータのみを保存する
- 埋め込みの次元数をモデルに合わせる(例:
text-embedding-3-small
の場合は1536)