Gravar diretamente no armazenamento

APLICA-SE A: SDK v4

Você pode ler e gravar diretamente em seu objeto de armazenamento sem usar middleware ou objeto de contexto. Isso pode ser apropriado para dados que seu bot usa para preservar a conversa ou dados originados de uma fonte fora do fluxo de conversa do bot. Nesse modelo de armazenamento de dados, os dados são lidos diretamente do armazenamento em vez de usar um gerenciador de estado. Os exemplos de código neste artigo mostram como ler e gravar dados no armazenamento usando os armazenamentos de memória, Cosmos DB, Blob do Azure e transcrição do Blob do Azure.

Observação

Os SDKs do Bot Framework para JavaScript, C# e Python continuarão a ter suporte, no entanto, o SDK para Java está sendo desativado. Seu suporte final de longo prazo será encerrado em novembro de 2023. Somente correções críticas de segurança e de bugs serão realizadas neste repositório.

Os bots existentes criados com o SDK para Java continuarão a funcionar.

Para a criação de novos bots, considere usar o Power Virtual Agents e leia sobre como escolher a solução de chatbot mais adequada.

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

Pré-requisitos

Observação

Você pode instalar os modelos do Visual Studio.

  1. No menu, escolha Extensões e depois Gerenciar Extensões.
  2. No diálogo Gerenciar Extensões, procure e instale os modelos do SDK do Bot Framework v4 para o Visual Studio.

Para obter informações sobre a implantação de bots .NET no Azure, confira como Provisionar e publicar um bot.

Sobre este exemplo

O código de exemplo neste artigo começa com a estrutura de um bot de eco básico e estende a funcionalidade dele, adicionando códigos (fornecidos abaixo). Esse código estendido cria uma lista para preservar as entradas de usuário conforme elas são recebidas. A cada turno, a lista completa de entradas de usuário salvas na memória é ecoada de volta para o usuário. A estrutura de dados que contém essa lista de entradas é então modificada para ser salva no armazenamento. Vários tipos de armazenamento são explorados à medida que outras funcionalidades são adicionadas a esse código de exemplo.

Armazenamento de memória

O SDK do Bot Framework permite que você armazene entradas do usuário usando o armazenamento na memória. Como o armazenamento na memória é limpo sempre que o bot é reiniciado, ele é mais adequado para fins de teste e não se destina ao uso em produção. Os tipos de armazenamento persistentes, como o armazenamento de banco de dados, são melhores para bots de produção.

Crie um bot básico

O restante deste tópico se baseia em um bot de Eco. O código de exemplo do bot Echo pode ser criado localmente seguindo as instruções de início rápido para Criar um bot.

Substitua o código em EchoBot.cs pelo seguinte código:

using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

// Represents a bot saves and echoes back user input.
public class EchoBot : ActivityHandler
{
   // Create local Memory Storage.
   private static readonly MemoryStorage _myStorage = new MemoryStorage();

   // Create cancellation token (used by Async Write operation).
   public CancellationToken cancellationToken { get; private set; }

   // Class for storing a log of utterances (text of messages) as a list.
   public class UtteranceLog : IStoreItem
   {
      // A list of things that users have said to the bot
      public List<string> UtteranceList { get; } = new List<string>();

      // The number of conversational turns that have occurred
      public int TurnNumber { get; set; } = 0;

      // Create concurrency control where this is used.
      public string ETag { get; set; } = "*";
   }

   // Echo back user input.
   protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
   {
      // preserve user input.
      var utterance = turnContext.Activity.Text;

      // Make empty local log-items list.
      UtteranceLog logItems = null;

      // See if there are previous messages saved in storage.
      try
      {
         string[] utteranceList = { "UtteranceLog" };
         logItems = _myStorage.ReadAsync<UtteranceLog>(utteranceList).Result?.FirstOrDefault().Value;
      }
      catch
      {
         // Inform the user an error occurred.
         await turnContext.SendActivityAsync("Sorry, something went wrong reading your stored messages!");
      }

      // If no stored messages were found, create and store a new entry.
      if (logItems is null)
      {
         // Add the current utterance to a new object.
         logItems = new UtteranceLog();
         logItems.UtteranceList.Add(utterance);

         // Set initial turn counter to 1.
         logItems.TurnNumber++;

         // Show user new user message.
         await turnContext.SendActivityAsync($"{logItems.TurnNumber}: The list is now: {string.Join(", ", logItems.UtteranceList)}");

         // Create dictionary object to hold received user messages.
         var changes = new Dictionary<string, object>();
         {
            changes.Add("UtteranceLog", logItems);
         }
         try
         {
            // Save the user message to your Storage.
            await _myStorage.WriteAsync(changes, cancellationToken);
         }
         catch
         {
            // Inform the user an error occurred.
            await turnContext.SendActivityAsync("Sorry, something went wrong storing your message!");
         }
      }
      // Else, our storage already contained saved user messages, add new one to the list.
      else
      {
         // add new message to list of messages to display.
         logItems.UtteranceList.Add(utterance);
         // increment turn counter.
         logItems.TurnNumber++;

         // show user new list of saved messages.
         await turnContext.SendActivityAsync($"{logItems.TurnNumber}: The list is now: {string.Join(", ", logItems.UtteranceList)}");

         // Create Dictionary object to hold new list of messages.
         var changes = new Dictionary<string, object>();
         {
            changes.Add("UtteranceLog", logItems);
         };

         try
         {
            // Save new list to your Storage.
            await _myStorage.WriteAsync(changes,cancellationToken);
         }
         catch
         {
            // Inform the user an error occurred.
            await turnContext.SendActivityAsync("Sorry, something went wrong storing your message!");
         }
      }
   }
}

Inicie seu bot

Execute o bot localmente.

Iniciar o emulador e conectar seu bot

Instale o Bot Framework Emulator, depois inicie o Emulator e conecte-se ao bot no Emulator:

  1. Selecione o link Criar nova configuração de bot na guia Boas-vindas do Emulator.
  2. Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.

Interagir com o bot

Envie uma mensagem ao bot. Ele listará as mensagens recebidas.

A conversation with the bot that shows the bot keeping a list of messages from the user.

O restante deste artigo demonstrará como salvar no armazenamento persistente em vez de na memória interna do bot.

Usar o Cosmos DB

Importante

A classe de armazenamento do Cosmos DB foi preterida. Os contêineres criados originalmente com o CosmosDbStorage não tinham nenhuma chave de partição definida e receberam a chave de partição padrão de _/partitionKey.

Os contêineres criados com o armazenamento do Cosmos DB podem ser usados com o armazenamento particionado do Cosmos DB. Para obter mais informações, leia Particionamento no Azure Cosmos DB.

Observe também que, ao contrário do armazenamento herdado do Cosmos DB, o armazenamento particionado do Cosmos DB não cria automaticamente um banco de dados dentro da sua conta do Cosmos DB. Você precisa criar um novo banco de dados manualmente, mas ignore a criação manual de um contêiner, pois o CosmosDbPartitionedStorage criará o contêiner para você.

Agora que você usou o armazenamento de memória, vamos atualizar o código para usar o Azure Cosmos DB. O Cosmos DB é o banco de dados multimodelo globalmente distribuído da Microsoft. O Azure Cosmos DB permite que você dimensione a taxa de transferência e o armazenamento de maneira elástica e independente em qualquer número de regiões geográficas do Azure. Ele oferece garantias de taxa de transferência, disponibilidade, latência e consistência com contratos de nível de serviço (SLAs) abrangentes.

Configurar um recurso do Cosmos DB

Para usar o Cosmos DB em seu bot, você precisará criar um recurso de banco de dados antes de mexer no código. Para obter uma descrição detalhada do banco de dados e da criação de aplicativos do Cosmos DB, confira o guia de início rápido para .NET, Node.js ou Python.

Criar sua conta de banco de dados

  1. Vá para o portal do Azure para criar uma conta do Azure Cosmos DB. Pesquise e selecione Azure Cosmos DB.

  2. Na página Azure Cosmos DB, escolha Novo para abrir a página Criar Conta do Azure Cosmos DB.

    Screenshot of creating your Cosmos DB account.

  3. Forneça valores para os seguintes campos:

    1. Assinatura. Selecione a assinatura do Azure que você deseja usar para essa conta do Azure Cosmos.
    2. Grupo de recursos. Escolha um grupo de recursos existente ou escolha Criar novo e insira um nome para o grupo de recursos novo.
    3. Nome da conta. Insira um nome para identificar a conta do Azure Cosmos. Já que documents.Azure.com é acrescentado ao nome que você fornece para criar o URI, use um nome exclusivo. Observe as diretrizes abaixo:
      • O nome deve ser exclusivo em todo o Azure.
      • O nome deve ter entre 3 e 31 caracteres.
      • Apenas letras minúsculas, números e o caractere de hífen (-) podem ser incluídas no nome.
    4. API. Selecione Core (SQL)
    5. Local. Selecione um local mais próximo dos usuários para fornecer a eles acesso mais rápido aos dados.
  4. Selecione Examinar + criar.

  5. Após a validação, selecione Criar.

A criação da conta leva alguns minutos. Aguarde até que o portal exiba a página Parabéns! Sua conta do Azure Cosmos DB foi criada.

Adicionar um banco de dados

Observação

Não crie o contêiner sozinho. O bot vai criá-lo para você ao criar seu respectivo cliente interno do Cosmos DB. Isso garante que ele esteja configurado corretamente para armazenar o estado do bot.

  1. Navegue até a página Data Explorer em sua conta do Cosmos DB recém-criada e, em seguida, escolha Novo Banco de Dados na caixa suspensa do Novo Contêiner. Um painel será aberto no lado direito da janela, no qual você poderá inserir os detalhes do novo banco de dados.

    Screenshot of creating your Cosmos DB database.

  2. Insira uma ID para o novo banco de dados e, opcionalmente, defina a produtividade (você poderá alterar isso mais tarde) e, por fim, escolha OK para criar seu banco de dados. Ao configurar seu bot, anote essa ID de banco de dados para uso posterior.

  3. Agora que criou uma conta do Cosmos DB e um banco de dados, você precisa copiar alguns dos valores para integrar seu novo banco de dados ao bot. Para recuperá-los, navegue até a guia Chaves na seção de configurações do banco de dados da sua conta do Cosmos DB. Dessa página, você precisará do URI (ponto de extremidade do Cosmos DB) e da CHAVE PRIMÁRIA (chave de autorização).

Agora você deve ter uma conta do Cosmos DB com um banco de dados e os seguintes valores prontos para usar nas configurações de bot.

  • URI
  • Chave Primária
  • ID do banco de dados

Adicionar informações de configuração do Cosmos DB

Use os detalhes que você anotou na parte anterior deste artigo para definir o ponto de extremidade, a chave de autorização e a ID do banco de dados. Por fim, você precisa escolher um nome apropriado para o contêiner que será criado no banco de dados para armazenar o estado do bot. No exemplo abaixo, o contêiner do Cosmos DB criado será chamado de "bot-storage".

Adicione as informações a seguir ao arquivo de configuração.

appsettings.json

"CosmosDbEndpoint": "<your-CosmosDb-URI>",
"CosmosDbAuthKey": "<your-primary-key>",
"CosmosDbDatabaseId": "<your-database-id>",
"CosmosDbContainerId": "bot-storage"

Como instalar pacotes do Cosmos DB

Verifique se você tem os pacotes necessários para o Cosmos DB.

Instale o pacote NuGet Microsoft.Bot.Builder.Azure. Para obter mais informações sobre como usar o NuGet, confira Instalar e gerenciar pacotes no Visual Studio usando o Gerenciador de Pacotes do NuGet.

Implementação do Cosmos BD

Observação

A versão 4.6 introduziu um novo provedor de armazenamento do Cosmos DB, a classe de armazenamento particionado do Cosmos DB. A classe de armazenamento do Cosmos DB original foi preterida. Os contêineres criados com o armazenamento do Cosmos DB podem ser usados com o armazenamento particionado do Cosmos DB. Para obter mais informações, leia Particionamento no Azure Cosmos DB.

Ao contrário do armazenamento herdado do Cosmos DB, o armazenamento particionado do Cosmos DB não cria automaticamente um banco de dados dentro da sua conta do Cosmos DB. Você precisa criar um novo banco de dados manualmente, mas ignore a criação manual de um contêiner, pois o CosmosDbPartitionedStorage criará o contêiner para você.

O código de exemplo a seguir é executado usando o mesmo código de bot do exemplo de armazenamento de memória fornecido acima, excluindo as exceções listadas aqui. Os snippets de código a seguir mostram uma implementação de armazenamento do Cosmos DB para “myStorage” que substitui o armazenamento de memória local.

Primeiro, você precisa atualizar o Startup.cs para fazer referência à biblioteca bot builder do Azure:

using Microsoft.Bot.Builder.Azure;

Em seguida, no método ConfigureServices em Startup.cs, crie o objeto CosmosDbPartitionedStorage. Isso será passado para o construtor EchoBot por meio da injeção de dependência.

// Use partitioned CosmosDB for storage, instead of in-memory storage.
services.AddSingleton<IStorage>(
    new CosmosDbPartitionedStorage(
        new CosmosDbPartitionedStorageOptions
        {
            CosmosDbEndpoint = Configuration.GetValue<string>("CosmosDbEndpoint"),
            AuthKey = Configuration.GetValue<string>("CosmosDbAuthKey"),
            DatabaseId = Configuration.GetValue<string>("CosmosDbDatabaseId"),
            ContainerId = Configuration.GetValue<string>("CosmosDbContainerId"),
            CompatibilityMode = false,
        }));

No EchoBot.cs, altere a declaração private static readonly MemoryStorage _myStorage = new MemoryStorage(); da variável _myStorage para o seguinte:

// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;

Em seguida, passe o objeto IStorage para o construtor EchoBot:

public EchoBot(IStorage storage)
{
    if (storage is null) throw new ArgumentNullException();
    _myStorage = storage;
}

Inicie o bot do Cosmos DB

Execute o bot localmente.

Testar o bot do Cosmos DB com o Bot Framework Emulator

Agora inicie o Bot Framework Emulator e conecte-se ao seu bot:

  1. Selecione o link Criar nova configuração de bot na guia Boas-vindas do Emulator.
  2. Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.

Interagir com o bot do Cosmos DB

Envie uma mensagem ao bot e o bot listará as mensagens recebidas por ele.

A conversation with the bot that shows the bot keeping a list of messages from the user.

Exibir os dados do Cosmos DB

Depois de executar o bot e salvar suas informações, será possível visualizar os dados armazenados no portal do Azure na guia Data Explorer.

Screenshot of the Data Explorer in the Azure portal.

Usar o armazenamento de blobs

O Armazenamento de Blobs do Azure é uma solução de armazenamento de objetos da Microsoft para a nuvem. O armazenamento de Blobs é otimizado para armazenar grandes quantidades de dados não estruturados, como texto ou dados binários. Esta seção explica como criar uma conta e um contêiner de armazenamento de Blobs do Azure e, em seguida, como fazer referência ao contêiner de armazenamento de Blobs do bot.

Para obter mais informações sobre o armazenamento de Blobs, confira O que é o Armazenamento de Blobs do Azure?.

Criar sua conta de Armazenamento de Blobs

Para usar o Armazenamento de Blobs em seu bot, você precisará configurar algumas coisas antes de mexer no código.

  1. No portal do Azure, selecione Todos os serviços.

  2. Na seção Em destaque da página Todos os serviços, escolha Contas de armazenamento.

  3. Na página Contas de armazenamento, escolha Nova.

    Screenshot of creating an Azure Storage account.

  4. No campo Assinatura, selecione a assinatura na qual você deseja criar a conta de armazenamento.

  5. No campo Grupo de recursos, selecione um grupo de recursos existente ou selecione Criar novo e insira um nome para o novo grupo de recursos.

  6. No campo Nome da conta de armazenamento, insira um nome para a conta. Observe as diretrizes abaixo:

    • O nome deve ser exclusivo em todo o Azure.
    • O nome precisa ter entre 3 e 24 caracteres.
    • O nome pode conter apenas números e letras minúsculas.
  7. No campo Local, selecione um local para a conta de armazenamento ou use o local padrão.

  8. Nas demais configurações, configure o seguinte:

  9. Na seção Detalhes do projeto da página Criar conta de armazenamento, escolha os valores desejados para assinatura e Grupo de recursos.

  10. Na seção Detalhes da instância da página Criar conta de armazenamento, insira o Nome da conta de armazenamento e escolha os valores de Localização, Tipo de conta e Duplicação.

  11. Selecione Examinar + criar para conferir as configurações da conta de armazenamento.

  12. Após a validação, selecione Criar.

Criar contêiner de Armazenamento de Blobs

Depois de criar sua conta de armazenamento de Blobs, abra-a e:

  1. Selecione Gerenciador de Armazenamento (Preview).

  2. Em seguida, clique com o botão direito do mouse em CONTÊINERES DE BLOBS

  3. Selecione Criar contêiner de Blobs na lista suspensa.

    Screenshot of creating a blob container.

  4. Insira um nome no formulário Novo contêiner. Você usará esse nome para o valor "nome do contêiner de Blobs" para fornecer acesso à sua conta de Armazenamento de Blobs. Observe as diretrizes abaixo:

    • O nome pode conter apenas letras minúsculas, números e hifens.
    • O nome deve começar com uma letra ou um número.
    • Cada hífen deve ser precedido e seguido por um caractere válido que não seja um hífen.
    • O nome precisa ter entre 3 e 63 caracteres.

Adicionar informações de configuração do armazenamento de Blobs

Localize as chaves do armazenamento de Blobs necessárias para configurá-lo para o bot, conforme mostrado acima:

  1. No portal do Azure, abra sua conta de armazenamento de Blobs e escolha Chaves de acesso na seção Configurações.
  2. Para configurar o bot para acessar sua conta de armazenamento de Blobs, use Cadeia de conexão como o valor da cadeia de conexão de Blobs.

Adicione as informações a seguir ao arquivo de configuração.

appsettings.json

"BlobConnectionString": "<your-blob-connection-string>",
"BlobContainerName": "<your-blob-container-name>",

Como instalar pacotes de armazenamento de Blobs

Caso ainda não os tenha instalado, instale os pacotes a seguir.

Instale o pacote NuGet Microsoft.Bot.Builder.Azure.Blobs. Para obter mais informações, confira Instalar e gerenciar pacotes no Visual Studio usando o Gerenciador de Pacotes do NuGet.

Implementação do armazenamento de Blobs

O amazenamento de Blobs é usado para armazenar o estado do bot.

Observação

Microsoft.Bot.Builder.Azure.AzureBlobStorage é preterido nas versões 4.10 e posteriores. Use o novo Microsoft.Bot.Builder.Azure.Blobs.BlobsStorage em seu lugar.

O código de exemplo a seguir é executado usando o mesmo código de bot do exemplo de armazenamento de memória fornecido acima, excluindo as exceções listadas aqui.

Os snippets de código a seguir mostram uma implementação de armazenamento de Blobs para “myStorage” que substitui o armazenamento de memória local.

Primeiro, você precisa atualizar o Startup.cs para fazer referência à biblioteca de Blobs do bot builder do Azure:

Startup.cs

using Microsoft.Bot.Builder.Azure.Blobs;

Em seguida, no método ConfigureServices em Startup.cs, crie o objeto BlobsStorage, passando os valores de appsettings.json. Isso será passado para o construtor EchoBot por meio da injeção de dependência.

//Use Azure Blob storage, instead of in-memory storage.
services.AddSingleton<IStorage>(
    new BlobsStorage(
        Configuration.GetValue<string>("BlobConnectionString"),
        Configuration.GetValue<string>("BlobContainerName")
        ));

Agora você primeiro precisa atualizar o EchoBot.cs para fazer referência à biblioteca de Blobs do bot builder do Azure:

EchoBot.cs

using Microsoft.Bot.Builder.Azure.Blobs;

Em seguida, remova ou comente a linha de código que cria a variável MemoryStorage 'private static readonly MemoryStorage _myStorage = new MemoryStorage();' e crie uma variável nova que será usada para salvar a entrada de usuário no Armazenamento de Blobs.

EchoBot.cs

// variable used to save user input to CosmosDb Storage.
private readonly IStorage _myStorage;

Em seguida, passe o objeto IStorage para o construtor EchoBot:

public EchoBot(IStorage storage)
{
    if (storage is null) throw new ArgumentNullException();
    _myStorage = storage;
}

Quando o armazenamento estiver definido para apontar para a conta de Armazenamento de Blobs, o código do bot armazenará e recuperará dados do Armazenamento de Blobs.

Quando o armazenamento estiver definido para apontar para a conta de Armazenamento de Blobs, o código do bot armazenará e recuperará dados do Armazenamento de Blobs.

Iniciar o bot de armazenamento de Blobs

Execute o bot localmente.

Iniciar o Emulator e conectar seu bot de armazenamento de Blobs

Em seguida, inicie o Emulator e, depois, conecte-se ao seu bot no Emulator:

  1. Selecione o link Criar nova configuração de bot na guia "Boas-vindas" do Emulator.
  2. Preencha os campos para se conectar ao seu bot considerando as informações na página da Web exibida ao iniciar o bot.

Interagir com seu bot de armazenamento de Blobs

Envie uma mensagem ao bot, e ele listará as mensagens recebidas.

A conversation with the bot that shows the bot keeping a list of messages from the user.

Exibir seus dados de armazenamento de Blobs

Depois de executar o bot e salvar suas informações, poderemos exibi-lo na guia Gerenciador de Armazenamento no portal do Azure.

Armazenamento de transcrição de blobs

O armazenamento de transcrições do Blob do Azure fornece uma opção de armazenamento especializado que permite salvar e recuperar facilmente conversas do usuário como transcrições gravadas. O armazenamento de transcrições de Blobs do Azure é útil para capturar automaticamente as entradas de usuário para examinar durante a depuração do desempenho do seu bot.

Observação

Atualmente, o Python não oferece suporte ao armazenamento de transcrições de Blobs do Azure. Embora o JavaScript ofereça suporte ao armazenamento de transcrições de Blobs, as instruções a seguir são apenas para C#.

Configurar um contêiner de armazenamento de transcrições de Blobs

O armazenamento de transcrições do Blob do Azure pode usar a mesma conta de Armazenamento de Blobs criada seguindo as etapas detalhadas nas seções "Criar sua conta de Armazenamento de Blobs" e "Adicionar informações de configuração" acima. Agora, adicionamos um contêiner para manter nossas transcrições.

Screenshot of creating a blob container to use as a transcript store.

  1. Abra uma conta de Armazenamento de Blobs do Azure.
  2. Selecione o Gerenciador de Armazenamento.
  3. Clique com botão direito do mouse em CONTÊINERES DE BLOBS e selecione Criar contêiner de blobs.
  4. Insira um nome para o contêiner de transcrição e escolha OK. (Inserimos mybottranscripts)

Implementação de armazenamento de transcrições de Blobs

O código a seguir conecta o ponteiro de armazenamento de transcrição _myTranscripts à sua nova conta de armazenamento de transcrições do Blob do Azure. Para criar esse link com um novo nome de contêiner, <your-blob-transcript-container-name>, cria um novo contêiner no Armazenamento de Blobs para manter os arquivos de transcrição.

O armazenamento de transcrições de Blobs foi projetado para armazenar transcrições de bot.

Observação

Microsoft.Bot.Builder.Azure.AzureBlobTranscriptStore é preterido nas versões 4.10 e posteriores. Use o novo Microsoft.Bot.Builder.Azure.Blobs.BlobsTranscriptStore em seu lugar.

echoBot.cs

using Microsoft.Bot.Builder.Azure.Blobs;

public class EchoBot : ActivityHandler
{
   ...

   private readonly BlobsTranscriptStore _myTranscripts = new BlobsTranscriptStore("<your-azure-storage-connection-string>", "<your-blob-transcript-container-name>");

   ...
}

Armazenar conversas do usuário em transcrições de Blobs do Azure

Quando um contêiner de Blobs fica disponível para armazenar transcrições, você pode começar a armazenar as conversas dos usuários com seu bot. Essas conversas poderão ser usadas posteriormente como uma ferramenta de depuração para ver como os usuários interagem com o bot. Cada Reiniciar conversa do Emulator inicia a criação de uma nova lista de conversa de transcrição. O código a seguir preserva as entradas de conversas do usuário em um arquivo de transcrição armazenado.

  • A transcrição atual é salva usando LogActivityAsync.
  • Transcrições salvas são recuperadas usando ListTranscriptsAsync. Nesse código de exemplo, a ID de cada transcrição armazenada é salva em uma lista chamada "storedTranscripts". Posteriormente, essa lista é usada para gerenciar a quantidade de transcrições armazenadas de blobs que podemos manter.

echoBot.cs


protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    await _myTranscripts.LogActivityAsync(turnContext.Activity);

    List<string> storedTranscripts = new List<string>();
    PagedResult<Microsoft.Bot.Builder.TranscriptInfo> pagedResult = null;
    var pageSize = 0;
    do
    {
       pagedResult = await _myTranscripts.ListTranscriptsAsync("emulator", pagedResult?.ContinuationToken);
       pageSize = pagedResult.Items.Count();

       // transcript item contains ChannelId, Created, Id.
       // save the channelIds found by "ListTranscriptsAsync" to a local list.
       foreach (var item in pagedResult.Items)
       {
          storedTranscripts.Add(item.Id);
       }
    } while (pagedResult.ContinuationToken != null);

    ...
}

Gerenciar transcrições armazenadas de blobs

Embora as transcrições armazenadas possam ser usadas como uma ferramenta de depuração, ao longo do tempo, a quantidade de transcrições armazenadas poderá ficar maior do que você consegue preservar. O código adicional incluído abaixo usa DeleteTranscriptAsync para remover tudo, exceto os três últimos itens de transcrição recuperados do seu armazenamento de transcrições de blobs.

echoBot.cs


protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    await _myTranscripts.LogActivityAsync(turnContext.Activity);

    List<string> storedTranscripts = new List<string>();
    PagedResult<Microsoft.Bot.Builder.TranscriptInfo> pagedResult = null;
    var pageSize = 0;
    do
    {
       pagedResult = await _myTranscripts.ListTranscriptsAsync("emulator", pagedResult?.ContinuationToken);
       pageSize = pagedResult.Items.Count();

       // transcript item contains ChannelId, Created, Id.
       // save the channelIds found by "ListTranscriptsAsync" to a local list.
       foreach (var item in pagedResult.Items)
       {
          storedTranscripts.Add(item.Id);
       }
    } while (pagedResult.ContinuationToken != null);

    // Manage the size of your transcript storage.
    for (int i = 0; i < pageSize; i++)
    {
       // Remove older stored transcripts, save just the last three.
       if (i < pageSize - 3)
       {
          string thisTranscriptId = storedTranscripts[i];
          try
          {
             await _myTranscripts.DeleteTranscriptAsync("emulator", thisTranscriptId);
           }
           catch (System.Exception ex)
           {
              await turnContext.SendActivityAsync("Debug Out: DeleteTranscriptAsync had a problem!");
              await turnContext.SendActivityAsync("exception: " + ex.Message);
           }
       }
    }
    ...
}

Para obter mais informações sobre a classe, confira Armazenamento de transcrições de Blobs do Azure.

Informações adicionais

Gerenciar simultaneidade usando eTags

Em nosso exemplo de código do bot, definimos a propriedade eTag de cada IStoreItem como *. O membro (marca da entidade) eTag do objeto de repositório é usado no Cosmos DB para gerenciar a simultaneidade. eTag indica ao banco dados o que fazer caso outra instância do bot altere o objeto no mesmo armazenamento onde o bot está gravando.

A última gravação prevalece - permite substituições

Um valor da propriedade eTag do asterisco (*) indica que o último gravador prevalece. Ao criar um novo armazenamento de dados, é possível definir eTag de uma propriedade como * para indicar que os dados em gravação não foram salvos anteriormente, ou que você deseja que o último gravador substitua qualquer propriedade salva anteriormente. Se a simultaneidade não for um problema para o bot, a definição da propriedade eTag como * para qualquer dado que você esteja gravando viabilizará as substituições.

Manter simultaneidade e evitar substituições

Ao armazenar seus dados no Cosmos DB, use um valor diferente de * para eTag se quiser impedir o acesso simultâneo a uma propriedade e evitar a substituição de alterações por outra instância do bot. O bot receberá uma resposta de erro com a mensagem etag conflict key= ao tentar salvar dados de estado se o eTag não tiver o mesmo valor de eTag em armazenamento.

Por padrão, o armazenamento do Cosmos DB verificará a propriedade eTag de um objeto de armazenamento quanto à igualdade sempre que um bot gravar esse item e, em seguida, atualizará para um novo valor exclusivo após cada gravação. Se a propriedade eTag na gravação não corresponder com eTag no armazenamento, isso significa que outro bot ou thread alterou os dados.

Por exemplo, digamos que você queira que o bot edite uma nota salva, mas não quer que o bot substitua as alterações feitas por outra instância do bot. Se outra instância do bot tiver feito edições, você quer que o usuário edite a versão com as atualizações mais recentes.

Primeiro, crie uma classe que implemente IStoreItem.

EchoBot.cs

public class Note : IStoreItem
{
    public string Name { get; set; }
    public string Contents { get; set; }
    public string ETag { get; set; }
}

Em seguida, crie uma nota inicial criando um objeto de armazenamento e adicione o objeto ao armazenamento.

EchoBot.cs

// create a note for the first time, with a non-null, non-* ETag.
var note = new Note { Name = "Shopping List", Contents = "eggs", ETag = "x" };

var changes = Dictionary<string, object>();
{
    changes.Add("Note", note);
};
await NoteStore.WriteAsync(changes, cancellationToken);

Então, acesse e atualize a nota mais tarde, mantendo eTag que foi lido no armazenamento.

EchoBot.cs

var note = NoteStore.ReadAsync<Note>("Note").Result?.FirstOrDefault().Value;

if (note != null)
{
    note.Contents += ", bread";
    var changes = new Dictionary<string, object>();
    {
         changes.Add("Note1", note);
    };
    await NoteStore.WriteAsync(changes, cancellationToken);
}

Se a nota foi atualizada no armazenamento antes de gravar as alterações, a chamada para Write lançará uma exceção.

Para manter a simultaneidade, sempre leia uma propriedade do armazenamento e modifique a propriedade lida para que eTag seja mantido. Ao ler os dados de usuário do armazenamento, a resposta conterá a propriedade eTag. Se você alterar os dados e gravar dados atualizados no armazenamento, a solicitação deverá incluir a propriedade eTag que especifica o mesmo valor lido anteriormente. No entanto, gravar um objeto com eTag definido para * permitirá que a gravação substitua quaisquer outras alterações.

Próximas etapas

Agora que você sabe como ler e gravar diretamente do armazenamento, veremos como é possível utilizar o gerenciador de estado para fazer isso.