HoloLens (1º gênero) e Azure 312: Integração bot

Nota

Os tutoriais da Mixed Reality Academy foram desenhados com HoloLens (1º género) e Auscultadores Imersivos de Realidade Mista em mente. Como tal, sentimos que é importante deixar estes tutoriais no lugar para os desenvolvedores que ainda estão à procura de orientação no desenvolvimento para esses dispositivos. Estes tutoriais não serão atualizados com os mais recentes instrumentos ou interações a serem utilizados para HoloLens 2. Serão mantidos para continuar a trabalhar nos dispositivos suportados. Haverá uma nova série de tutoriais que serão publicados no futuro que demonstrarão como se desenvolver para HoloLens 2. Este aviso será atualizado com um link para esses tutoriais quando forem publicados.

Neste curso, você vai aprender a criar e implementar um bot usando o Microsoft Bot Framework V4 e comunicar com ele através de uma aplicação Windows Mixed Reality.

O Microsoft Bot Framework V4 é um conjunto de APIs projetado para fornecer aos desenvolvedores as ferramentas para construir uma aplicação de bot extensível e escalável. Para mais informações, visite a página Microsoft Bot Framework ou o Repositório V4 Git.

Após completar este curso, terá construído uma aplicação Windows Mixed Reality, que poderá fazer o seguinte:

  1. Utilize um Gesto de Toque para iniciar o bot a ouvir a voz dos utilizadores.
  2. Quando o utilizador disse algo, o bot tentará fornecer uma resposta.
  3. Exiba a resposta dos bots como texto, posicionado perto do bot, na Cena da Unidade.

Na sua aplicação, cabe-lhe a si integrar os resultados com o seu design. Este curso destina-se a ensinar-lhe como integrar um Serviço Azure com o seu projeto Unidade. É seu trabalho usar o conhecimento que ganha com este curso para melhorar a sua aplicação de realidade mista.

Suporte de dispositivos

Curso HoloLens Auscultadores imersivos
MR e Azure 312: Integração bot ✔️ ✔️

Nota

Embora este curso se centre principalmente em HoloLens, você também pode aplicar o que você aprende neste curso para Windows Mixed Reality auscultadores imersivos (VR). Como os auscultadores imersivos (VR) não têm câmaras acessíveis, vai precisar de uma câmara externa ligada ao seu PC. À medida que segue o curso, verá notas sobre quaisquer alterações que possa necessitar de utilizar para suportar auscultadores imersivos (VR).

Pré-requisitos

Nota

Este tutorial é projetado para desenvolvedores que têm experiência básica com Unidade e C#. Tenha também em atenção que os pré-requisitos e instruções escritas neste documento representam o que foi testado e verificado no momento da escrita (julho de 2018). É livre de utilizar o software mais recente, tal como listado no artigo de instalação, embora não deva presumir-se que as informações neste curso irão corresponder perfeitamente ao que encontrará no software mais recente do que o listado abaixo.

Recomendamos o seguinte hardware e software para este curso:

Antes de começar

  1. Para evitar encontrar problemas na construção deste projeto, sugere-se fortemente que crie o projeto mencionado neste tutorial numa pasta de raiz ou de raiz (os caminhos de pasta longa podem causar problemas no tempo de construção).
  2. Prepara e testa a tua HoloLens. Se precisar de apoio para configurar o seu HoloLens, visite o artigo de configuração HoloLens.
  3. É uma boa ideia executar a calibração e a sintonização sensor quando se começa a desenvolver uma nova aplicação HoloLens (por vezes pode ajudar a executar essas tarefas para cada utilizador).

Para obter ajuda na Calibração, siga este link para o artigo de calibração HoloLens.

Para obter ajuda no Sensor Afinação, siga este link para o artigo de Afinação de Sensores HoloLens.

Capítulo 1 - Criar a aplicação Bot

O primeiro passo é criar o seu bot como uma aplicação core ASP.Net local. Uma vez terminado e testado, irá publicá-lo no Portal Azure.

  1. Abra o Visual Studio. Crie um novo projeto, selecione ASP NET Core Web Application como o tipo de projeto (você vai encontrá-lo sob a subsecção .NET Core) e chamá-lo de MyBot. Clique em OK.

  2. Na janela que aparecerá selecione Empty. Certifique-se também de que o alvo está definido para ASP NET Core 2.0 e que a Autenticação está definida para Não Autenticação. Clique em OK.

    Crie a aplicação bot

  3. A solução vai agora abrir-se. Clique com o botão direito na Solução Mybot no Explorador de Solução e clique em Gerir pacotes nuget para solução.

    Criar a aplicação Bot

  4. No separador Procurar, procure microsoft.Bot.Builder.Integration.AspNet.Core (certifique-se de que tem Incluído pré-lançamento verificado). Selecione a versão pacote 4.0.1 pré-visualizaçãoe marque as caixas de projeto. Em seguida, clique em Instalar. Instalou agora as bibliotecas necessárias para o Bot Framework v4. Feche a página NuGet.

    Crie a aplicação bot

  5. Clique com o botão direito no seu Project,MyBot,no Solution Explorer e clique em AddClass.

    Criar a aplicação Bot

  6. Nomeie a classe MyBot e clique em Adicionar.

    Crie a aplicação bot

  7. Repita o ponto anterior, para criar outra classe chamada ConversationContext.

  8. Clique em wwwroot no Solution Explorer e clique em AdicionarNovo Item. Selecione a página HTML (irá encontrá-la na Web da subsecção). Diga o nome do ficheirodefault.html. Clique em Adicionar.

    Crie a aplicação bot

  9. A lista de classes/objetos no Solution Explorer deve parecer-se com a imagem abaixo.

    Crie a aplicação bot

  10. Clique duas vezes na aula de ConversationContext. Esta classe é responsável por manter as variáveis usadas pelo bot para manter o contexto da conversação. Estes valores de contexto de conversação são mantidos num caso desta classe, porque qualquer instância da classe MyBot irá refrescar-se cada vez que uma atividade é recebida. Adicione o seguinte código à classe:

    namespace MyBot
    {
        public static class ConversationContext
        {
            internal static string userName;
    
            internal static string userMsg;
        }
    }
    
  11. Clique duas vezes na aula de MyBot. Esta aula acolherá os manipuladores chamados por qualquer atividade recebida do cliente. Nesta aula irá adicionar o código utilizado para construir a conversação entre o bot e o cliente. Como mencionado anteriormente, um exemplo desta classe é inicializado cada vez que uma atividade é recebida. Adicione o seguinte código a esta classe:

    using Microsoft.Bot;
    using Microsoft.Bot.Builder;
    using Microsoft.Bot.Schema;
    using System.Threading.Tasks;
    
    namespace MyBot
    {
        public class MyBot : IBot
        {       
            public async Task OnTurn(ITurnContext context)
            {
                ConversationContext.userMsg = context.Activity.Text;
    
                if (context.Activity.Type is ActivityTypes.Message)
                {
                    if (string.IsNullOrEmpty(ConversationContext.userName))
                    {
                        ConversationContext.userName = ConversationContext.userMsg;
                        await context.SendActivity($"Hello {ConversationContext.userName}. Looks like today it is going to rain. \nLuckily I have umbrellas and waterproof jackets to sell!");
                    }
                    else
                    {
                        if (ConversationContext.userMsg.Contains("how much"))
                        {
                            if (ConversationContext.userMsg.Contains("umbrella")) await context.SendActivity($"Umbrellas are $13.");
                            else if (ConversationContext.userMsg.Contains("jacket")) await context.SendActivity($"Waterproof jackets are $30.");
                            else await context.SendActivity($"Umbrellas are $13. \nWaterproof jackets are $30.");
                        }
                        else if (ConversationContext.userMsg.Contains("color") || ConversationContext.userMsg.Contains("colour"))
                        {
                            await context.SendActivity($"Umbrellas are black. \nWaterproof jackets are yellow.");
                        }
                        else
                        {
                            await context.SendActivity($"Sorry {ConversationContext.userName}. I did not understand the question");
                        }
                    }
                }
                else
                {
    
                    ConversationContext.userMsg = string.Empty;
                    ConversationContext.userName = string.Empty;
                    await context.SendActivity($"Welcome! \nI am the Weather Shop Bot \nWhat is your name?");
                }
    
            }
        }
    }
    
  12. Clique duas vezes na classe Startup. Esta aula vai inicializar o bot. Adicione o seguinte código à classe:

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Bot.Builder.BotFramework;
    using Microsoft.Bot.Builder.Integration.AspNet.Core;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace MyBot
    {
    public class Startup
        {
            public IConfiguration Configuration { get; }
    
            public Startup(IHostingEnvironment env)
            {
                var builder = new ConfigurationBuilder()
                    .SetBasePath(env.ContentRootPath)
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                    .AddEnvironmentVariables();
                Configuration = builder.Build();
            }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton(_ => Configuration);
                services.AddBot<MyBot>(options =>
                {
                    options.CredentialProvider = new ConfigurationCredentialProvider(Configuration);
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseDefaultFiles();
                app.UseStaticFiles();
                app.UseBotFramework();
            }
        }
    }
    
  13. Abra o ficheiro de classe Programa e verifique se o código nele é o mesmo que:

    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    
    namespace MyBot
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                BuildWebHost(args).Run();
            }
    
            public static IWebHost BuildWebHost(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    .Build();
        }
    }
    
  14. Lembre-se de guardar as suas alterações, para o fazer, vá ao FileSave All, da barra de ferramentas na parte superior do Visual Studio.

Capítulo 2 - Criar o Serviço Azure Bot

Agora que construiu o código para o seu bot, tem de publicá-lo a uma instância do Serviço de Bot da Web App, no Portal Azure. Este Capítulo irá mostrar-lhe como criar e configurar o Serviço Bot em Azure e, em seguida, publicar o seu código para ele.

  1. Primeiro, faça login no Portal Azure https://portal.azure.com ().

    1. Se ainda não tiver uma conta Azure, terá de criar uma. Se estiver a seguir este tutorial numa sala de aula ou em laboratório, peça ao seu instrutor ou a um dos proctors para ajudar a criar a sua nova conta.
  2. Assim que iniciar sessão, clique em Criar um recurso no canto superior esquerdo e procurar por Web App bot, e clique em Entrar.

    Criar o Serviço Azure Bot

  3. A nova página fornecerá uma descrição do Serviço de Bot da Web App. Na parte inferior esquerda desta página, selecione o botão Criar, para criar uma associação com este Serviço.

    Criar o Serviço Azure Bot

  4. Uma vez clicado no Criar:

    1. Insira o nome desejado para esta instância de Serviço.

    2. Selecione uma subscrição.

    3. Escolha um Grupo de Recursos ou crie um novo. Um grupo de recursos fornece uma forma de monitorizar, controlar o acesso, fornecer e gerir a faturação para uma recolha de ativos da Azure. Recomenda-se manter todos os Serviços Azure associados a um único projeto (por exemplo, como estes cursos) sob um grupo de recursos comuns).

      Se desejar ler mais sobre os Grupos de Recursos Azure, por favor siga este link

    4. Determine a localização do seu grupo de recursos (se estiver a criar um novo Grupo de Recursos). A localização seria idealmente na região onde a aplicação iria decorrer. Alguns ativos da Azure só estão disponíveis em certas regiões.

    5. Selecione o Nível de Preços apropriado para si, se esta for a primeira vez que cria um Serviço de Bot de Aplicação Web, um nível gratuito (chamado F0) deve estar disponível para si

    6. O nome da aplicação pode ser deixado da mesma forma que o nome Bot.

    7. Deixe o modelo bot como Básico (C#).

    8. O plano de serviço de aplicações/localização deveria ter sido preenchido automaticamente para a sua conta.

    9. Desconfiem do Armazenamento Azure que pretende utilizar para hospedar o seu Bot. Se ainda não tem um, pode criá-lo aqui.

    10. Também terá de confirmar que compreendeu os Termos e Condições aplicados a este Serviço.

    11. Clique em Criar.

      Criar o Serviço Azure Bot

  5. Uma vez clicado no Create,terá de esperar pela criação do Serviço, pode demorar um minuto.

  6. Uma notificação aparecerá no Portal assim que a instância de Serviço for criada.

    Criar o Serviço Azure Bot

  7. Clique na notificação para explorar a sua nova instância de Serviço.

    Criar o Serviço Azure Bot

  8. Clique no botão 'Ir ao recurso' na notificação para explorar a sua nova instância de Serviço. Será levado para a sua nova instância do Serviço Azure.

    Criar o Serviço Azure Bot

  9. Neste momento é necessário configurar uma funcionalidade chamada Direct Line para permitir que a aplicação do seu cliente comunique com este Serviço Bot. Clique em Canais,em seguida, na secção Adicionar um canal em destaque, clique no canal Configure Direct Line.

    Criar o Serviço Azure Bot

  10. Nesta página encontrará as chaves Secret que permitirão que a aplicação do seu cliente autente com o bot. Clique no botão Mostrar e pegue numa cópia de uma das Chaves visualizadas, pois vai precisar disso mais tarde no seu projeto.

    Criar o Serviço Azure Bot

Capítulo 3 – Publicar o Bot no Azure Web App Bot Service

Agora que o seu Serviço está pronto, precisa de publicar o seu código Bot, que construiu anteriormente, para o seu recém-criado Serviço de Bot de Aplicação Web.

Nota

Terá de publicar o seu Bot no Serviço Azure sempre que escoar alterações na solução/código Bot.

  1. Volte para a sua Solução Visual Studio que criou anteriormente.

  2. Clique com o botão direito no seu projeto MyBot, no Solution Explorer,em seguida, clique em Publicar.

    Publique o Bot no Azure Web App Bot Service

  3. Na página-alvo da publicação, clique em 'App Service'e, em seguida, selecione Existing, clique por último no Perfil de Criação (pode ter de clicar na seta dropdown ao lado do botão Publicar, se esta não for visível).

    Publique o Bot no Azure Web App Bot Service

  4. Se ainda não tiver iniciado sessão na sua Conta Microsoft, tem de o fazer aqui.

  5. Na página publicar encontrará que tem de definir a mesma Subscrição que utilizou para a criação do Serviço Bot da Web App. Em seguida, desenrem a Vista como Grupo de Recursos e, na estrutura da pasta drop down, selecione o Grupo de Recursos que criou anteriormente. Clique em OK.

    Publique o Bot no Azure Web App Bot Service

  6. Agora clique no botão Publicar e aguarde que o Bot seja publicado (pode demorar alguns minutos).

    Publique o Bot no Azure Web App Bot Service

Capítulo 4 - Criar o projeto Unidade

O seguinte é um conjunto típico para o desenvolvimento com realidade mista, e como tal, é um bom modelo para outros projetos.

  1. Abra a unidade e clique em Novo.

    Criar o projeto Unidade

  2. Agora terá de fornecer um nome de projeto de unidade. Insira HoloLens Bot. Certifique-se de que o modelo de projeto está definido para 3D. Desa esta medida para um local apropriado para si (lembre-se, mais perto dos diretórios de raiz é melhor). Em seguida, clique em Criar projeto.

    Criar o projeto Unidade

  3. Com a Unidade aberta, vale a pena verificar se o Script Editor padrão está definido para Visual Studio. Vá para Editar Preferências e, em seguida, a partir da nova janela, navegue para Ferramentas Externas. Alterar editor de script externo para Visual Studio 2017. Feche a janela Preferências.

    Criar o projeto Unidade

  4. Em seguida, vá ao File Build Definições e selecione Universal Windows Platform, em seguida, clique no botão 'Plataforma Switch' para aplicar a sua seleção.

    Criar o projeto Unidade

  5. Enquanto ainda está em File Build Definições e certifique-se de que:

    1. O dispositivo-alvo está definido para HoloLens

      Para os auscultadores imersivos, desaponte o dispositivo alvo a qualquer dispositivo.

    2. O Tipo de Construção está definido para D3D

    3. SDK está definido para as últimas instalações

    4. Visual Studio versão está definida para o mais recente instalado

    5. Build and Run está definido para máquina local

    6. Salve a cena e adicione-a à construção.

      1. Faça-o selecionando Add Open Scenes. Aparecerá uma janela de salvamento.

        Criar o projeto Unidade

      2. Crie uma nova pasta para isto e qualquer futuro, cena, em seguida, selecione o botão nova pasta, para criar uma nova pasta, nomeie-a Cenas.

        Criar o projeto Unidade

      3. Abra a pasta Cenas recém-criada e, em seguida, no nome Ficheiro: campo de texto, escreva BotScene,clique em Guardar.

        Criar o projeto Unidade

    7. As definições restantes, em Build Definições,devem ser deixadas como padrão por enquanto.

  6. Na janela Build Definições, clique no botão Player Definições, isto abrirá o painel relacionado no espaço onde o Inspetor está localizado.

    Criar o projeto Unidade

  7. Neste painel, é necessário verificar algumas definições:

    1. No separador Other Definições:

      1. A versão de tempo de execução de scripts deve ser experimental (NET 4.6 Equivalent); alterar isto requer um reinício do Editor.

      2. Scripting Backend deve ser .NET

      3. O nível de compatibilidade da API deve ser .NET 4.6

        Criar o projeto Unidade

    2. No separador Definições de Publicação, em Capacidades,verifique:

      • InternetClient

      • Microfone

        Criar o projeto Unidade

    3. Mais abaixo no painel, em XR Definições (encontrado abaixo Definições De Publicação),marque o Suporte à Realidade Virtual, certifique-se de que o Windows Mixed Reality SDK é adicionado.

      Criar o projeto Unidade

  8. Back in Build DefiniçõesUnity C# Projects já não está acinzentado; marque a caixa de verificação ao lado desta.

  9. Feche a janela Build Definições.

  10. Guarde a sua cena e projeto(FILE SAVE SCENE / FILE > SAVE PROJECT).

Capítulo 5 - Configuração da câmara

Importante

Se desejar saltar a componente De Unidade Configurar este curso e continuar em linha reta com o código, sinta-se livre para baixar este pacote Azure-MR-312-Unitity,importá-lo para o seu projeto como pacote personalizado, e depois continuar a partir do Capítulo 7.

  1. No painel hierarquia,selecione a Câmara Principal.

  2. Uma vez selecionados, poderá ver todos os componentes da Câmara Principal no painel do Inspetor.

    1. O objeto da câmara deve ser nomeado Câmara Principal (note a ortografia)
    2. A etiqueta principal da câmara deve ser definida para MainCamera (note a ortografia)
    3. Certifique-se de que a Posição de Transformação está definida para 0,0,0
    4. Desasse bandeiras para a cor sólida.
    5. Coloque a cor de fundo do componente da câmara em preto, Alpha 0 (Código Hex: #00000000)

    configuração da câmera

Capítulo 6 - Importar a biblioteca Newtonsoft

Para ajudá-lo a deserizar e serializar objetos recebidos e enviados para o Serviço Bot, precisa de descarregar a biblioteca Newtonsoft. Encontrará aqui uma versão compatível já organizada com a estrutura correta da pasta Unidade.

Para importar a biblioteca Newtonsoft para o seu projeto, use o Pacote de Unidade que veio com este curso.

  1. Adicione a embalagem .unity à Unidade utilizando a opção pacote personalizado pacote de pacote de importação de ativos.

    Importe a biblioteca Newtonsoft

  2. Na caixa 'Pacote de Unidade de Importação' que aparece, certifique-se de que tudo sob (e incluindo) Plugins é selecionado.

    Importe a biblioteca Newtonsoft

  3. Clique no botão Importar para adicionar os itens ao seu projeto.

  4. Vá à pasta Newtonsoft sob plugins na vista do projeto e selecione o plugin Newtonsoft.

  5. Com o plugin Newtonsoft selecionado, certifique-se de que qualquer plataforma não é controlada,então certifique-se de que o WSAPlayer também não é verificado,em seguida, clique em Aplicar. Isto é apenas para confirmar que os ficheiros estão configurados corretamente.

    Nota

    A marcação destes plugins configura-os apenas para serem utilizados no Editor de Unidade. Há um conjunto diferente deles na pasta WSA que será usado após a exportação do projeto da Unidade.

  6. Em seguida, tem de abrir a pasta WSA, dentro da pasta Newtonsoft. Verá uma cópia do mesmo ficheiro que acabou de configurar. Selecione o ficheiro e, em seguida, no inspetor, certifique-se de que

    • Qualquer Plataforma não é controlada
    • apenasWSAPlayer é verificado
    • O processo do não é verificado

Capítulo 7 - Criar o BotTag

  1. Crie um novo objeto Tag chamado BotTag. Selecione a Câmara Principal na cena. Clique no menu 'Tag drop down' no painel do Inspetor. Clique em Adicionar Tag.

    configuração da câmera

  2. Clique no + símbolo. Nomeie a nova Tag como BotTag, Save.

    configuração da câmera

Aviso

Não aplique o BotTag na Câmara Principal. Se tiver feito isto acidentalmente, certifique-se de que muda a etiqueta da Câmara Principal de volta para MainCamera.

Capítulo 8 - Criar a classe BotObjects

O primeiro script que precisa de criar é a classe BotObjects, que é uma classe vazia criada para que uma série de outros objetos de classe possam ser armazenados dentro do mesmo script e acedidos por outros scripts na cena.

A criação desta classe é puramente uma escolha arquitetónica, estes objetos poderiam, em vez disso, ser hospedados no script Bot que você vai criar mais tarde neste curso.

Para criar esta classe:

  1. Clique com o botão direito no painel Projecte, em seguida, crie pasta. Nomeie as pastas Scripts.

    Crie a pasta scripts.

  2. Clique duas vezes na pasta Scripts para abri-la. Em seguida, dentro dessa pasta, clique com o botão direito e selecione Criar Script C#. Nomeie o script BotObjects.

  3. Clique duas vezes no novo script BotObjects para abri-lo com Visual Studio.

  4. Elimine o conteúdo do script e substitua-o pelo seguinte código:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class BotObjects : MonoBehaviour{}
    
    /// <summary>
    /// Object received when first opening a conversation
    /// </summary>
    [Serializable]
    public class ConversationObject
    {
        public string ConversationId;
        public string token;
        public string expires_in;
        public string streamUrl;
        public string referenceGrammarId;
    }
    
    /// <summary>
    /// Object including all Activities
    /// </summary>
    [Serializable]
    public class ActivitiesRootObject
    {
        public List<Activity> activities { get; set; }
        public string watermark { get; set; }
    }
    [Serializable]
    public class Conversation
    {
        public string id { get; set; }
    }
    [Serializable]
    public class From
    {
        public string id { get; set; }
        public string name { get; set; }
    }
    [Serializable]
    public class Activity
    {
        public string type { get; set; }
        public string channelId { get; set; }
        public Conversation conversation { get; set; }
        public string id { get; set; }
        public From from { get; set; }
        public string text { get; set; }
        public string textFormat { get; set; }
        public DateTime timestamp { get; set; }
        public string serviceUrl { get; set; }
    }
    
  5. Certifique-se de que guarda as suas alterações na Visual Studio antes de regressar à Unidade.

Capítulo 9 - Criar a classe GazeInput

A próxima aula que vais criar é a aula gazeInput. Esta classe é responsável por:

  • Criar um cursor que represente o olhar do jogador.
  • Detetando objetos atingidos pelo olhar do leitor e segurando uma referência a objetos detetados.

Para criar esta classe:

  1. Vá à pasta Scripts que criou anteriormente.

  2. Clique com o botão direito dentro da pasta, Crie O Script C#. Chame o script GazeInput.

  3. Clique duas vezes no novo script GazeInput para abri-lo com Visual Studio.

  4. Insira a seguinte linha mesmo em cima do nome da classe:

    /// <summary>
    /// Class responsible for the User's gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    
  5. Em seguida, adicione as seguintes variáveis dentro da classe GazeInput, acima do método Iniciar():

        [Tooltip("Used to compare whether an object is to be interacted with.")]
        internal string InteractibleTag = "BotTag";
    
        /// <summary>
        /// Length of the gaze
        /// </summary>
        internal float GazeMaxDistance = 300;
    
        /// <summary>
        /// Object currently gazed
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        internal GameObject _oldFocusedObject { get; private set; }
    
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// Cursor object visible in the scene
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        internal bool Hit { get; private set; }
    
        internal Vector3 Position { get; private set; }
    
        internal Vector3 Normal { get; private set; }
    
        private Vector3 _gazeOrigin;
    
        private Vector3 _gazeDirection;
    
  6. O código para o início() método deve ser adicionado. Isto será chamado quando a classe rubricar:

        /// <summary>
        /// Start method used upon initialization.
        /// </summary>
        internal virtual void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
  7. Implementar um método que instantaneamente e configurará o cursor de gaze:

        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        internal GameObject CreateCursor()
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            newCursor.SetActive(false);
            // Remove the collider, so it does not block Raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
            newCursor.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);
            Material mat = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<MeshRenderer>().material = mat;
            mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
  8. Implemente os métodos que irão configurar o Raycast a partir da Câmara Principal e acompanhará o objeto focado atual.

        /// <summary>
        /// Called every frame
        /// </summary>
        internal virtual void Update()
        {
            _gazeOrigin = Camera.main.transform.position;
    
            _gazeDirection = Camera.main.transform.forward;
    
            UpdateRaycast();
        }
    
    
        /// <summary>
        /// Reset the old focused object, stop the gaze timer, and send data if it
        /// is greater than one.
        /// </summary>
        private void ResetFocusedObject()
        {
            // Ensure the old focused object is not null.
            if (_oldFocusedObject != null)
            {
                if (_oldFocusedObject.CompareTag(InteractibleTag))
                {
                    // Provide the OnGazeExited event.
                    _oldFocusedObject.SendMessage("OnGazeExited", 
                        SendMessageOptions.DontRequireReceiver);
                }
            }
        }
    
    
        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            _oldFocusedObject = FocusedObject;
            RaycastHit hitInfo;
    
            // Initialize Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance);
            HitInfo = hitInfo;
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                Position = hitInfo.point;
                Normal = hitInfo.normal;
    
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedObject = null;
    
                // Provide default position for cursor.
                Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance);
    
                // Provide a default normal.
                Normal = _gazeDirection;
            }
    
            // Lerp the cursor to the given position, which helps to stabilize the gaze.
            Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f);
    
            // Check whether the previous focused object is this same. If so, reset the focused object.
            if (FocusedObject != _oldFocusedObject)
            {
                ResetFocusedObject();
                if (FocusedObject != null)
                {
                    if (FocusedObject.CompareTag(InteractibleTag))
                    {
                        // Provide the OnGazeEntered event.
                        FocusedObject.SendMessage("OnGazeEntered",
                            SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
        }
    
  9. Certifique-se de que guarda as suas alterações na Visual Studio antes de regressar à Unidade.

Capítulo 10 - Criar a classe Bot

O guião que vais criar agora chama-se Bot. Esta é a classe central da sua aplicação, armazena:

  • As suas credenciais de Bot de aplicação web
  • O método que recolhe os comandos de voz do utilizador
  • O método necessário para iniciar conversas com o seu Web App Bot
  • O método necessário para enviar mensagens para o seu Web App Bot

Para enviar mensagens para o Serviço Bot, a coroutina SendMessageToBot irá construir uma atividade, que é um objeto reconhecido pela Estrutura bot como dados enviados pelo utilizador.

Para criar esta classe:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito dentro da pasta Scripts, clique em Criar Script C#. Diga o nome do script Bot.

  3. Clique duas vezes no novo script para abri-lo com Visual Studio.

  4. Atualize os espaços de nome para serem os mesmos que os seguintes, no topo da classe Bot:

    using Newtonsoft.Json;
    using System.Collections;
    using System.Text;
    using UnityEngine;
    using UnityEngine.Networking;
    using UnityEngine.Windows.Speech;
    
  5. Dentro da classe Bot adicione as seguintes variáveis:

        /// <summary>
        /// Static instance of this class
        /// </summary>
        public static Bot Instance;
    
        /// <summary>
        /// Material of the sphere representing the Bot in the scene
        /// </summary>
        internal Material botMaterial;
    
        /// <summary>
        /// Speech recognizer class reference, which will convert speech to text.
        /// </summary>
        private DictationRecognizer dictationRecognizer;
    
        /// <summary>
        /// Use this variable to identify the Bot Id
        /// Can be any value
        /// </summary>
        private string botId = "MRBotId";
    
        /// <summary>
        /// Use this variable to identify the Bot Name
        /// Can be any value
        /// </summary>
        private string botName = "MRBotName";
    
        /// <summary>
        /// The Bot Secret key found on the Web App Bot Service on the Azure Portal
        /// </summary>
        private string botSecret = "-- Add your Secret Key here --"; 
    
        /// <summary>
        /// Bot Endpoint, v4 Framework uses v3 endpoint at this point in time
        /// </summary>
        private string botEndpoint = "https://directline.botframework.com/v3/directline";
    
        /// <summary>
        /// The conversation object reference
        /// </summary>
        private ConversationObject conversation;
    
        /// <summary>
        /// Bot states to regulate the application flow
        /// </summary>
        internal enum BotState {ReadyToListen, Listening, Processing}
    
        /// <summary>
        /// Flag for the Bot state
        /// </summary>
        internal BotState botState;
    
        /// <summary>
        /// Flag for the conversation status
        /// </summary>
        internal bool conversationStarted = false;
    

    Nota

    Certifique-se de que insere a sua chave bot secret na variável botSecret. Você terá notado a sua Chave Secreta Bot no início deste curso, no Capítulo 2, passo 10.

  6. O Código para Despertar() e Arranque() agora precisa ser adicionado.

        /// <summary>
        /// Called on Initialization
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called immediately after Awake method
        /// </summary>
        void Start()
        {
            botState = BotState.ReadyToListen;
        }
    
  7. Adicione os dois manipuladores que são chamados pelas bibliotecas de fala quando a captura de voz começa e termina. O DitadoRecognizer deixará automaticamente de capturar a voz do utilizador quando o utilizador deixar de falar.

        /// <summary>
        /// Start microphone capture.
        /// </summary>
        public void StartCapturingAudio()
        {
            botState = BotState.Listening;
            botMaterial.color = Color.red;
    
            // Start dictation
            dictationRecognizer = new DictationRecognizer();
            dictationRecognizer.DictationResult += DictationRecognizer_DictationResult;
            dictationRecognizer.Start();
        }
    
    
        /// <summary>
        /// Stop microphone capture.
        /// </summary>
        public void StopCapturingAudio()
        {
            botState = BotState.Processing;
            dictationRecognizer.Stop();
        }
    
    
  8. O seguinte manipulador recolhe o resultado da entrada de voz do utilizador e chama a coroutina responsável pelo envio da mensagem para o Serviço de Bot da Web App.

        /// <summary>
        /// This handler is called every time the Dictation detects a pause in the speech. 
        /// </summary>
        private void DictationRecognizer_DictationResult(string text, ConfidenceLevel confidence)
        {
            // Update UI with dictation captured
            Debug.Log($"User just said: {text}");      
    
            // Send dictation to Bot
            StartCoroutine(SendMessageToBot(text, botId, botName, "message"));
            StopCapturingAudio();
        }     
    
  9. A coroutina seguinte é chamada para iniciar uma conversa com o Bot. Notará que assim que a chamada de conversação estiver concluída, chamará o SendMessageToCoroutine,,. Isto é feito para levar o Serviço Bot a iniciar o diálogo.

        /// <summary>
        /// Request a conversation with the Bot Service
        /// </summary>
        internal IEnumerator StartConversation()
        {
            string conversationEndpoint = string.Format("{0}/conversations", botEndpoint);
    
            WWWForm webForm = new WWWForm();
    
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(conversationEndpoint, webForm))
            {
                unityWebRequest.SetRequestHeader("Authorization", "Bearer " + botSecret);
                unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
    
                yield return unityWebRequest.SendWebRequest();
                string jsonResponse = unityWebRequest.downloadHandler.text;
    
                conversation = new ConversationObject();
                conversation = JsonConvert.DeserializeObject<ConversationObject>(jsonResponse);
                Debug.Log($"Start Conversation - Id: {conversation.ConversationId}");
                conversationStarted = true; 
            }
    
            // The following call is necessary to create and inject an activity of type //"conversationUpdate" to request a first "introduction" from the Bot Service.
            StartCoroutine(SendMessageToBot("", botId, botName, "conversationUpdate"));
        }    
    
  10. A coroutina seguinte é chamada para construir a atividade a ser enviada para o Serviço Bot.

        /// <summary>
        /// Send the user message to the Bot Service in form of activity
        /// and call for a response
        /// </summary>
        private IEnumerator SendMessageToBot(string message, string fromId, string fromName, string activityType)
        {
            Debug.Log($"SendMessageCoroutine: {conversation.ConversationId}, message: {message} from Id: {fromId} from name: {fromName}");
    
            // Create a new activity here
            Activity activity = new Activity();
            activity.from = new From();
            activity.conversation = new Conversation();
            activity.from.id = fromId;
            activity.from.name = fromName;
            activity.text = message;
            activity.type = activityType;
            activity.channelId = "DirectLineChannelId";
            activity.conversation.id = conversation.ConversationId;     
    
            // Serialize the activity
            string json = JsonConvert.SerializeObject(activity);
    
            string sendActivityEndpoint = string.Format("{0}/conversations/{1}/activities", botEndpoint, conversation.ConversationId);
    
            // Send the activity to the Bot
            using (UnityWebRequest www = new UnityWebRequest(sendActivityEndpoint, "POST"))
            {
                www.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(json));
    
                www.downloadHandler = new DownloadHandlerBuffer();
                www.SetRequestHeader("Authorization", "Bearer " + botSecret);
                www.SetRequestHeader("Content-Type", "application/json");
    
                yield return www.SendWebRequest();
    
                // extrapolate the response Id used to keep track of the conversation
                string jsonResponse = www.downloadHandler.text;
                string cleanedJsonResponse = jsonResponse.Replace("\r\n", string.Empty);
                string responseConvId = cleanedJsonResponse.Substring(10, 30);
    
                // Request a response from the Bot Service
                StartCoroutine(GetResponseFromBot(activity));
            }
        }
    
  11. A coroutina seguinte é chamada a solicitar uma resposta após o envio de uma atividade para o Serviço Bot.

        /// <summary>
        /// Request a response from the Bot by using a previously sent activity
        /// </summary>
        private IEnumerator GetResponseFromBot(Activity activity)
        {
            string getActivityEndpoint = string.Format("{0}/conversations/{1}/activities", botEndpoint, conversation.ConversationId);
    
            using (UnityWebRequest unityWebRequest1 = UnityWebRequest.Get(getActivityEndpoint))
            {
                unityWebRequest1.downloadHandler = new DownloadHandlerBuffer();
                unityWebRequest1.SetRequestHeader("Authorization", "Bearer " + botSecret);
    
                yield return unityWebRequest1.SendWebRequest();
    
                string jsonResponse = unityWebRequest1.downloadHandler.text;
    
                ActivitiesRootObject root = new ActivitiesRootObject();
                root = JsonConvert.DeserializeObject<ActivitiesRootObject>(jsonResponse);
    
                foreach (var act in root.activities)
                {
                    Debug.Log($"Bot Response: {act.text}");
                    SetBotResponseText(act.text);
                }
    
                botState = BotState.ReadyToListen;
                botMaterial.color = Color.blue;
            }
        } 
    
  12. O último método a ser adicionado a esta classe, é necessário para exibir a mensagem na cena:

        /// <summary>
        /// Set the UI Response Text of the bot
        /// </summary>
        internal void SetBotResponseText(string responseString)
        {        
            SceneOrganiser.Instance.botResponseText.text =  responseString;
        }
    

    Nota

    Pode ver um erro dentro da Consola de Editores de Unidade, sobre a falta da classe SceneOrganiser. Ignore esta mensagem, pois irá criar esta aula mais tarde no tutorial.

  13. Certifique-se de que guarda as suas alterações na Visual Studio antes de regressar à Unidade.

Capítulo 11 - Criar a classe Interações

A classe que vai criar agora chama-se Interações. Esta classe é utilizada para detetar a HoloLens toque de entrada do utilizador.

Se o utilizador tocar enquanto olha para o objeto Bot na cena, e o Bot estiver pronto para ouvir as entradas de voz, o objeto Bot mudará de cor para vermelho e começará a ouvir entradas de voz.

Esta classe herda da classe GazeInput, pelo que é capaz de referenciar o método Start() e variáveis dessa classe, denotada pela utilização da base.

Para criar esta classe:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito dentro da pasta Scripts, clique em Criar Script C#. Nomeie o script Interações.

  3. Clique duas vezes no novo script para abri-lo com Visual Studio.

  4. Atualizar os espaços de nome e a herança de classe para ser o mesmo que o seguinte, no topo da classe Interações:

    using UnityEngine.XR.WSA.Input;
    
    public class Interactions : GazeInput
    {
    
  5. Dentro da classe Interações adicione a seguinte variável:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  6. Em seguida, adicione o método Iniciar()

        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        internal override void Start()
        {
            base.Start();
    
            //Register the application to recognize HoloLens user inputs
            _gestureRecognizer = new GestureRecognizer();
            _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap);
            _gestureRecognizer.Tapped += GestureRecognizer_Tapped;
            _gestureRecognizer.StartCapturingGestures();
        }
    
  7. Adicione o manipulador que será acionado quando o utilizador executar o gesto de toque em frente à câmara HoloLens

        /// <summary>
        /// Detects the User Tap Input
        /// </summary>
        private void GestureRecognizer_Tapped(TappedEventArgs obj)
        {
            // Ensure the bot is being gazed upon.
            if(base.FocusedObject != null)
            {
                // If the user is tapping on Bot and the Bot is ready to listen
                if (base.FocusedObject.name == "Bot" && Bot.Instance.botState == Bot.BotState.ReadyToListen)
                {
                    // If a conversation has not started yet, request one
                    if(Bot.Instance.conversationStarted)
                    {
                        Bot.Instance.SetBotResponseText("Listening...");
                        Bot.Instance.StartCapturingAudio();
                    }
                    else
                    {
                        Bot.Instance.SetBotResponseText("Requesting Conversation...");
                        StartCoroutine(Bot.Instance.StartConversation());
                    }                                  
                }
            }
        }
    
  8. Certifique-se de que guarda as suas alterações na Visual Studio antes de regressar à Unidade.

Capítulo 12 - Criar a classe SceneOrganiser

A última aula necessária neste laboratório chama-se SceneOrganiser. Esta aula configurará a cena programáticamente, adicionando componentes e scripts à Câmara Principal e criando os objetos apropriados na cena.

Para criar esta classe:

  1. Clique duas vezes na pasta Scripts para abri-la.

  2. Clique com o botão direito dentro da pasta Scripts, clique em Criar Script C#. Nomeie o script SceneOrganiser.

  3. Clique duas vezes no novo script para abri-lo com Visual Studio.

  4. Dentro da classe SceneOrganiser adicione as seguintes variáveis:

        /// <summary>
        /// Static instance of this class
        /// </summary>
        public static SceneOrganiser Instance;
    
        /// <summary>
        /// The 3D text representing the Bot response
        /// </summary>
        internal TextMesh botResponseText;
    
  5. Em seguida, adicione os métodos Despertar eIniciar()

        /// <summary>
        /// Called on Initialization
        /// </summary>
        private void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called immediately after Awake method
        /// </summary>
        void Start ()
        {
            // Add the GazeInput class to this object
            gameObject.AddComponent<GazeInput>();
    
            // Add the Interactions class to this object
            gameObject.AddComponent<Interactions>();
    
            // Create the Bot in the scene
            CreateBotInScene();
        }
    
  6. Adicione o seguinte método, responsável pela criação do objeto Bot na cena e pela configuração dos parâmetros e componentes:

        /// <summary>
        /// Create the Sign In button object in the scene
        /// and sets its properties
        /// </summary>
        private void CreateBotInScene()
        {
            GameObject botObjInScene = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            botObjInScene.name = "Bot";
    
            // Add the Bot class to the Bot GameObject
            botObjInScene.AddComponent<Bot>();
    
            // Create the Bot UI
            botResponseText = CreateBotResponseText();
    
            // Set properties of Bot GameObject
            Bot.Instance.botMaterial = new Material(Shader.Find("Diffuse"));
            botObjInScene.GetComponent<Renderer>().material = Bot.Instance.botMaterial;
            Bot.Instance.botMaterial.color = Color.blue;
            botObjInScene.transform.position = new Vector3(0f, 2f, 10f);
            botObjInScene.tag = "BotTag";
        }
    
  7. Adicione o seguinte método, responsável pela criação do objeto UI na cena, representando as respostas do Bot:

        /// <summary>
        /// Spawns cursor for the Main Camera
        /// </summary>
        private TextMesh CreateBotResponseText()
        {
            // Create a sphere as new cursor
            GameObject textObject = new GameObject();
            textObject.transform.parent = Bot.Instance.transform;
            textObject.transform.localPosition = new Vector3(0,1,0);
    
            // Resize the new cursor
            textObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
    
            // Creating the text of the Label
            TextMesh textMesh = textObject.AddComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleCenter;
            textMesh.alignment = TextAlignment.Center;
            textMesh.fontSize = 50;
            textMesh.text = "Hi there, tap on me and I will start listening.";
    
            return textMesh;
        }
    
  8. Certifique-se de que guarda as suas alterações na Visual Studio antes de regressar à Unidade.

  9. No Editor de Unidade, arraste o script SceneOrganiser da pasta Scripts para a Câmara Principal. O componente de Organizador de Cena deve agora aparecer no objeto da Câmara Principal, como mostra a imagem abaixo.

    Criar o Serviço Azure Bot

Capítulo 13 - Antes de construir

Para realizar um teste minucioso da sua aplicação, terá de a carregar lateralmente no seu HoloLens. Antes de o fazer, certifique-se de que:

  • Todas as definições mencionadas no capítulo 4 estão corretamente definidas.
  • O script SceneOrganiser está ligado ao objeto da Câmara Principal.
  • Na classe Bot, certifique-se de ter inserido a sua Chave Bot Secret na variável botSecret.

Capítulo 14 - Construir e Sideload ao HoloLens

Tudo o que é necessário para a secção de Unidade deste projeto já está concluído, pelo que é tempo de o construir a partir da Unidade.

  1. Navegue para construir Definições, construção de ficheiros Definições....

  2. A partir da janela Build Definições, clique em Construir.

    Construindo a app da Unidade

  3. Se já não for, marque projetos de Unidade C#.

  4. Clique em Construir. A Unidade lançará uma janela do Explorador de Ficheiros, onde precisa de criar e, em seguida, selecionará uma pasta para construir a aplicação. Crie esta pasta agora, e nomeie-a App. Em seguida, com a pasta App selecionada, clique em Selecionar Pasta.

  5. A unidade começará a construir o seu projeto para a pasta app.

  6. Uma vez terminada a construção da Unidade (pode demorar algum tempo), abrirá uma janela do Explorador de Ficheiros no local da sua construção (verifique a sua barra de tarefas, uma vez que pode nem sempre aparecer acima das suas janelas, mas irá notificá-lo da adição de uma nova janela).

Capítulo 15 - Implantação para HoloLens

Para implantar no HoloLens:

  1. Necessitará do endereço IP do seu HoloLens (para implementação remota) e para garantir que o seu HoloLens está no Modo de Desenvolvimento. Para efetuar este procedimento:

    1. Enquanto usa o HoloLens, abra a Definições.
    2. Ir para a Rede Internet Wi-Fi >> Opções Avançadas
    3. Note o endereço IPv4.
    4. Em seguida, volte a Definições, e depois atualizar segurança para desenvolvedores
    5. Definir modo de desenvolvedor ligado.
  2. Navegue para a sua nova build Unity (a pasta App) e abra o ficheiro de solução com Visual Studio.

  3. Na Configuração da Solução selecione Debug.

  4. Na Plataforma solução,selecione x86,Máquina Remota.

    Implemente a solução a partir de Visual Studio.

  5. Vá ao menu Construir e clique na Solução De Implementação,para carregar a aplicação para o seu HoloLens.

  6. A sua aplicação deve agora figurar na lista de aplicações instaladas no seu HoloLens, prontas a serem lançadas!

    Nota

    Para implementar para auscultadores imersivos, desloque a Plataforma de Solução para Máquina Local,e coloque a Configuração em Debug,com x86 como Plataforma. Em seguida, desloque-se para a máquina local, utilizando o menu Construir,selecionando a Solução de Implantação.

Capítulo 16 - Utilização da aplicação no HoloLens

  • Assim que lançar a aplicação, verá o Bot como uma esfera azul à sua frente.

  • Utilize o Gesto de Toque enquanto está a olhar para a esfera para iniciar uma conversação.

  • Aguarde o início da conversação (a UI apresentará uma mensagem quando acontecer). Assim que receber a mensagem introdutória do Bot, toque novamente no Bot para que fique vermelho e comece a ouvir a sua voz.

  • Assim que deixar de falar, a sua aplicação enviará a sua mensagem para o Bot e receberá prontamente uma resposta que será exibida na UI.

  • Repita o processo para enviar mais mensagens para o seu Bot (tem de tocar sempre que quiser sentir uma mensagem).

Esta conversa demonstra como o Bot pode reter informações (o seu nome), ao mesmo tempo que fornece informações conhecidas (como os itens que são armazenados).

Algumas perguntas para fazer ao Bot:

what do you sell? 

how much are umbrellas?

how much are raincoats?

A sua aplicação de Web App Bot (v4) acabada

Parabéns, construíste uma aplicação de realidade mista que aproveita o Azure Web App Bot, Microsoft Bot Framework v4.

Produto final

Exercícios de bónus

Exercício 1

A estrutura de conversação neste laboratório é muito básica. Use o Microsoft LUIS para dar ao seu bot capacidades de compreensão da linguagem natural.

Exercício 2

Este exemplo não inclui terminar uma conversa e reiniciar uma nova. Para completar a funcionalidade Bot, tente implementar o encerramento da conversa.