다음을 통해 공유


RAG(검색 보강 생성)에 플러그 인 사용

AI 에이전트는 종종 외부 원본에서 데이터를 검색하여 접지된 응답을 생성해야 합니다. 이 추가 컨텍스트가 없으면 AI 에이전트가 잘못된 정보를 환각하거나 제공할 수 있습니다. 이 문제를 해결하기 위해 플러그 인을 사용하여 외부 원본에서 데이터를 검색할 수 있습니다.

RAG(검색 증강 세대)에 대한 플러그 인을 고려할 때 다음 두 가지 질문을 스스로에게 질문해야 합니다.

  1. 사용자(또는 AI 에이전트)가 필요한 데이터를 어떻게 "검색"할 수 있나요? 의미 체계 검색 또는 클래식 검색이 필요한가요?
  2. AI 에이전트가 미리 필요한 데이터(미리 가져온 데이터)를 이미 알고 있나요? 아니면 AI 에이전트가 데이터를 동적으로 검색해야 합니까?
  3. 데이터를 안전하게 유지하고 중요한 정보의 과잉 공유를 방지하려면 어떻게 해야 할까요?

RAG(검색 증강 세대)용 플러그 인을 개발할 때 의미 체계 검색과 클래식 검색의 두 가지 유형의 검색을 사용할 수 있습니다.

의미 체계 검색은 벡터 데이터베이스를 활용하여 단순히 키워드를 일치시키는 것이 아니라 쿼리의 의미와 컨텍스트에 따라 정보를 이해하고 검색합니다. 이 메서드를 사용하면 검색 엔진이 동의어, 관련 개념 및 쿼리의 전체 의도와 같은 언어의 뉘앙스를 파악할 수 있습니다.

의미 체계 검색은 사용자 쿼리가 복잡하고 개방형이거나 콘텐츠에 대한 심층적인 이해가 필요한 환경에서 탁월합니다. 예를 들어 "최고의 사진용 스마트폰"을 검색하면 "최고", "스마트폰", "사진"이라는 단어를 일치시키는 대신 스마트폰의 사진 기능 컨텍스트를 고려하는 결과가 생성됩니다.

LLM에 의미 체계 검색 함수를 제공하는 경우 일반적으로 단일 검색 쿼리를 사용하여 함수를 정의하기만 하면 됩니다. 그런 다음 LLM은 이 함수를 사용하여 필요한 정보를 검색합니다. 다음은 Azure AI Search를 사용하여 지정된 쿼리와 유사한 문서를 찾는 의미 체계 검색 함수의 예입니다.

using System.ComponentModel;
using System.Text.Json.Serialization;
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Models;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Embeddings;

public class InternalDocumentsPlugin
{
    private readonly ITextEmbeddingGenerationService _textEmbeddingGenerationService;
    private readonly SearchIndexClient _indexClient;

    public AzureAISearchPlugin(ITextEmbeddingGenerationService textEmbeddingGenerationService, SearchIndexClient indexClient)
    {
        _textEmbeddingGenerationService = textEmbeddingGenerationService;
        _indexClient = indexClient;
    }

    [KernelFunction("Search")]
    [Description("Search for a document similar to the given query.")]
    public async Task<string> SearchAsync(string query)
    {
        // Convert string query to vector
        ReadOnlyMemory<float> embedding = await _textEmbeddingGenerationService.GenerateEmbeddingAsync(query);

        // Get client for search operations
        SearchClient searchClient = _indexClient.GetSearchClient("default-collection");

        // Configure request parameters
        VectorizedQuery vectorQuery = new(embedding);
        vectorQuery.Fields.Add("vector");

        SearchOptions searchOptions = new() { VectorSearch = new() { Queries = { vectorQuery } } };

        // Perform search request
        Response<SearchResults<IndexSchema>> response = await searchClient.SearchAsync<IndexSchema>(searchOptions);

        // Collect search results
        await foreach (SearchResult<IndexSchema> result in response.Value.GetResultsAsync())
        {
            return result.Document.Chunk; // Return text from first result
        }

        return string.Empty;
    }

    private sealed class IndexSchema
    {
        [JsonPropertyName("chunk")]
        public string Chunk { get; set; }

        [JsonPropertyName("vector")]
        public ReadOnlyMemory<float> Vector { get; set; }
    }
}

특성 기반 또는 조건 기반 검색이라고도 하는 클래식 검색은 데이터 세트 내에서 정확한 용어 또는 값을 필터링하고 일치시키는 데 의존합니다. 데이터베이스 쿼리, 인벤토리 검색 및 특정 특성별 필터링이 필요한 상황에 특히 효과적입니다.

예를 들어 사용자가 특정 고객 ID로 주문한 모든 주문을 찾거나 특정 가격 범위 및 범주 내에서 제품을 검색하려는 경우 클래식 검색은 정확하고 신뢰할 수 있는 결과를 제공합니다. 그러나 클래식 검색은 언어의 컨텍스트 또는 변형을 이해할 수 없기 때문에 제한됩니다.

대부분의 경우 기존 서비스는 이미 클래식 검색을 지원합니다. 의미 체계 검색을 구현하기 전에 기존 서비스가 AI 에이전트에 필요한 컨텍스트를 제공할 수 있는지 여부를 고려합니다.

예를 들어 클래식 검색을 사용하여 CRM 시스템에서 고객 정보를 검색하는 플러그 인을 예로 들어보십시오. 여기서 AI는 고객 ID를 GetCustomerInfoAsync 사용하여 함수를 호출하여 필요한 정보를 검색하기만 하면 됩니다.

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class CRMPlugin
{
    private readonly CRMService _crmService;

    public CRMPlugin(CRMService crmService)
    {
        _crmService = crmService;
    }

    [KernelFunction("GetCustomerInfo")]
    [Description("Retrieve customer information based on the given customer ID.")]
    public async Task<Customer> GetCustomerInfoAsync(string customerId)
    {
        return await _crmService.GetCustomerInfoAsync(customerId);
    }
}

의미 체계 검색을 사용하여 동일한 검색 기능을 달성하는 것은 의미 체계 쿼리의 비결정적 특성으로 인해 불가능하거나 비실용적일 수 있습니다.

각 사용 시기

의미 체계와 클래식 검색 중에서 선택하는 것은 쿼리의 특성에 따라 달라집니다. 사용자가 자연어를 사용하여 질문을 하거나 제품을 찾을 수 있는 기술 자료 및 고객 지원과 같은 콘텐츠가 많은 환경에 이상적입니다. 반면에 클래식 검색은 정밀도와 정확한 일치가 중요할 때 사용해야 합니다.

일부 시나리오에서는 포괄적인 검색 기능을 제공하기 위해 두 방법을 모두 결합해야 할 수 있습니다. 예를 들어 전자 상거래 저장소의 고객을 지원하는 챗봇은 의미 체계 검색을 사용하여 사용자 쿼리 및 클래식 검색을 이해하여 가격, 브랜드 또는 가용성과 같은 특정 특성을 기반으로 제품을 필터링할 수 있습니다.

다음은 의미 체계와 클래식 검색을 결합하여 전자 상거래 데이터베이스에서 제품 정보를 검색하는 플러그 인의 예입니다.

using System.ComponentModel;
using Microsoft.SemanticKernel;

public class ECommercePlugin
{
    [KernelFunction("search_products")]
    [Description("Search for products based on the given query.")]
    public async Task<IEnumerable<Product>> SearchProductsAsync(string query, ProductCategories category = null, decimal? minPrice = null, decimal? maxPrice = null)
    {
        // Perform semantic and classic search with the given parameters
    }
}

동적 및 미리 가져온 데이터 검색

RAG(검색 증강 생성)용 플러그 인을 개발할 때 데이터 검색 프로세스가 정적인지 동적인지도 고려해야 합니다. 이렇게 하면 필요한 경우에만 데이터를 검색하여 AI 에이전트의 성능을 최적화할 수 있습니다.

동적 데이터 검색

대부분의 경우 사용자 쿼리는 AI 에이전트가 검색해야 하는 데이터를 결정합니다. 예를 들어 사용자가 서로 다른 두 제품의 차이점을 요청할 수 있습니다. 그런 다음 AI 에이전트는 함수 호출을 사용하여 응답을 생성하기 위해 데이터베이스 또는 API에서 제품 정보를 동적으로 검색해야 합니다. 가능한 모든 제품 정보를 미리 가져와서 AI 에이전트에 제공하는 것은 비현실적입니다.

다음은 동적 데이터 검색이 필요한 사용자와 AI 에이전트 간의 앞뒤로 채팅하는 예입니다.

역할 메시지
🔵사용자 당신은 최고의 매트리스에 대해 말해 줄 수 있습니까?
🔴도우미(함수 호출) Products.Search("mattresses")
🟢도구 [{"id": 25323, "name": "Cloud Nine"},{"id": 63633, "name": "Best Sleep"}]
🔴도우미 물론입니다! 클라우드 나인과 최고의 절전 모드가 모두 있습니다.
🔵사용자 이 둘의 차이점은 무엇인가요?
🔴도우미(함수 호출) Products.GetDetails(25323) Products.GetDetails(63633)
🟢도구 { "id": 25323, "name": "Cloud Nine", "price": 1000, "material": "Memory foam" }
🟢도구 { "id": 63633, "name": "Best Sleep", "price": 1200, "material": "Latex" }
🔴도우미 Cloud Nine은 메모리 폼으로 만들어졌으며 비용은 $1000입니다. 최고의 수면은 라텍스로 만들어졌으며 비용은 $1200입니다.

미리 가져온 데이터 검색

정적 데이터 검색에는 외부 원본에서 데이터를 가져오고 항상 AI 에이전트에 제공하는 작업이 포함됩니다. 이는 모든 요청에 데이터가 필요하거나 데이터가 비교적 안정적이며 자주 변경되지 않는 경우에 유용합니다.

예를 들어 항상 현지 날씨에 대한 질문에 대답하는 에이전트를 예로 들어 보세요. 날씨 API가 WeatherPlugin있다고 가정하면 날씨 API에서 날씨 데이터를 미리 가져와 채팅 기록에 제공할 수 있습니다. 이를 통해 에이전트는 API에서 데이터를 요청하는 시간을 낭비하지 않고 날씨에 대한 응답을 생성할 수 있습니다.

using System.Text.Json;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

IKernelBuilder builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);
builder.Plugins.AddFromType<WeatherPlugin>();
Kernel kernel = builder.Build();

// Get the weather
var weather = await kernel.Plugins.GetFunction("WeatherPlugin", "get_weather").InvokeAsync(kernel);

// Initialize the chat history with the weather
ChatHistory chatHistory = new ChatHistory("The weather is:\n" + JsonSerializer.Serialize(weather));

// Simulate a user message
chatHistory.AddUserMessage("What is the weather like today?");

// Get the answer from the AI agent
IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory);

데이터 보안 유지

외부 원본에서 데이터를 검색할 때는 데이터가 안전하고 중요한 정보가 노출되지 않도록 하는 것이 중요합니다. 중요한 정보의 과잉 공유를 방지하기 위해 다음 전략을 사용할 수 있습니다.

전략 설명
사용자의 인증 토큰 사용 AI 에이전트에서 사용자의 정보를 검색하는 데 사용하는 서비스 주체를 만들지 않습니다. 이렇게 하면 사용자가 검색된 정보에 액세스할 수 있는지 확인하기가 어렵습니다.
검색 서비스 다시 생성 방지 벡터 DB를 사용하여 새 검색 서비스를 만들기 전에 필요한 데이터가 있는 서비스에 대한 검색 서비스가 이미 있는지 확인합니다. 기존 서비스를 다시 사용하면 중요한 콘텐츠가 중복되는 것을 방지하고, 기존 액세스 제어를 활용하며, 사용자가 액세스할 수 있는 데이터만 반환하는 기존 필터링 메커니즘을 사용할 수 있습니다.
콘텐츠 대신 벡터 DB에 참조 저장 중요한 콘텐츠를 벡터 DB에 복제하는 대신 실제 데이터에 대한 참조를 저장할 수 있습니다. 사용자가 이 정보에 액세스하려면 먼저 해당 인증 토큰을 사용하여 실제 데이터를 검색해야 합니다.

다음 단계

이제 외부 원본의 데이터를 사용하여 AI 에이전트를 접지하는 방법을 알아보고 AI 에이전트를 사용하여 비즈니스 프로세스를 자동화하는 방법을 알아볼 수 있습니다. 자세한 내용은 작업 자동화 함수 사용을 참조 하세요.