RAGシステムにおける検索
埋め込みを保存した後、ユーザーのクエリに答えるために関連するチャンクを検索する必要があります。
Mastraは、セマンティック検索、フィルタリング、再ランキングに対応した柔軟な検索オプションを提供します。
検索の仕組み
- ユーザーのクエリは、ドキュメント埋め込みと同じモデルを使って埋め込みに変換されます
- この埋め込みは、ベクトル類似度を用いて保存された埋め込みと比較されます
- 最も類似したチャンクが取得され、必要に応じて以下の処理が行われます:
- メタデータでフィルタリング
- より高い関連性のために再ランク付け
- ナレッジグラフを通じて処理
基本的な検索
最もシンプルなアプローチは直接的な意味検索です。この方法では、ベクトル類似性を使用してクエリに意味的に類似したチャンクを見つけます:
import { openai } from "@ai-sdk/openai";
import { embed } from "ai";
import { PgVector } from "@mastra/pg";
// Convert query to embedding
const { embedding } = await embed({
value: "What are the main points in the article?",
model: openai.embedding("text-embedding-3-small"),
});
// Query vector store
const pgVector = new PgVector({ connectionString: process.env.POSTGRES_CONNECTION_STRING });
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
});
// Display results
console.log(results);
結果には、テキストコンテンツと類似度スコアの両方が含まれます:
[
{
text: "Climate change poses significant challenges...",
score: 0.89,
metadata: { source: "article1.txt" },
},
{
text: "Rising temperatures affect crop yields...",
score: 0.82,
metadata: { source: "article1.txt" },
},
// ... more results
];
基本的な検索方法の使用例については、結果の取得の例を参照してください。
高度な検索オプション
メタデータフィルタリング
メタデータフィールドに基づいて結果をフィルタリングし、検索範囲を絞り込みます。これは、異なるソースや時期、特定の属性を持つドキュメントがある場合に便利です。Mastra は、すべての対応ベクトルストアで動作する統一された MongoDB 形式のクエリ構文を提供します。
利用可能な演算子や構文の詳細については、メタデータフィルタリファレンスをご覧ください。
基本的なフィルタリング例:
// シンプルな等価フィルタ
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
source: "article1.txt",
},
});
// 数値比較
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
price: { $gt: 100 },
},
});
// 複数条件
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
category: "electronics",
price: { $lt: 1000 },
inStock: true,
},
});
// 配列操作
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
tags: { $in: ["sale", "new"] },
},
});
// 論理演算子
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
$or: [{ category: "electronics" }, { category: "accessories" }],
$and: [{ price: { $gt: 50 } }, { price: { $lt: 200 } }],
},
});
メタデータフィルタリングの主なユースケース:
- ドキュメントのソースや種類でフィルタリング
- 日付範囲でフィルタリング
- 特定のカテゴリやタグでフィルタリング
- 数値範囲(例:価格、評価)でフィルタリング
- 複数の条件を組み合わせて精密なクエリを実行
- ドキュメント属性(例:言語、著者)でフィルタリング
メタデータフィルタリングの使用例については、ハイブリッドベクトル検索の例をご覧ください。
ベクトルクエリツール
エージェントにベクトルデータベースへ直接クエリを実行させたい場合があります。ベクトルクエリツールを使うことで、エージェントが検索の判断を担い、セマンティック検索とオプションのフィルタリング、さらにユーザーのニーズに基づいたリランキングを組み合わせることができます。
const vectorQueryTool = createVectorQueryTool({
vectorStoreName: "pgVector",
indexName: "embeddings",
model: openai.embedding("text-embedding-3-small"),
});
ツールを作成する際は、ツールの名前と説明に特に注意してください。これらはエージェントがいつ、どのように検索機能を使うべきかを理解する助けになります。たとえば、「SearchKnowledgeBase」と名付け、「ドキュメント内からXトピックに関する関連情報を検索します」と説明することができます。
この機能が特に有用なのは次のような場合です:
- エージェントが動的に取得すべき情報を判断する必要がある場合
- 検索プロセスに複雑な意思決定が必要な場合
- エージェントに文脈に応じて複数の検索戦略を組み合わせてほしい場合
詳細な設定オプションや高度な使い方については、ベクトルクエリツールリファレンスをご覧ください。
ベクトルストアプロンプト
ベクトルストアプロンプトは、各ベクトルデータベース実装のためのクエリパターンやフィルタリング機能を定義します。 フィルタリングを実装する際、これらのプロンプトはエージェントの指示内で必要となり、各ベクトルストア実装における有効な演算子や構文を指定します。
Pg Vector
import { openai } from '@ai-sdk/openai';
import { PGVECTOR_PROMPT } from "@mastra/pg";
export const ragAgent = new Agent({
name: 'RAG Agent',
model: openai('gpt-4o-mini'),
instructions: `
Process queries using the provided context. Structure responses to be concise and relevant.
${PGVECTOR_PROMPT}
`,
tools: { vectorQueryTool },
});
再ランキング
初期のベクトル類似検索では、微妙な関連性を見逃すことがあります。再ランキングは、より計算コストが高いものの、より正確なアルゴリズムであり、以下の方法で結果を改善します:
- 単語の順序や完全一致を考慮する
- より高度な関連性スコアリングを適用する
- クエリとドキュメント間でクロスアテンションと呼ばれる手法を使用する
再ランキングの使い方は次の通りです:
import { openai } from "@ai-sdk/openai";
import { rerank } from "@mastra/rag";
// Get initial results from vector search
const initialResults = await pgVector.query({
indexName: "embeddings",
queryVector: queryEmbedding,
topK: 10,
});
// Re-rank the results
const rerankedResults = await rerank(
initialResults,
query,
openai("gpt-4o-mini"),
);
注: 再ランキング時にセマンティックスコアリングが正しく機能するためには、各結果が
metadata.text
フィールドにテキストコンテンツを含んでいる必要があります。
再ランキングされた結果は、ベクトル類似性と意味的理解を組み合わせて、検索品質を向上させます。
再ランキングの詳細については、rerank() メソッドをご覧ください。
再ランキングメソッドの使用例については、Re-ranking Results の例をご参照ください。
グラフベース検索
複雑な関係を持つドキュメントの場合、グラフベース検索はチャンク間の接続をたどることができます。これは次のような場合に役立ちます:
- 情報が複数のドキュメントに分散している
- ドキュメント同士が相互に参照している
- 完全な答えを見つけるために関係をたどる必要がある
セットアップ例:
const graphQueryTool = createGraphQueryTool({
vectorStoreName: "pgVector",
indexName: "embeddings",
model: openai.embedding("text-embedding-3-small"),
graphOptions: {
threshold: 0.7,
},
});
グラフベース検索の詳細については、GraphRAG クラスおよび createGraphQueryTool() 関数をご覧ください。
グラフベース検索メソッドの使用例については、Graph-based Retrieval の例をご参照ください。