RAG

Microsoft Agent Framework では、モデル呼び出しの前に取得されたコンテンツを追加するコンテキスト プロバイダーと、モデルが必要に応じてグラウンド データを取得できるようにする検索ツールを通じて、取得拡張生成 (RAG) がサポートされます。

取得と共に会話/セッション パターンについては、「 会話とメモリの概要」を参照してください。 サービス固有のセットアップについては、Azure AI 検索、Microsoft Foundry、Neo4j を参照してください。

TextSearchProvider の使用

TextSearchProvider クラスは、RAG コンテキスト プロバイダーのすぐに使用する実装です。 チャット履歴を使用して実行される各エージェントの検索や、検索を実行するための広告機能ツールなど、さまざまな操作モードがサポートされています。

ChatClientAgent オプションを使用して、AIContextProvidersに簡単にアタッチできます。

// Configure the options for the TextSearchProvider.
TextSearchProviderOptions textSearchOptions = new()
{
    SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke,
};

// Create the AI agent with the TextSearchProvider.
AIAgent agent = azureOpenAIClient
    .GetChatClient(deploymentName)
    .AsAIAgent(new ChatClientAgentOptions
    {
        ChatOptions = new() { Instructions = "You are a helpful support specialist. Answer questions using the provided context and cite the source document when available." },
        AIContextProviders = [new TextSearchProvider(SearchAdapter, textSearchOptions)]
    });

TextSearchProviderには、クエリに指定された検索結果を提供する関数が必要です。 これは、Azure AI 検索や Web 検索エンジンなど、任意の検索テクノロジを使用して実装できます。

Tip

検索結果に ベクター ストアを使用する 方法の詳細については、ベクター ストアの統合に関するページを参照してください。

クエリに基づいて定義済みの結果を返すモック検索機能の例を次に示します。 SourceName および SourceLink は省略可能ですが、指定された場合は、エージェントがユーザーの質問に答えるときに情報のソースを引用するために使用されます。

static Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchAdapter(string query, CancellationToken cancellationToken)
{
    // The mock search inspects the user's question and returns pre-defined snippets
    // that resemble documents stored in an external knowledge source.
    List<TextSearchProvider.TextSearchResult> results = new();

    if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase))
    {
        results.Add(new()
        {
            SourceName = "Contoso Outdoors Return Policy",
            SourceLink = "https://contoso.com/policies/returns",
            Text = "Customers may return any item within 30 days of delivery. Items should be unused and include original packaging. Refunds are issued to the original payment method within 5 business days of inspection."
        });
    }

    return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
}

TextSearchProvider オプション

TextSearchProviderは、TextSearchProviderOptions クラスを使用してカスタマイズできます。 すべてのモデル呼び出しの前に検索を実行し、検索のチャット履歴の短いローリング ウィンドウを保持するオプションを作成する例を次に示します。

TextSearchProviderOptions textSearchOptions = new()
{
    // Run the search prior to every model invocation and keep a short rolling window of chat history for searches.
    SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke,
    RecentMessageMemoryLimit = 6,
};

TextSearchProvider クラスは、TextSearchProviderOptions クラスを介して次のオプションをサポートしています。

Option タイプ 説明 Default
検索時間 TextSearchProviderOptions.TextSearchBehavior 検索を実行するタイミングを示します。 エージェントを実行するたびに、または関数呼び出しを介してオンデマンドで、2 つのオプションがあります。 TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke
FunctionToolName string オンデマンド モードで動作する場合に公開される検索ツールの名前。 "検索"
FunctionToolDescription string オンデマンド モードで動作する場合に公開される検索ツールの説明。 "ユーザーの質問に答えるのに役立つ追加情報を検索できます。"
コンテキストプロンプト string 結果のプレフィックスが付いたコンテキスト プロンプト。 "## 追加コンテキスト\nユーザーに応答するときに、ソース ドキュメントからの次の情報を考慮してください。"
CitationsPrompt string 引用を要求する結果の後に追加された命令。 "ドキュメント名とリンクを使用できる場合は、ドキュメント名とリンクを使用して、ソース ドキュメントへの引用を含めます。"
ContextFormatter Func<IList<TextSearchProvider.TextSearchResult>, string> 結果一覧の書式を完全にカスタマイズするための省略可能なデリゲート。 指定した場合、 ContextPrompt と CitationsPrompt は無視されます。 null
RecentMessageMemoryLimit int メモリ内に保持し、 BeforeAIInvoke 検索の検索入力を構築するときに含める最近の会話メッセージ (ユーザーとアシスタントの両方) の数。 0 (無効)
RecentMessageRolesIncluded List<ChatRole> 検索入力の作成時に含める最近のメッセージを決定するときに、最近使用したメッセージをフィルター処理する ChatRole の種類の一覧。 ChatRole.User

Tip

実行可能な完全な例については、 .NET サンプル を参照してください。

Agent Framework には、ネイティブ ベクター ストア コントラクトと create_vector_search_tool()が用意されています。 ヘルパーは、 SupportsVectorSearch 実装を関数ツールに変換するため、モデルは応答する前に接地データを取得できます。

ネイティブ ベクター検索ツールを作成する

まず、ベクター ストア モデルを定義し、コレクションを作成し、そのレコードを読み込みます。 次の例では、OpenAIEmbeddingClientでInMemoryCollectionを使用していますが、SupportsVectorSearchを実装する任意のネイティブ Agent Framework コレクションを指定できます。 次に、オプションのカテゴリと評価フィルターをモデルに公開し、各結果をグラウンド テキストにマップし、回答する前に検索するようにエージェントに指示します。

import asyncio
import json
import os
from typing import Annotated, Any, Literal
from urllib.request import urlopen

from agent_framework import (
    Agent,
    Filter,
    FilterGroup,
    InMemoryCollection,
    Param,
    VectorStoreField,
    create_vector_search_tool,
    vectorstoremodel,
)
from agent_framework.openai import OpenAIChatClient, OpenAIEmbeddingClient
from dotenv import load_dotenv
async def main() -> None:
    """Create an in-memory hotel search tool and give it to an agent."""
    api_key = os.environ["OPENAI_API_KEY"]
    collection: InMemoryCollection[str, Hotel] = InMemoryCollection(
        Hotel,
        embedding_generator=OpenAIEmbeddingClient(
            model="text-embedding-3-small",
            api_key=api_key,
        ),
    )
    await collection.ensure_collection_exists()

    # 1. Load the hotel records.
    hotels = await asyncio.to_thread(load_hotels)
    await collection.upsert(hotels)

    # 2. Param values become optional model-visible filter arguments.
    # When the allowed values are known, use Literal so the tool schema exposes
    # them as an enum.
    category = Param(
        "category",
        Literal["Boutique", "Budget", "Extended-Stay", "Luxury", "Resort and Spa", "Suite"],
        description="Only return hotels in this category.",
    )
    min_rating = Param(
        "min_rating",
        float,
        description="The minimum guest rating.",
        minimum=0,
        maximum=5,
    )
    tool = create_vector_search_tool(
        collection,
        description="Search the hotel dataset, optionally filtering by category and minimum rating.",
        filter=FilterGroup(
            "and",
            (
                Filter("category", "eq", category),
                Filter("rating", "gte", min_rating),
            ),
        ),
        result_mapper=lambda result: (
            f"(hotel_id: {result['record'].hotel_id}) {result['record'].hotel_name} "
            f"(rating {result['record'].rating}) - {result['record'].description}. "
            f"Address: {result['record'].address.city}, {result['record'].address.country}."
        ),
    )

    # 3. The agent chooses whether to supply the exposed category and minimum-rating filters.
    async with Agent(
        client=OpenAIChatClient(
            model="gpt-5.4-nano",
            api_key=api_key,
        ),
        name="HotelAgent",
        instructions=(
            "Always use the search tool to answer hotel questions. "
            "Use category and minimum rating filters when the request provides them. "
            "Include the hotel_id in the answer."
        ),
        tools=[tool],
    ) as agent:
        result = await agent.run("Find a resort and spa with a rating of at least 4.")
        print(result)

完全なサンプルでは、 Hotel モデルを定義し、表示されるコレクションのセットアップの前にソース レコードを読み込みます。 OPENAI_API_KEYを実行する前に設定します。

検索動作をカスタマイズする

次のオプションを使用して create_vector_search_tool() を構成します。

Option Purpose
name モデルに公開される関数名を設定します。 複数の検索ツールを追加する場合は、一意の名前を使用します。
description モデルでツールを使用するタイミングと理由について説明します。
approval_mode ツールの承認を always_require または never_requireに設定します。
search_type vectorまたはkeyword_hybrid検索を選択します。 コレクションは、選択したモードをサポートする必要があります。
top と skip 固定ページング値を設定するか、モデルが提供する型指定された Param 値を使用します。
filter 移植可能な Filter または FilterGroupを適用します。 フィルターには、ツール スキーマで公開されている型指定された Param 値を含めることができます。
result_mapper 各 SearchResponse をモデルのテキストまたはマルチモーダル Content に変換します。

生成されたツールには、常に query 文字列が含まれます。 フィルター、top、またはskip設定のParam値は、追加の検証済みツール引数になります。 Literal制約と数値制約を使用して、アプリケーションが受け入れる範囲内にモデル指定の値を保持します。

さまざまなコレクションまたは検索モードに対して複数のツールを作成できます。 モデルが適切なナレッジ ソースを選択できるように、各ツールに個別の name と description を与えます。

ネイティブ ベクター ストアを選択する

ネイティブ Python実装は、pgvector、Qdrant、Redis を使用したメモリ内検索、Azure AI 検索、PostgreSQL に使用できます。 検索モード、パッケージのライフサイクル、インストール コマンド、および制限は異なります。 実装を選択して構成するには 、Vector ストアの統合 に関する記述を参照してください。 また、そのページには、現在、個別のSemantic Kernel コネクタしかないデータベースも識別されます。

GO での RAG

agent/textsearch パッケージは、agent.ContextProviderを通じて取得したナレッジを追加します。 テキスト、オプションのソース名、リンクなど、 []textsearch.Resultを返す検索機能を指定し、プロバイダーを agent.Config.ContextProvidersに登録します。

管理されているカスタム データ ソース サンプルでは、モック検索機能と Foundry モデルのデプロイを使用します。

import (
    "context"
    "fmt"
    "strings"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/agent/textsearch"
    "github.com/microsoft/agent-framework-go/examples/internal/demo"
    "github.com/microsoft/agent-framework-go/provider/foundryprovider"
)
    searchProvider := textsearch.NewContextProvider(mockSearch, textsearch.Config{
        SearchTime:               textsearch.BeforeInvoke,
        RecentMessageMemoryLimit: 6,
    })

    a := foundryprovider.NewAgent(demo.FoundryProjectEndpoint, token, foundryprovider.ModelDeployment(demo.FoundryModel),
        foundryprovider.AgentConfig{
            Instructions: "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.",
            Config: agent.Config{
                ContextProviders: []agent.ContextProvider{searchProvider},
                Middlewares:      []agent.Middleware{logger},
            },
            DisableStoreOutput: true,
        })

取得を実行するタイミングを選択します。

  • textsearch.BeforeInvoke は、各実行の前に検索し、書式設定された結果をモデル コンテキストに挿入します。 これが既定値です。
  • textsearch.OnDemandFunctionCalling は、モデルが追加のコンテキストを要求できるように、検索ツールを公開します。 関数ツールの自動呼び出しが有効になっているプロバイダーを使用します。

RecentMessageMemoryLimit 必要に応じて、セッション内の個々のメッセージを保持して、自動検索クエリを強化します。 明示的なセッションを再利用して、このクエリ コンテキストを保持します。 これは、長期的な会話ストレージではありません。

自動検索診断を表示するように textsearch.Config.Logger を構成します。 検索機能でアクセス制御を適用し、取得したテキストクエリとモデル生成検索クエリを信頼できない入力として扱います。

メモリ内ベクター検索、Qdrant、カスタム取得、Foundry ファイル検索、Neo4j GraphRAG については、 Go RAG サンプル を参照してください。 組み込みストアとその制限事項については、 Vector ストアの統合に関する説明を参照してください。

グラフ ラグ

Cyher クエリでグラフ トラバーサルエンリッチ検索を使用する GraphRAG については、Neo4j GraphRAG プロバイダーを参照してください。

次のステップ