Skip to Content

RAGシステムにおける検索

埋め込みを保存した後、ユーザーのクエリに答えるために関連するチャンクを検索する必要があります。

Mastraは、セマンティック検索、フィルタリング、再ランキングに対応した柔軟な検索オプションを提供します。

検索の仕組み

  1. ユーザーのクエリは、ドキュメント埋め込みと同じモデルを使って埋め込みに変換されます
  2. この埋め込みは、ベクトル類似度を用いて保存された埋め込みと比較されます
  3. 最も類似したチャンクが取得され、必要に応じて以下の処理が行われます:
  • メタデータでフィルタリング
  • より高い関連性のために再ランク付け
  • ナレッジグラフを通じて処理

基本的な検索

最もシンプルな方法は、直接的なセマンティック検索です。この方法では、ベクトル類似度を利用して、クエリと意味的に類似したチャンクを見つけます。

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トピックに関する関連情報を見つけるためにドキュメントを検索する」と説明することができます。

これは特に以下の場合に便利です:

  • エージェントが取得する情報を動的に決定する必要がある場合
  • 検索プロセスが複雑な意思決定を必要とする場合
  • エージェントがコンテキストに基づいて複数の検索戦略を組み合わせることを望む場合

データベース固有の設定

ベクタークエリツールは、異なるベクターストアの独自の機能と最適化を活用できるデータベース固有の設定をサポートしています:

// Pinecone with namespace const pineconeQueryTool = createVectorQueryTool({ vectorStoreName: "pinecone", indexName: "docs", model: openai.embedding("text-embedding-3-small"), databaseConfig: { pinecone: { namespace: "production" // Isolate data by environment } } }); // pgVector with performance tuning const pgVectorQueryTool = createVectorQueryTool({ vectorStoreName: "postgres", indexName: "embeddings", model: openai.embedding("text-embedding-3-small"), databaseConfig: { pgvector: { minScore: 0.7, // Filter low-quality results ef: 200, // HNSW search parameter probes: 10 // IVFFlat probe parameter } } }); // Chroma with advanced filtering const chromaQueryTool = createVectorQueryTool({ vectorStoreName: "chroma", indexName: "documents", model: openai.embedding("text-embedding-3-small"), databaseConfig: { chroma: { where: { "category": "technical" }, whereDocument: { "$contains": "API" } } } }); // LanceDB with table specificity const lanceQueryTool = createVectorQueryTool({ vectorStoreName: "lance", indexName: "documents", model: openai.embedding("text-embedding-3-small"), databaseConfig: { lance: { tableName: "myVectors", // Specify which table to query includeAllColumns: true // Include all metadata columns in results } } });

主な利点:

  • Pineconeネームスペース: テナント、環境、またはデータタイプ別にベクトルを整理
  • pgVector最適化: ef/probesパラメータで検索精度と速度を制御
  • 品質フィルタリング: 最小類似度閾値を設定して結果の関連性を向上
  • LanceDBテーブル: より良い整理とパフォーマンスのためにデータをテーブルに分離
  • ランタイム柔軟性: コンテキストに基づいて設定を動的にオーバーライド

一般的な使用例:

  • Pineconeネームスペースを使用したマルチテナントアプリケーション
  • 高負荷シナリオでのパフォーマンス最適化
  • 環境固有の設定(dev/staging/prod)
  • 品質ゲート付き検索結果
  • エッジデプロイメントシナリオ向けのLanceDBを使用した組み込み、ファイルベースのベクトルストレージ

また、ランタイムコンテキストを使用してこれらの設定をランタイムでオーバーライドすることもできます:

import { RuntimeContext } from '@mastra/core/runtime-context'; const runtimeContext = new RuntimeContext(); runtimeContext.set('databaseConfig', { pinecone: { namespace: 'runtime-namespace' } }); await pineconeQueryTool.execute({ context: { queryText: 'search query' }, mastra, runtimeContext });

詳細な設定オプションと高度な使用方法については、Vector Query Tool Referenceを参照してください。

Vector Store Prompts

ベクトルストアプロンプトは、各ベクトルデータベース実装のクエリパターンとフィルタリング機能を定義します。 フィルタリングを実装する際、これらのプロンプトは各ベクトルストア実装の有効な演算子と構文を指定するために、エージェントの指示に必要です。

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の例を参照してください。