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
];
基本的な検索方法の使い方については、Retrieve Results の例をご覧ください。
高度な検索オプション
メタデータフィルタリング
メタデータフィールドに基づいて結果をフィルタリングし、検索範囲を絞り込みます。これは、異なるソース、時期、または特定の属性を持つドキュメントがある場合に便利です。Mastraは、サポートされているすべてのベクターストアで動作する統一されたMongoDB形式のクエリ構文を提供します。
利用可能な演算子と構文の詳細については、メタデータフィルターリファレンスを参照してください。
基本的なフィルタリングの例:
// Simple equality filter
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
source: "article1.txt",
},
});
// Numeric comparison
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
price: { $gt: 100 },
},
});
// Multiple conditions
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
category: "electronics",
price: { $lt: 1000 },
inStock: true,
},
});
// Array operations
const results = await pgVector.query({
indexName: "embeddings",
queryVector: embedding,
topK: 10,
filter: {
tags: { $in: ["sale", "new"] },
},
});
// Logical operators
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: `
提供されたコンテキストを使用してクエリを処理します。簡潔で関連性の高い応答を構造化してください。
${PGVECTOR_PROMPT}
`,
tools: { vectorQueryTool },
});
Re-ranking
初期のベクトル類似度検索では、微妙な関連性を見逃すことがあります。Re-rankingは計算コストが高いプロセスですが、より正確なアルゴリズムで以下により結果を改善します:
- 単語の順序と完全一致を考慮
- より洗練された関連性スコアリングを適用
- クエリと文書間のクロスアテンションと呼ばれる手法を使用
Re-rankingの使用方法は以下の通りです:
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"),
);
注意: Re-ranking中にセマンティックスコアリングが適切に機能するためには、各結果の
metadata.text
フィールドにテキストコンテンツが含まれている必要があります。
Re-rankingされた結果は、ベクトル類似度とセマンティック理解を組み合わせて、検索品質を向上させます。
Re-rankingの詳細については、rerank()メソッドを参照してください。
Re-rankingメソッドの使用例については、Re-ranking Resultsの例を参照してください。
Graph-based Retrieval
複雑な関係を持つ文書の場合、グラフベースの検索はチャンク間の接続をたどることができます。これは以下の場合に役立ちます:
- 情報が複数の文書に分散している場合
- 文書が互いを参照している場合
- 完全な回答を見つけるために関係をたどる必要がある場合
セットアップ例:
const graphQueryTool = createGraphQueryTool({
vectorStoreName: "pgVector",
indexName: "embeddings",
model: openai.embedding("text-embedding-3-small"),
graphOptions: {
threshold: 0.7,
},
});
グラフベース検索の詳細については、GraphRAGクラスとcreateGraphQueryTool()関数を参照してください。
グラフベース検索メソッドの使用例については、Graph-based Retrievalの例を参照してください。