Compartilhar via


Adicionando RAG (Geração Aumentada de Recuperação) a Agentes de Kernel Semântico

Aviso

A funcionalidade RAG do Agente kernel semântico é experimental, sujeita a alterações e só será finalizada com base em comentários e avaliação.

Usando o TextSearchProvider para RAG

Permite Microsoft.SemanticKernel.Data.TextSearchProvider que os agentes recuperem documentos relevantes com base na entrada do usuário e os integrem ao contexto do agente, proporcionando respostas mais informadas. Ele integra uma Microsoft.SemanticKernel.Data.ITextSearch instância com agentes kernel semânticos. Existem várias ITextSearch implementações, dando suporte a pesquisas de similaridade em repositórios de vetores e integração do mecanismo de pesquisa. Encontre mais informações aqui.

Também fornecemos um Microsoft.SemanticKernel.Data.TextSearchStore, o qual oferece armazenamento de vetor simples e estruturado de dados textuais para fins de Geração Aumentada por Recuperação. TextSearchStore tem um esquema interno para armazenar e recuperar dados textuais em um repositório de vetores. Se você quiser usar seu próprio esquema para armazenamento, confira VectorStoreTextSearch.

Configurando o TextSearchProvider

Pode TextSearchProvider ser usado com um VectorStore e TextSearchStore para armazenar e pesquisar documentos de texto.

O exemplo a seguir demonstra como configurar e usar o TextSearchProvider com um TextSearchStore e InMemoryVectorStore para que um agente execute RAG simples sobre texto.

// Create an embedding generator using Azure OpenAI.
var embeddingGenerator = new AzureOpenAIClient(new Uri("<Your_Azure_OpenAI_Endpoint>"), new AzureCliCredential())
    .GetEmbeddingClient("<Your_Deployment_Name>")
    .AsIEmbeddingGenerator(1536);

// Create a vector store to store documents.
var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = embeddingGenerator });

// Create a TextSearchStore for storing and searching text documents.
using var textSearchStore = new TextSearchStore<string>(vectorStore, collectionName: "FinancialData", vectorDimensions: 1536);

// Upsert documents into the store.
await textSearchStore.UpsertTextAsync(new[]
{
    "The financial results of Contoso Corp for 2024 is as follows:\nIncome EUR 154 000 000\nExpenses EUR 142 000 000",
    "The Contoso Corporation is a multinational business with its headquarters in Paris."
});

// Create an agent.
Kernel kernel = new Kernel();
ChatCompletionAgent agent = new()
{
    Name = "FriendlyAssistant",
    Instructions = "You are a friendly assistant",
    Kernel = kernel,
    // This setting must be set to true when using the on-demand RAG feature
    UseImmutableKernel = true
};

// Create an agent thread and add the TextSearchProvider.
ChatHistoryAgentThread agentThread = new();
var textSearchProvider = new TextSearchProvider(textSearchStore);
agentThread.AIContextProviders.Add(textSearchProvider);

// Use the agent with RAG capabilities.
ChatMessageContent response = await agent.InvokeAsync("Where is Contoso based?", agentThread).FirstAsync();
Console.WriteLine(response.Content);

Recursos avançados: citações e filtragem

O TextSearchStore suporta recursos avançados, como filtrar resultados por namespace e incluir citações em respostas.

Incluindo citações

Documentos no TextSearchStore podem incluir metadados, como nomes de origem e links, permitindo a geração de citações nas respostas do agente.

await textSearchStore.UpsertDocumentsAsync(new[]
{
    new TextSearchDocument
    {
        Text = "The financial results of Contoso Corp for 2023 is as follows:\nIncome EUR 174 000 000\nExpenses EUR 152 000 000",
        SourceName = "Contoso 2023 Financial Report",
        SourceLink = "https://www.contoso.com/reports/2023.pdf",
        Namespaces = ["group/g2"]
    }
});

Quando o TextSearchProvider recuperar este documento, ele incluirá, por padrão, o nome da fonte e o link em sua resposta.

Filtragem por Namespace

Ao atualizar documentos, você pode, opcionalmente, fornecer um ou mais namespaces para cada documento. Namespaces podem ser qualquer cadeia de caracteres que defina o escopo de um documento. Em seguida, você pode configurar os resultados da TextSearchStore pesquisa para limitar apenas os registros que correspondem ao namespace solicitado.

using var textSearchStore = new TextSearchStore<string>(
    vectorStore,
    collectionName: "FinancialData",
    vectorDimensions: 1536,
    new() { SearchNamespace = "group/g2" }
);

Comparação entre RAG automático e sob demanda

Ele TextSearchProvider pode executar pesquisas automaticamente durante cada invocação de agente ou permitir pesquisas sob demanda por meio de chamadas de ferramenta quando o agente precisar de informações adicionais.

A configuração padrão é BeforeAIInvoke, o que significa que as pesquisas serão executadas antes de cada invocação de agente usando a mensagem passada para o agente. Isso pode ser alterado para OnDemandFunctionCalling, o que permitirá que o Agente faça uma chamada de ferramenta para fazer pesquisas usando uma cadeia de caracteres de pesquisa de escolha do agente.

var options = new TextSearchProviderOptions
{
    SearchTime = TextSearchProviderOptions.RagBehavior.OnDemandFunctionCalling,
};

var provider = new TextSearchProvider(mockTextSearch.Object, options: options);

Aviso

Ao usar o TextSearchProvider com OnDemandFunctionCalling, a configuração UseImmutableKernel no agente deve ser definida para true, pois o recurso requer a clonagem do kernel ao invocar o agente. Observe que ao definir UseImmutableKernel para true, quaisquer modificações de dados do kernel feitas durante a invocação do agente, por exemplo, por meio de plug-ins, não serão mantidas após a conclusão da invocação.

Opções do Provedor de Busca de Textos

O TextSearchProvider pode ser configurado com várias opções para personalizar seu comportamento. As opções são fornecidas usando a TextSearchProviderOptions classe para o TextSearchProvider construtor.

TOP

Especifica o número máximo de resultados a serem retornados da pesquisa de similaridade.

  • Padrão: 3

Tempo de Pesquisa

Controla quando a pesquisa de texto é executada. As opções incluem:

  • BeforeAIInvoke: uma pesquisa é executada sempre que o modelo/agente é invocado, pouco antes da invocação, e os resultados são fornecidos ao modelo/agente por meio do contexto de invocação.
  • OnDemandFunctionCalling: uma pesquisa pode ser executada pelo modelo/agente sob demanda por meio da chamada de função.

PluginFunctionName

Especifica o nome do método de plug-in que será disponibilizado para pesquisa se SearchTime for definido como OnDemandFunctionCalling.

  • Padrão: "Pesquisar"

DescriçãoDaFunçãoDoPlugin

Fornece uma descrição do método de plug-in que será disponibilizado para pesquisa se SearchTime estiver definido como OnDemandFunctionCalling.

  • Padrão: "Permite pesquisar informações adicionais para ajudar a responder à pergunta do usuário".

ContextPrompt

Ao fornecer as partes de texto para o modelo de IA na invocação, um prompt é necessário para indicar ao modelo de IA para que servem as partes de texto e como elas devem ser usadas. Essa configuração permite substituir o sistema de mensagens padrão que é integrado ao TextSearchProvider.

IncludeCitationsPrompt

Ao fornecer os trechos de texto para o modelo de IA na invocação, um comando é necessário para informar ao modelo de IA se e como fazer citações. Essa configuração permite substituir o sistema de mensagens padrão que é integrado ao TextSearchProvider.

ContextFormatter

Este retorno de chamada opcional pode ser usado para completamente personalizar o texto que é gerado pelo TextSearchProvider. Por padrão, o TextSearchProvider produzirá um texto que inclui

  1. Um prompt informando ao modelo de IA para que servem os fragmentos de texto.
  2. A lista de partes de texto com links e nomes de origem.
  3. Um prompt instruindo o modelo de IA sobre como incluir citações.

Você pode escrever seu próprio resultado implementando e fornecendo esta função de retorno.

Observação: Se este delegado for fornecido, as configurações ContextPrompt e IncludeCitationsPrompt não serão usadas.

Combinando o RAG com outros provedores

TextSearchProvider pode ser combinado com outros provedores, como mem0 ou WhiteboardProvider, para criar agentes com recursos de memória e recuperação.

// Add both mem0 and TextSearchProvider to the agent thread.
agentThread.AIContextProviders.Add(mem0Provider);
agentThread.AIContextProviders.Add(textSearchProvider);

// Use the agent with combined capabilities.
ChatMessageContent response = await agent.InvokeAsync("What was Contoso's income for 2023?", agentThread).FirstAsync();
Console.WriteLine(response.Content);

Combinando esses recursos, os agentes podem oferecer uma experiência mais personalizada e com reconhecimento de contexto.

Próximas etapas

Em breve

Mais informações em breve.

Em breve

Mais informações em breve.