Compartilhar via


Provedor de memória de histórico de chat

ChatHistoryMemoryProvider é um Provedor de Contexto de IA que armazena todo o histórico de chat em um repositório de vetores e recupera mensagens relacionadas para aumentar a conversa atual. Isso permite que os agentes lembrem o contexto relevante de interações anteriores usando a pesquisa de similaridade semântica.

Como funciona

O provedor opera em duas fases:

  1. Armazenamento: após cada invocação de agente, novas mensagens de solicitação e resposta são armazenadas no repositório de vetores com inserções geradas de seu conteúdo.

  2. Recuperação: antes de cada invocação (ou sob demanda por meio da chamada de função), o provedor pesquisa no repositório de vetores mensagens semanticamente semelhantes à entrada do usuário atual e as injeta como contexto.

As mensagens armazenadas têm escopo usando identificadores configuráveis (aplicativo, agente, usuário, sessão) permitindo controle refinado sobre qual histórico é armazenado e pesquisável.

Pré-requisitos

Dica

Consulte a documentação de integração do Vector Stores para obter mais informações sobre a abstração vectorData e implementações disponíveis.

Usage

O exemplo a seguir demonstra a criação de um agente com o ChatHistoryMemoryProvider uso de um repositório de vetores na memória.

Observe que o uso deve ser apenas de ID de usuário para o escopo de pesquisa. Isso permite que o agente lembre informações de conversas anteriores com o mesmo usuário para informar novas respostas.

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") 
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var embeddingDeploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME") 
    ?? "text-embedding-3-large";

// Create a vector store with an embedding generator.
// For production, replace InMemoryVectorStore with a persistent store.
VectorStore vectorStore = new InMemoryVectorStore(new InMemoryVectorStoreOptions()
{
    EmbeddingGenerator = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential())
        .GetEmbeddingClient(embeddingDeploymentName)
        .AsIEmbeddingGenerator()
});

// Create the agent with ChatHistoryMemoryProvider
AIAgent agent = new AzureOpenAIClient(
    new Uri(endpoint),
    new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsAIAgent(new ChatClientAgentOptions
    {
        ChatOptions = new() { Instructions = "You are a helpful assistant." },
        Name = "MemoryAgent",
        AIContextProviders = [new ChatHistoryMemoryProvider(
            vectorStore,
            collectionName: "chathistory",
            vectorDimensions: 3072,
            session => new ChatHistoryMemoryProvider.State(
                // Configure where messages are stored
                storageScope: new() { UserId = "user-123", SessionId = Guid.NewGuid().ToString() },
                // Configure where to search (can be broader than storage scope)
                searchScope: new() { UserId = "user-123" }))]
    });

// Start a session and interact with the agent
AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("I prefer window seats on flights.", session));

// Start a new session - the agent can recall the user's preference
AgentSession session2 = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("Book me a flight to Seattle.", session2));

Dica

Utilize diferentes configurações de storageScope e searchScope para controlar o isolamento de memória. Por exemplo, armazene por sessão, mas pesquise todas as sessões de um usuário.

Opções de configuração

A ChatHistoryMemoryProviderOptions classe fornece configuração para o comportamento do provedor.

Comportamento de pesquisa

Opção Tipo Default Descrição
SearchTime SearchBehavior BeforeAIInvoke Controla quando a pesquisa de memória é executada.

A SearchBehavior enumeração tem dois valores:

  • BeforeAIInvoke: pesquisa automaticamente memórias relevantes antes de cada invocação de IA e as injeta como mensagens de contexto. Esse é o comportamento padrão.
  • OnDemandFunctionCalling: expõe uma ferramenta de função que o modelo de IA pode invocar para pesquisar memórias sob demanda. Use isso quando quiser que o modelo decida quando recuperar memórias.

Opções de resultado da pesquisa

Opção Tipo Default Descrição
MaxResults int? 3 Número máximo de resultados do histórico de chat a serem recuperados por pesquisa.
ContextPrompt string? "## Memories\nConsider the following memories..." O texto do prompt prefixado nos resultados da pesquisa antes da injeção.

Opções de ferramenta funcional sob demanda

Essas opções só se aplicam quando SearchTime é definida como OnDemandFunctionCalling:

Opção Tipo Default Descrição
FunctionToolName string? "Search" O nome da ferramenta de pesquisa exposta ao modelo.
FunctionToolDescription string? "Allows searching for related previous chat history..." A descrição da ferramenta de busca.

Filtragem de mensagens

Opção Tipo Default Descrição
SearchInputMessageFilter Func<IEnumerable<ChatMessage>, IEnumerable<ChatMessage>>? Somente mensagens externas Filtro aplicado a mensagens de solicitação ao construir consultas de pesquisa.
StorageInputRequestMessageFilter Func<IEnumerable<ChatMessage>, IEnumerable<ChatMessage>>? Somente mensagens externas Filtro aplicado a mensagens de solicitação antes do armazenamento.
StorageInputResponseMessageFilter Func<IEnumerable<ChatMessage>, IEnumerable<ChatMessage>>? Sem-filtro Filtro aplicado a mensagens de resposta antes do armazenamento.

Registro em log e telemetria

Opção Tipo Default Descrição
EnableSensitiveTelemetryData bool false Quando truedados confidenciais (IDs de usuário, conteúdo da mensagem) aparecem em logs inalterados.
Redactor Redactor? Redator que substitui o texto por "<redacted>" Redator personalizado para valores confidenciais ao registrar em log. Ignorado se EnableSensitiveTelemetryData for true.

Gerenciamento de estado

Opção Tipo Default Descrição
StateKey string? Nome do tipo de provedor Chave usada para armazenar o estado do provedor em AgentSession.StateBag. Substitua ao usar várias ChatHistoryMemoryProvider instâncias na mesma sessão.

Configuração do âmbito

A ChatHistoryMemoryProviderScope classe controla como as mensagens são organizadas e filtradas no repositório de vetores.

Propriedade Tipo Descrição
ApplicationId string? Mensagens de escopo para um aplicativo específico. Se não estiver definido, abrange todos os aplicativos.
AgentId string? Direcione as mensagens para um agente específico. Se não estiver definido, abrange todos os agentes.
UserId string? Direcionar mensagens para um usuário específico. Se não estiver definido, abrange todos os usuários.
SessionId string? Delimitar mensagens a uma sessão específica.

Escopo de armazenamento versus escopo de pesquisa

A ChatHistoryMemoryProvider.State classe aceita dois escopos:

  • storageScope: define como as novas mensagens são marcadas quando armazenadas. Todas as propriedades de escopo são gravadas como metadados.
  • searchScope: define os critérios de filtro ao pesquisar. Defina este escopo de modo a ser mais amplo que o armazenamento, para permitir pesquisas em várias sessões ou agentes.

Exemplo: Armazene por sessão, pesquise em todas as sessões por um usuário:

new ChatHistoryMemoryProvider.State(
    storageScope: new() { UserId = "user-123", SessionId = "session-456" },
    searchScope: new() { UserId = "user-123" })

Considerações de segurança

Aviso

Examine essas considerações de segurança antes de implantar a ChatHistoryMemoryProvider em produção.

  • Injeção de prompt indireto: as mensagens recuperadas do repositório de vetores são injetadas no contexto LLM. Se o repositório de vetores estiver comprometido, o conteúdo do adversário poderá influenciar o comportamento de LLM. Os dados da loja são aceitos como estão sem validação.

  • PII e dados confidenciais: as mensagens de conversa (incluindo entradas do usuário e respostas LLM) são armazenadas como vetores. Essas mensagens podem conter PII ou informações confidenciais. Verifique se o repositório de vetores possui controles de acesso adequados e criptografia em repouso.

  • Ferramenta de pesquisa sob demanda: ao usar OnDemandFunctionCalling, o modelo de IA controla quando e o que pesquisar. A consulta de pesquisa é gerada por IA e deve ser tratada como entrada não confiável pela implementação do repositório de vetores.

  • Log de rastreamento: quando LogLevel.Trace estiver habilitado, as consultas e os resultados completos da pesquisa poderão ser registrados. Esses dados podem conter PII. Use a opção Redactor ou desabilite a telemetria confidencial na produção.

Esse provedor ainda não está disponível para Python. Consulte a guia C# para obter exemplos de uso.

Próximas Etapas