Partilhar via


Save user and conversation data (Guardar dados da conversação e do utilizador)

APLICA-SE A: SDK v4

Um bot é inerentemente apátrida. Depois que o bot é implantado, ele pode não ser executado no mesmo processo ou na mesma máquina de um turno para o outro. No entanto, seu bot pode precisar rastrear o contexto de uma conversa para que ele possa gerenciar seu comportamento e lembrar as respostas a perguntas anteriores. Os recursos de estado e armazenamento do SDK do Bot Framework permitem que você adicione estado ao seu bot. Os bots usam gerenciamento de estado e objetos de armazenamento para gerenciar e persistir o estado. O gerenciador de estado fornece uma camada de abstração que permite acessar propriedades de estado usando acessadores de propriedade, independentemente do tipo de armazenamento subjacente.

Nota

Os SDKs JavaScript, C# e Python do Bot Framework continuarão a ser suportados, no entanto, o Java SDK está sendo desativado com suporte final de longo prazo terminando em novembro de 2023.

Os bots existentes construídos com o Java SDK continuarão a funcionar.

Para a criação de novos bots, considere usar o Microsoft Copilot Studio e leia sobre como escolher a solução de copilot certa.

Para obter mais informações, consulte O futuro da criação de bots.

Pré-requisitos

Sobre este exemplo

Ao receber a entrada do usuário, este exemplo verifica o estado da conversa armazenada para ver se esse usuário foi solicitado anteriormente a fornecer seu nome. Caso contrário, o nome do usuário é solicitado e essa entrada é armazenada no estado do usuário. Em caso afirmativo, o nome armazenado no estado do usuário é usado para conversar com o usuário e seus dados de entrada, juntamente com o tempo recebido e o ID do canal de entrada, são retornados ao usuário. Os valores de ID de hora e canal são recuperados dos dados de conversa do usuário e, em seguida, salvos no estado de conversa. O diagrama a seguir mostra a relação entre o bot, o perfil de usuário e as classes de dados de conversação.

Definir classes

A primeira etapa na configuração do gerenciamento de estado é definir as classes que contêm as informações a serem gerenciadas no estado de usuário e conversação. O exemplo usado neste artigo define as seguintes classes:

  • No UserProfile.cs, você define uma UserProfile classe para as informações do usuário que o bot coletará.
  • Além ConversationData.cs, você define uma ConversationData classe para controlar nosso estado de conversação enquanto coleta informações do usuário.

Os exemplos de código a seguir mostram as definições para as UserProfile classes e ConversationData .

UserProfile.cs

public class UserProfile
{
    public string Name { get; set; }
}

ConversationData.cs

public class ConversationData
{
    // The time-stamp of the most recent incoming message.
    public string Timestamp { get; set; }

    // The ID of the user's channel.
    public string ChannelId { get; set; }

    // Track whether we have already asked the user's name
    public bool PromptedUserForName { get; set; } = false;
}

Criar objetos de conversação e estado do utilizador

Em seguida, você registra MemoryStorage que é usado para criar UserState e ConversationState objetos. Os objetos de estado de usuário e conversação são criados em Startup e a dependência é injetada no construtor do bot. Outros serviços para um bot que estão registrados são: um provedor de credenciais, um adaptador e a implementação do bot.

Startup.cs

// {
//     TypeNameHandling = TypeNameHandling.All,
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state");

// With a custom JSON SERIALIZER, use this instead.
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state", jsonSerializer);

/* END AZURE BLOB STORAGE */

Bots/StateManagementBot.cs

private BotState _conversationState;
private BotState _userState;

public StateManagementBot(ConversationState conversationState, UserState userState)
{
    _conversationState = conversationState;
    _userState = userState;
}

Adicionar acessadores de propriedade de estado

Agora você cria acessadores de propriedade usando o CreateProperty método que fornece um identificador para o BotState objeto. Cada acessador de propriedade de estado permite que você obtenha ou defina o valor da propriedade de estado associada. Antes de usar as propriedades de estado, use cada acessador para carregar a propriedade do armazenamento e obtê-la do cache de estado. Para obter a chave com escopo adequado associada à propriedade state, chame o GetAsync método.

Bots/StateManagementBot.cs

var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));

Estado de acesso a partir do seu bot

A seção anterior aborda as etapas de tempo de inicialização para adicionar acessadores de propriedade de estado ao nosso bot. Agora, você pode usar esses acessadores em tempo de execução para ler e gravar informações de estado. O código de exemplo abaixo usa o seguinte fluxo lógico:

  • Se userProfile.Name estiver vazio e conversationData.PromptedUserForName for true, você recuperará o nome de usuário fornecido e armazená-lo no estado do usuário.
  • Se userProfile.Name estiver vazio e conversationData.PromptedUserForName for falso, você pede o nome do usuário.
  • Se userProfile.Name tiver sido armazenado anteriormente, você recupera o tempo da mensagem e o ID do canal da entrada do usuário, ecoa todos os dados de volta para o usuário e armazena os dados recuperados no estado da conversa.

Bots/StateManagementBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // Get the state properties from the turn context.

    var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
    var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

    var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());

    if (string.IsNullOrEmpty(userProfile.Name))
    {
        // First time around this is set to false, so we will prompt user for name.
        if (conversationData.PromptedUserForName)
        {
            // Set the name to what the user provided.
            userProfile.Name = turnContext.Activity.Text?.Trim();

            // Acknowledge that we got their name.
            await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

            // Reset the flag to allow the bot to go through the cycle again.
            conversationData.PromptedUserForName = false;
        }
        else
        {
            // Prompt the user for their name.
            await turnContext.SendActivityAsync($"What is your name?");

            // Set the flag to true, so we don't prompt in the next turn.
            conversationData.PromptedUserForName = true;
        }
    }
    else
    {
        // Add message details to the conversation data.
        // Convert saved Timestamp to local DateTimeOffset, then to string for display.
        var messageTimeOffset = (DateTimeOffset)turnContext.Activity.Timestamp;
        var localMessageTime = messageTimeOffset.ToLocalTime();
        conversationData.Timestamp = localMessageTime.ToString();
        conversationData.ChannelId = turnContext.Activity.ChannelId.ToString();

        // Display state data.
        await turnContext.SendActivityAsync($"{userProfile.Name} sent: {turnContext.Activity.Text}");
        await turnContext.SendActivityAsync($"Message received at: {conversationData.Timestamp}");
        await turnContext.SendActivityAsync($"Message received from: {conversationData.ChannelId}");
    }
}

Antes de sair do manipulador de turnos, use o método SaveChangesAsync() dos objetos de gerenciamento de estado para gravar todas as alterações de estado de volta ao armazenamento.

Bots/StateManagementBot.cs

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    await base.OnTurnAsync(turnContext, cancellationToken);

    // Save any state changes that might have occurred during the turn.
    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}

Teste seu bot

  1. Baixe e instale o mais recente Bot Framework Emulator
  2. Execute a amostra localmente na sua máquina. Se precisar de instruções, consulte o LEIA-ME para C#, JavaScript, Java ou Python.
  3. Use o emulador para testar seu bot de exemplo.

Informações adicionais

Este artigo descreveu como você pode adicionar estado ao seu bot. Consulte a tabela a seguir para obter mais informações sobre tópicos relacionados.

Tópico Notas
Privacidade Caso pretenda armazenar dados pessoais do utilizador, deverá assegurar o cumprimento do Regulamento Geral de Proteção de Dados.
Gestão de estados Todas as chamadas de gerenciamento de estado são assíncronas e o último gravador ganha por padrão. Na prática, você deve obter, definir e salvar o estado o mais próximo possível em seu bot. Para obter uma discussão sobre como implementar o bloqueio otimista, consulte Implementar armazenamento personalizado para seu bot.
Dados críticos para os negócios Use o estado do bot para armazenar preferências, nome de usuário ou a última coisa que eles pediram, mas não o use para armazenar dados corporativos críticos. Para dados críticos, crie seus próprios componentes de armazenamento ou grave diretamente no armazenamento.
Reconhecedor-Texto O exemplo usa as bibliotecas Microsoft/Recognizers-Text para analisar e validar a entrada do usuário. Para obter mais informações, consulte a página de visão geral .

Próximos passos

Saiba como fazer uma série de perguntas ao usuário, validar suas respostas e salvar suas entradas.