Escritura directa en el almacenamiento

SE APLICA A: SDK v4

Puede leer y escribir directamente en el objeto de almacenamiento sin usar middleware ni un objeto de contexto. Esto puede ser adecuado para los datos que el bot usa para conservar una conversación o los que provienen de un origen externo al flujo de conversación del bot. En este modelo de almacenamiento de datos, los datos se leen directamente desde el almacenamiento en lugar de usar un administrador de estados. En los ejemplos de código de este artículo, se muestra cómo leer y escribir datos en el almacenamiento con memoria, Cosmos DB, Azure Blob y el almacén de transcripciones de blobs de Azure.

Nota:

Los SDK de JavaScript, C# y Python de Bot Framework seguirán siendo compatibles, pero el SDK de Java se va a retirar con la compatibilidad final a largo plazo que finaliza en noviembre de 2023.

Los bots existentes creados con el SDK de Java seguirán funcionando.

Para la creación de nuevos bots, considera el uso de Power Virtual Agents y lee sobre cómo elegir la solución de bot de chat adecuada.

Para obtener más información, consulta El futuro de la creación de bots.

Requisitos previos

Nota:

Puedes instalar las plantillas desde Visual Studio.

  1. En el menú, selecciona Extensiones, y a continuación Administrar extensiones.
  2. En el cuadro de diálogo Administrar extensiones, busque e instale plantillas del SDK de Bot Framework v4 para Visual Studio.

Para obtener información sobre cómo implementar bots de .NET en Azure, consulte Aprovisionamiento y publicación de un bot.

Acerca de este ejemplo

El código de ejemplo de este artículo comienza con la estructura de un bot de eco básico y luego se amplía la funcionalidad de ese bot mediante la incorporación de código adicional (que se proporciona a continuación). Este código ampliado permite crear una lista para conservar las entradas del usuario tal como se reciben. En cada turno, la lista completa de entradas del usuario, guardada en la memoria, se devuelve al usuario. A continuación, se modifica la estructura de datos que contiene esta lista de entradas para guardarla en el almacenamiento. Se describen varios tipos de almacenamiento a medida que se va agregando funcionalidad adicional a este código de ejemplo.

Almacenamiento en memoria

Bot Framework SDK le permite almacenar las entradas del usuario mediante el almacenamiento en memoria. Dado que el almacenamiento en memoria se borra cada vez que se reinicia el bot, es más adecuado para fines de prueba y no está pensado para su uso en producción. Los tipos de almacenamiento persistente, como el almacenamiento de base de datos, son los más adecuados para los bots de producción.

Creación de un bot básico

El resto de este tema se basa en un bot de eco. El código de ejemplo del bot de eco se puede compilar localmente siguiendo las instrucciones de inicio rápido para Crear un bot.

Reemplace el código de EchoBot.cs por el código siguiente:

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!");
         }
      }
   }
}

Inicio del bot

Ejecute el bot localmente.

Inicio del emulador y conexión del bot

Instale Bot Framework Emulator. A continuación, inicie el emulador y, después, conéctese al bot en el emulador:

  1. Seleccione el vínculo Crear nueva configuración de bot en la pestaña Bienvenido/a de Emulator.
  2. Rellene los campos para conectarse al bot con la información de la página web que aparece cuando inicia el bot.

Interacción con el bot

Envíe un mensaje al bot. El bot mostrará la lista de mensajes que ha recibido.

Una conversación con el bot que muestra el bot que mantiene una lista de mensajes del usuario.

El resto de este artículo mostrará cómo guardar en el almacenamiento persistente en lugar de la memoria interna del bot.

Uso de Cosmos DB

Importante

La clase almacenamiento de Cosmos DB está en desuso. Los contenedores creados originalmente con CosmosDbStorage no tenían ningún conjunto de claves de partición y se les dio la clave de partición predeterminada de _/partitionKey.

Los contenedores creados con el almacenamiento de Cosmos DB pueden utilizarse con el almacenamiento particionado de Cosmos DB. Para más información, consulte Creación de particiones en Azure Cosmos DB.

Tenga en cuenta también que, a diferencia del almacenamiento heredado de Cosmos DB, el almacenamiento con particiones de Cosmos DB no crea automáticamente una base de datos dentro de la cuenta de Cosmos DB. Debe crear manualmente una nueva base de datos, pero omitir manualmente la creación de un contenedor, ya que CosmosDbPartitionedStorage creará el contenedor automáticamente.

Ahora que ha usado el almacenamiento en memoria, actualizaremos el código para usar Azure Cosmos DB. Cosmos DB es la base de datos multimodelo de distribución global de Microsoft. Azure Cosmos DB permite escalar de forma elástica e individual el rendimiento y el almacenamiento en cualquiera de las regiones geográficas de Azure. Ofrece garantía de rendimiento, latencia, disponibilidad y coherencia con Acuerdos de Nivel de Servicio (SLA) integrales.

Configuración de un recurso de Cosmos DB

Para utilizar Cosmos DB en el bot, es necesario crear un recurso de base de datos antes de meternos en el código. Para obtener una descripción detallada de la creación de aplicaciones y bases de datos de Cosmos DB, consulte el inicio rápido de .NET, Node.js o Python.

Crear la cuenta de base de datos

  1. Vaya a Azure Portal para crear una cuenta de Azure Cosmos DB. Busque y seleccione Azure Cosmos DB.

  2. En la página Azure Cosmos DB, seleccione Nuevo para abrir la página Crear cuenta de Azure Cosmos DB.

    Captura de pantalla de la creación de la cuenta de Cosmos DB.

  3. Proporcione valores para los campos siguientes:

    1. Suscripción. Seleccione la suscripción de Azure que desea usar para esta cuenta de Azure Cosmos.
    2. Grupo de recursos. Seleccione un grupo de recursos existente o Crear nuevo y escriba un nombre para el nuevo grupo de recursos.
    3. Nombre de cuenta. Escriba un nombre para identificar la cuenta de Azure Cosmos. Dado que documents.azure.com se anexa al nombre que se proporciona para crear el identificador URI, debe usar un nombre único. Tenga en cuenta estas directrices:
      • El nombre debe ser único en Azure.
      • El nombre debe tener entre 3 y 63 caracteres.
      • El nombre solo puede incluir letras minúsculas, números y el carácter de guion (-).
    4. API. Seleccione Core (SQL).
    5. Ubicación. seleccione una ubicación que sea la más cercana a los usuarios para que puedan acceder de la forma más rápida posible a los datos.
  4. Seleccione Revisar + crear.

  5. Una vez validada, seleccione Crear.

La cuenta tarda unos minutos en crearse. Espere a que el portal muestre la página ¡Enhorabuena! Se ha creado su cuenta de Azure Cosmos DB.

Agregar una base de datos

Nota:

No cree el contenedor usted mismo. El bot lo creará automáticamente al crear su cliente interno de Cosmos DB, asegurándose de que esté configurado correctamente para almacenar el estado del bot.

  1. Vaya a la página Data Explorer dentro de la cuenta de Cosmos DB recién creada y, después, elija Nueva base de datos en el cuadro desplegable Nuevo contenedor. A continuación, se abrirá un panel en el lado derecho de la ventana, donde puede especificar los detalles de la nueva base de datos.

    Captura de pantalla de la creación de la base de datos de Cosmos DB.

  2. Escriba un identificador para la nueva base de datos y, opcionalmente, establezca el rendimiento (puede cambiarlo más adelante) y, por último, seleccione Aceptar para crear la base de datos. Tome nota de este identificador de base de datos para usarlo más adelante al configurar el bot.

  3. Ahora que ha creado una cuenta de Cosmos DB y una base de datos, debe copiar algunos valores para integrar la nueva base de datos en el bot. Para recuperarlos, vaya a la pestaña Claves de la sección de configuración de la base de datos de la cuenta de Cosmos DB. Desde esta página, necesitará su URI (punto de conexión de Cosmos DB) y su CLAVE PRINCIPAL (clave de autorización).

Ahora debería tener una cuenta de Cosmos DB con una base de datos y los siguientes valores listos para usarse en la configuración del bot.

  • URI
  • Primary Key
  • Identificador de base de datos

Adición de información de configuración de Cosmos DB

Use los detalles que anotó en la parte anterior de este artículo para establecer el punto de conexión, la clave de autorización y el identificador de base de datos. Por último, debe elegir un nombre apropiado para el contenedor que se creará en la base de datos para almacenar el estado de bot. En el ejemplo siguiente, el contenedor de Cosmos DB que se crea se denominará "bot-storage".

Agregue la siguiente información al archivo de configuración.

appsettings.json

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

Instalación de paquetes de Cosmos DB

Asegúrese de que tiene los paquetes necesarios para Cosmos DB.

Instale el paquete NuGet Microsoft.Bot.Builder.Azure. Para más información sobre el uso de NuGet, consulte Instalar y administrar paquetes en Visual Studio con el Administrador de paquetes NuGet.

Implementación de Cosmos DB

Nota:

La versión 4.6 incorporó un nuevo proveedor de almacenamiento de Cosmos DB, la clase almacenamiento con particiones de Cosmos DB, y la clase almacenamiento de Cosmos DB ha quedado en desuso. Los contenedores creados con el almacenamiento de Cosmos DB pueden utilizarse con el almacenamiento particionado de Cosmos DB. Para más información, consulte Creación de particiones en Azure Cosmos DB.

A diferencia del almacenamiento heredado de Cosmos DB, el almacenamiento con particiones de Cosmos DB no crea automáticamente una base de datos dentro de la cuenta de Cosmos DB. Debe crear manualmente una nueva base de datos, pero omitir manualmente la creación de un contenedor, ya que CosmosDbPartitionedStorage creará el contenedor automáticamente.

El código de ejemplo siguiente se ejecuta con el mismo código de bot que el ejemplo de almacenamiento en memoria anterior, con las excepciones enumeradas aquí. El siguiente fragmento de código muestra una implementación de almacenamiento de Cosmos DB para "myStorage", que sustituye al almacenamiento en memoria local.

En primer lugar, debe actualizar Startup.cs para hacer referencia a la biblioteca de Azure del generador de bots:

using Microsoft.Bot.Builder.Azure;

A continuación, en el método ConfigureServices de Startup.cs, cree el objeto CosmosDbPartitionedStorage. Esto se pasará al constructor EchoBot a través de la inserción de dependencias.

// 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,
        }));

En EchoBot.cs, cambie la declaración de variable _myStorageprivate static readonly MemoryStorage _myStorage = new MemoryStorage(); por lo siguiente:

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

A continuación, pase el objeto IStorage al constructor EchoBot:

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

Inicio del bot de Cosmos DB

Ejecute el bot localmente.

Pruebe su bot Cosmos DB con Bot Framework Emulator

Inicie Bot Framework Emulator y conéctese al bot:

  1. Seleccione el vínculo Crear nueva configuración de bot en la pestaña Bienvenido/a de Emulator.
  2. Rellene los campos para conectarse al bot con la información de la página web que aparece cuando inicia el bot.

Interacción con el bot Cosmos DB

Envíe un mensaje al bot y este enumerará los mensajes que ha recibido.

Una conversación con el bot que muestra el bot que mantiene una lista de mensajes del usuario.

Visualización de los datos de Cosmos DB

Después de ejecutar el bot y guardar la información, podemos ver los datos almacenados en Azure Portal en la pestaña Explorador de datos.

Captura de pantalla del Explorador de datos en Azure Portal.

Uso de Blob Storage

Azure Blob Storage es la solución de almacenamiento de objetos de Microsoft para la nube. Blob Storage está optimizado para el almacenamiento de cantidades masivas de datos no estructurados, como texto o datos binarios. En esta sección se explica cómo crear una cuenta y un contenedor de Azure Blob Storage y cómo hacer referencia al contenedor de Blob Storage desde el bot.

Para más información sobre el Blob Storage, consulte ¿Qué es Azure Blob Storage?.

Creación de la cuenta de Blob Storage

Para utilizar Blob Storage en el bot, es necesario configurar algunas cosas antes de meternos en el código.

  1. En Azure Portal, seleccione Todos los servicios.

  2. En la sección Destacados de la página Todos los servicios, seleccione Cuentas de almacenamiento.

  3. En la página Cuentas de almacenamiento, seleccione Nuevo.

    Captura de pantalla de la creación de una cuenta de Azure Storage.

  4. Seleccione la suscripción en la que se va a crear la cuenta de almacenamiento en el campo Suscripción.

  5. En el campo del Grupo de recursos, seleccione un grupo de recursos existente o Crear nuevo y escriba un nombre para el grupo de recursos.

  6. En el campo Nombre de la cuenta de almacenamiento, escriba un nombre para la cuenta. Tenga en cuenta estas directrices:

    • El nombre debe ser único en Azure.
    • El nombre debe tener entre 3 y 24 caracteres.
    • El nombre solo puede contener números y letras minúsculas.
  7. En el campo Ubicación, seleccione una ubicación para la cuenta de almacenamiento o utilice la ubicación predeterminada.

  8. Defina la configuración de los siguientes valores:

  9. En la sección Detalles del proyecto de la página Crear cuenta de almacenamiento, seleccione los valores deseados para la suscripción y el grupo de recursos.

  10. En la sección Detalles de la instancia de la página Crear cuenta de almacenamiento, escriba el nombre de la cuenta de almacenamiento y, a continuación, seleccione los valores de Ubicación, Tipo de cuenta y Replicación.

  11. Seleccione Revisar y crear para revisar la configuración de la cuenta de almacenamiento.

  12. Una vez validada, seleccione Crear.

Creación de un contenedor de Blob Storage

Una vez creada su cuenta de almacenamiento Blob, ábrala:

  1. Seleccione Explorador de Storage (versión preliminar).

  2. A continuación, haga clic con el botón derecho en CONTENEDORES DE BLOB.

  3. Seleccione Crear contenedor blob en la lista desplegable.

    Captura de pantalla de la creación de un contenedor de blobs.

  4. Introduzca un nombre en el formulario Nuevo contenedor. Usará este nombre para el valor de su "nombre de contenedor Blob" para proporcionar acceso a su cuenta de almacenamiento Blob. Tenga en cuenta estas directrices:

    • Este nombre solo pueden contener letras minúsculas, números y guiones.
    • Este nombre debe empezar con una letra o un número.
    • Antes y después de cada guion debe ir un carácter válido que no sea otro guión.
    • El nombre debe tener entre 3 y 63 caracteres.

Adición de información de configuración de Blob Storage

Busque las claves de Blob Storage que necesita para configurar el almacenamiento de blobs del bot, tal y como se indicó anteriormente:

  1. En Azure portal, abra su cuenta de Blob Storage y seleccione Claves de acceso en la sección Configuración.
  2. Para configurar el bot para acceder a la cuenta de Blob Storage, use Conectar cadena como valor para el cadena de conexión de blob.

Agregue la siguiente información al archivo de configuración.

appsettings.json

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

Instalación de paquetes de Blob Storage

Si no se han instalado anteriormente, instale los siguientes paquetes.

Instale el paquete NuGet Microsoft.Bot.Builder.Azure.Blobs. Para más información sobre el uso de NuGet, consulte Instalar y administrar paquetes en Visual Studio con el Administrador de paquetes NuGet.

Implementación de Blob Storage

Blob Storage se usa para almacenar el estado del bot.

Nota:

A partir de la versión 4.10, Microsoft.Bot.Builder.Azure.AzureBlobStorage está en desuso. Use el nuevo Microsoft.Bot.Builder.Azure.Blobs.BlobsStorage en su lugar.

El código de ejemplo siguiente se ejecuta con el mismo código de bot que el ejemplo de almacenamiento en memoria anterior, con las excepciones enumeradas aquí.

El siguiente fragmento de código muestra una implementación de Blob Storage para "myStorage", que sustituye al almacenamiento en memoria local.

Primero debe actualizar Startup.cs para hacer referencia a la biblioteca de blobs de Azure del generador de bots:

Startup.cs

using Microsoft.Bot.Builder.Azure.Blobs;

A continuación, en el método ConfigureServices de Startup.cs, cree el objeto BlobsStorage y pase los valores de appsettings.json. Esto se pasará al constructor EchoBot a través de la inserción de dependencias.

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

Ahora primero debe actualizar EchoBot.cs para hacer referencia a la biblioteca de blobs de Azure del generador de bots:

EchoBot.cs

using Microsoft.Bot.Builder.Azure.Blobs;

A continuación, quite o comente la línea de código que crea la variable MemoryStorage 'private static readonly MemoryStorage _myStorage = new MemoryStorage();' y cree una nueva variable que se usará para guardar la entrada del usuario en Blob Storage.

EchoBot.cs

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

A continuación, pase el objeto IStorage al constructor EchoBot:

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

Una vez que el almacenamiento se establece para que apunte a la cuenta de Blob Storage, el código del bot almacena y recupera los datos desde Blob Storage.

Una vez que el almacenamiento se establece para que apunte a la cuenta de Blob Storage, el código del bot almacena y recupera los datos desde Blob Storage.

Inicio del bot de Blob Storage

Ejecute el bot localmente.

Inicie Emulator y conecte su bot de Blob Storage

A continuación, inicie el emulador y, después, conéctese al bot en el emulador:

  1. Seleccione el vínculo Crear nueva configuración de bot en la pestaña "Bienvenido/a" de Emulator.
  2. Rellene los campos para conectarse al bot con la información de la página web que aparece cuando inicia el bot.

Interacción con el bot de Blob Storage

Envíe un mensaje al bot y este mostrará una lista de los mensajes que recibe.

Una conversación con el bot que muestra el bot que mantiene una lista de mensajes del usuario.

Visualización de los datos de Blob Storage

Después de ejecutar el bot y guardar la información, lo podemos ver en la pestaña Explorador de Storage de Azure Portal.

Almacenamiento de transcripciones de blobs

El almacenamiento de transcripciones de blobs de Azure ofrece una opción de almacenamiento especializado que le permite guardar y recuperar con facilidad las conversaciones del usuario en forma de una transcripción grabada. El almacenamiento de transcripciones de blobs de Azure es útil para capturar automáticamente las entradas de usuario para examinarlas al tiempo que se depura el rendimiento del bot.

Nota:

Python no admite actualmente el almacenamiento de transcripciones de blobs de Azure. Aunque JavaScript admite el almacenamiento de transcripciones de blobs, las instrucciones siguientes son solo para C#.

Configuración de un contenedor de almacenamiento de transcripciones de blobs

El almacenamiento de transcripciones de blobs de Azure puede usar la misma cuenta de Blob Storage que creó siguiendo los pasos detallados en las secciones "Creación de la cuenta de Blob Storage" y "Adición de la información de configuración" anteriores. Ahora se agrega un contenedor para almacenar las transcripciones

Captura de pantalla de la creación de un contenedor de blobs que se va a usar como almacén de transcripciones.

  1. Abra la cuenta de Azure Blob Storage.
  2. Selección del Explorador de almacenamiento
  3. Haga clic con el botón derecho en CONTENEDORES DE BLOB y seleccione Crear contenedor de blobs.
  4. Escriba un nombre para el contenedor de transcripciones y, después, seleccione Aceptar. (Hemos escrito mybottranscripts)

Implementación del almacenamiento de transcripciones de blobs

El siguiente código conecta el puntero de almacenamiento de transcripciones _myTranscripts a la nueva cuenta de almacenamiento de transcripciones de blobs de Azure. Para crear este vínculo con un nuevo nombre de contenedor, <your-blob-transcript-container-name>, cree un nuevo contenedor en Blob Storage para almacenar los archivos de transcripción.

El almacenamiento de transcripciones de blobs está diseñado para almacenar transcripciones del bot.

Nota:

A partir de la versión 4.10, Microsoft.Bot.Builder.Azure.AzureBlobTranscriptStore está en desuso. Use el nuevo Microsoft.Bot.Builder.Azure.Blobs.BlobsTranscriptStore en su 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>");

   ...
}

Almacenamiento de las conversaciones del usuario en transcripciones de blobs de Azure

Después de tener disponible un contenedor de blobs para almacenar las transcripciones, puede comenzar a conservar las conversaciones de los usuarios con el bot. Estas conversaciones se pueden utilizar más adelante como una herramienta de depuración para ver cómo interactúan los usuarios con el bot. Cada vez que se elige la opción Reiniciar conversación del emulador se inicia la creación de una nueva lista de conversación de transcripción. El siguiente código conserva las entradas de la conversación del usuario en un archivo de transcripciones almacenado.

  • La transcripción actual se guarda mediante LogActivityAsync.
  • Las transcripciones guardadas se recuperan mediante ListTranscriptsAsync. En este ejemplo de código, el identificador de cada transcripción almacenada se guarda en una lista llamada "storedTranscripts". Esta lista se usa más adelante para administrar el número de transcripciones de blobs almacenadas que se conservan.

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);

    ...
}

Administración de las transcripciones de blobs almacenadas

Aunque las transcripciones almacenadas se pueden usar como una herramienta de depuración, con el tiempo, el número de transcripciones almacenadas puede crecer más de lo que desea conservar. El código adicional que se incluye a continuación usa DeleteTranscriptAsync para eliminarlas todas excepto los tres últimos elementos de transcripción recuperados del almacén de transcripciones del blob.

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 más información sobre la clase, consulte Almacenamiento de transcripciones Blob de Azure.

Información adicional

Administración de la simultaneidad mediante eTags

En nuestro ejemplo de código de bot, establecemos la propiedad eTag de cada elemento IStoreItem en *. Cosmos DB utiliza el miembro eTag (etiqueta de entidad) del objeto de almacén para administrar la simultaneidad. La etiqueta eTag indica a la base de datos qué hacer si otra instancia del bot ha cambiado el objeto en el mismo almacenamiento en el que está escribiendo su bot.

La última escritura tiene prioridad: permitir la sobrescritura

Un valor de propiedad eTag de asterisco (*) indica que la última escritura tiene prioridad. Al crear un nuevo almacén de datos, puede establecer la etiqueta eTag de una propiedad en * para indicar que no ha guardado previamente los datos que está escribiendo, o que desea que el último escritor sobrescriba cualquier propiedad guardada previamente. Si la simultaneidad no es un problema para el bot, establezca la propiedad eTag en * para habilitar la sobrescritura para los datos que escriba.

Mantenimiento de la simultaneidad y evitación de la sobrescritura

Cuando almacene datos en Cosmos DB, use un valor distinto de * en la propiedad eTag si desea evitar el acceso simultáneo a una propiedad y sobrescribir los cambios de otra instancia del bot. El bot recibe una respuesta de error con el mensaje etag conflict key= cuando intenta guardar los datos de estado, y la etiqueta eTag no tiene el mismo valor que eTag en el almacenamiento.

De forma predeterminada, el almacén de Cosmos DB comprueba la igualdad de la propiedad eTag de un objeto de almacenamiento cada vez que un bot escribe en ese elemento y, a continuación, lo actualiza a un nuevo valor único después de cada escritura. Si la propiedad eTag en la escritura no coincide con la eTag en el almacenamiento, significa que otro subproceso o bot ha cambiado los datos.

Por ejemplo, supongamos que desea que su bot edite una nota guardada, pero no quiere que sobrescriba los cambios que haya realizado otra instancia del bot. Si otra instancia del bot ha realizado modificaciones, lo que quiere es que el usuario edite la versión con las actualizaciones más recientes.

Primero, cree una clase que implemente IStoreItem.

EchoBot.cs

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

A continuación, cree una nota inicial mediante la creación de un objeto de almacenamiento y agregue el objeto a su almacén.

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);

A continuación, acceda y actualice la nota más adelante, manteniendo su eTag que usted lee desde el almacén.

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);
}

Si se ha actualizado la nota en el almacén antes de que haya escrito los cambios, la llamada a Write iniciará una excepción.

Para mantener la simultaneidad, siempre es necesario leer una propiedad desde el almacenamiento y luego modificar la propiedad que se ha leído, de esta manera eTag se mantiene. Si lee datos de usuario desde el almacén, la respuesta contendrá la propiedad de eTag. Si cambia los datos y escribe datos actualizados en el almacén, la solicitud debe incluir la propiedad de eTag que especifica el mismo valor que leyó anteriormente. Sin embargo, escribir un objeto con su eTag establecida en * permitirá que la escritura sobrescriba cualquier otro cambio.

Pasos siguientes

Ahora que sabe cómo leer y escribir directamente desde el almacenamiento, eche un vistazo a cómo puede usar el Administrador de estado para que lo haga por usted.