RAG

Microsoft Agent Framework는 모델 호출 전에 검색된 콘텐츠를 추가하는 컨텍스트 공급자를 통해 RAG(검색 보강 생성)를 지원하고 모델이 요청 시 접지 데이터를 검색할 수 있도록 하는 검색 도구를 지원합니다.

검색과 함께 대화/세션 패턴은 대화 및 메모리 개요를 참조하세요. 서비스별 설정은 Azure AI 검색, Microsoft FoundryNeo4j를 참조하세요.

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 검색 또는 웹 검색 엔진과 같은 모든 검색 기술을 사용하여 구현할 수 있습니다.

Tip

검색 결과에 벡터 저장소를 사용하는 방법에 대한 자세한 내용은 Vector 저장소 통합 을 참조하세요.

다음은 쿼리를 기반으로 미리 정의된 결과를 반환하는 모의 검색 함수의 예입니다. 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 .

옵션 Type 설명 Default
검색시간 TextSearchProviderOptions.TextSearchBehavior 검색을 실행해야 하는 시기를 나타냅니다. 에이전트를 실행할 때마다 또는 함수 호출을 통해 주문형으로 두 가지 옵션이 있습니다. TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke
FunctionToolName string 주문형 모드에서 작동할 때 노출된 검색 도구의 이름입니다. "검색"
FunctionToolDescription string 주문형 모드에서 작동할 때 노출된 검색 도구에 대한 설명입니다. "사용자 질문에 대답하는 데 도움이 되는 추가 정보를 검색할 수 있습니다."
[문맥 프롬프트] string 결과에 접두사로 추가된 컨텍스트 프롬프트입니다. "## 추가 컨텍스트\n사용자에게 응답할 때 원본 문서에서 다음 정보를 고려합니다."
CitationsPrompt string 인용을 요청하기 위해 결과 후에 추가된 명령입니다. "문서 이름과 링크를 사용할 수 있는 경우 문서 이름과 링크가 있는 원본 문서에 인용을 포함합니다."
ContextFormatter Func<IList<TextSearchProvider.TextSearchResult>, string> 결과 목록의 서식을 완전히 사용자 지정하는 선택적 대리자입니다. 제공된 ContextPromptCitationsPrompt 경우 무시됩니다. null
RecentMessageMemoryLimit int 메모리에 유지하고 검색을 위한 BeforeAIInvoke 검색 입력을 생성할 때 포함할 최근 대화 메시지(사용자 및 도우미 모두)의 수입니다. 0 (사용 안 함)
RecentMessageRolesIncluded List<ChatRole> 검색 입력을 생성할 때 포함할 최근 메시지를 결정할 때 최근 메시지를 필터링할 형식 목록 ChatRole 입니다. ChatRole.User

Tip

실행 가능한 전체 예제는 .NET 샘플 참조하세요.

에이전트 프레임워크는 네이티브 벡터 저장소 계약 및 create_vector_search_tool(). 도우미는 모든 SupportsVectorSearch 구현을 함수 도구로 변환하므로 모델이 응답하기 전에 접지 데이터를 검색할 수 있습니다.

네이티브 벡터 검색 도구 만들기

먼저 벡터 저장소 모델을 정의하고, 컬렉션을 만들고, 해당 레코드를 로드합니다. 다음 샘플에서는 사용 InMemoryCollectionOpenAIEmbeddingClient하지만 구현하는 모든 네이티브 Agent Framework 컬렉션을 제공할 수 있습니다 SupportsVectorSearch. 그런 다음 선택적 범주 및 등급 필터를 모델에 노출하고, 각 결과를 접지 텍스트에 매핑하고, 에이전트가 답변하기 전에 검색하도록 지시합니다.

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() 합니다.

옵션 Purpose
name 모델에 노출되는 함수 이름을 설정합니다. 여러 검색 도구를 추가할 때 고유한 이름을 사용합니다.
description 모델에서 도구를 사용해야 하는 시기와 이유를 설명합니다.
approval_mode 도구 승인을 always_require 설정합니다.never_require
search_type 선택하거나 keyword_hybrid 검색합니다vector. 컬렉션은 선택한 모드를 지원해야 합니다.
topskip 고정 페이징 값을 설정하거나 모델이 제공하는 형식화된 Param 값을 사용합니다.
filter 이식 Filter 가능한 또는 FilterGroup.를 적용합니다. 필터는 도구 스키마에 노출되는 형식화된 Param 값을 포함할 수 있습니다.
result_mapper 각각 SearchResponse 을 모델의 텍스트 또는 멀티모달 Content 로 변환합니다.

생성된 도구에는 항상 문자열이 query 포함됩니다. 필터 top또는 skip 설정의 모든 Param 값은 유효성이 검사된 추가 도구 인수가 됩니다. 사용 Literal 및 숫자 제약 조건을 사용하여 애플리케이션에서 허용하는 범위 내에서 모델 제공 값을 유지합니다.

다양한 컬렉션 또는 검색 모드에 대한 여러 도구를 만들 수 있습니다. 각 도구에 고유 name 하게 지정하여 description 모델이 적절한 기술 자료를 선택할 수 있도록 합니다.

네이티브 벡터 저장소 선택

네이티브 Python 구현은 메모리 내 검색, Azure AI 검색, pgvector, Qdrant 및 Redis를 사용하는 PostgreSQL에 사용할 수 있습니다. 검색 모드, 패키지 수명 주기, 설치 명령 및 제한 사항이 다릅니다. 구현을 선택하고 구성하려면 Vector 저장소 통합 을 참조하세요. 또한 이 페이지는 현재 별도의 의미 체계 커널 커넥터만 있는 데이터베이스를 식별합니다.

비고

이 기능에 대한 지원은 곧 제공될 예정입니다. 최신 상태는 에이전트 프레임워크 Go 리포지토리 를 참조하세요.

그래프 RAG

GraphRAG가 Cypher 쿼리와 함께 그래프 순회 보강 검색을 사용하는 경우 Neo4j GraphRAG 공급자를 참조하세요.

다음 단계