Assistente virtual para o Microsoft TeamsVirtual Assistant for Microsoft Teams

O virtual Assistant é um modelo de código aberto da Microsoft que permite que você crie uma solução de conversação robusta, mantendo o controle total da experiência do usuário, da identidade visual da organização e dos dados necessários.Virtual Assistant is a Microsoft open-source template that enables you to create a robust conversational solution while maintaining full control of user experience, organizational branding, and necessary data. O modelo principal do assistente virtual é o bloco de construção básico que reúne as tecnologias da Microsoft necessárias para criar um assistente virtual, incluindo o SDK da estrutura de bot, a compreensão da linguagem (Luis), o QnA Maker, bem como os recursos essenciais, incluindo o registro de habilidades, contas vinculadas, intenção de conversa básica para oferecer aos usuários finais uma variedade de interações e experiências contínuasThe Virtual Assistant core template is the basic building block that brings together the Microsoft technologies required to build a Virtual Assistant, including the Bot Framework SDK, Language Understanding (LUIS), QnA Maker, as well as essential capabilities including skills registration, linked accounts, basic conversational intent to offer end users a range of seamless interactions and experiences. Além disso, os recursos de modelo incluem exemplos ricos de habilidadesde conversa reutilizáveis.In addition, the template capabilities include rich examples of reusable conversational skills. Habilidades individuais podem ser integradas em uma solução de assistente virtual para permitir vários cenários.Individual skills can be integrated in a Virtual Assistant solution to enable multiple scenarios. Usando o SDK da estrutura de bot, as habilidades são apresentadas no formulário de código-fonte, permitindo que você personalize e estenda conforme necessário.Using the Bot Framework SDK, Skills are presented in source code form enabling you to customize and extend as required. Veja o que é uma habilidade da estrutura de bot.See What is a Bot Framework Skill.

Diagrama visão geral do assistente virtual

As atividades de mensagem de texto são roteadas para habilidades associadas pelo núcleo do assistente virtual usando um modelo de expedição .Text message activities are routed to associated skills by the Virtual Assistant core using a dispatch model.

Considerações de implementaçãoImplementation considerations

A decisão de adicionar um assistente virtual pode incluir muitos determinantes e diferentes para cada organização.The decision to add a Virtual Assistant can include many determinants and differ for each organization. Estes são os fatores que dão suporte à implementação de um assistente virtual para sua organização:Here are the factors that support implementing a Virtual Assistant for your organization:

  • Uma equipe central gerencia todas as experiências de funcionários e tem a capacidade de criar uma experiência de assistente virtual e gerenciar atualizações para a experiência principal, incluindo a adição de novas habilidades.A central team manages all employee experiences and has the capability to build a Virtual Assistant experience and manage updates to the core experience including the addition of new skills.
  • Existem vários aplicativos nas funções de negócios e/ou o número deve crescer no futuro.Multiple applications exist across business functions and/or the number is expected to grow in the future.
  • Os aplicativos existentes são personalizáveis, pertencentes à organização e podem ser convertidos em habilidades para um assistente virtual.Existing applications are customizable, owned by the organization, and can be converted into skills for a Virtual Assistant.
  • A equipe central de experiências de funcionários é capaz de influenciar as personalizações para aplicativos existentes e fornecer orientações necessárias para integrar os aplicativos existentes como habilidades na experiência do assistente virtualThe central employee-experiences team is able to influence customizations to existing apps and provide necessary guidance for integrating existing applications as skills in Virtual Assistant experience

A equipe central mantém o assistente e as equipes de funções corporativas contribuem as habilidades

Criar um assistente virtual focado em equipesCreate a Teams-focused Virtual Assistant

A Microsoft publicou um modelo do Visual Studio para criar habilidades e assistentes virtuais.Microsoft has published a Visual Studio template for building Virtual Assistants and skills. Com o modelo do Visual Studio, você pode criar um assistente virtual, equipado com uma experiência baseada em texto com suporte para cartões ricos limitados com ações.With the Visual Studio template, you can create a Virtual Assistant, powered by a text-based experience with support for limited rich cards with actions. Aprimoramos o modelo de base do Visual Studio para incluir recursos de plataforma do Microsoft Teams e experiências de aplicativo para o Power Great Teams.We have enhanced the Visual Studio base template to include Microsoft Teams platform capabilities and power great Teams app experiences. Alguns dos recursos incluem suporte para cartões adaptáveis avançados, módulos de tarefas, bate-papos de equipes/grupos e extensões de mensagens.A few of the capabilities include support for rich adaptive cards, task modules, teams/group chats and messaging extensions. Confira também o tutorial: Estenda seu assistente virtual para o Microsoft Teams.See also, Tutorial: Extend Your Virtual Assistant to Microsoft Teams.

Diagrama de alto nível de uma solução de assistente virtual

Adicionar cartões adaptáveis ao seu assistente virtualAdd adaptive cards to your Virtual Assistant

Para distribuir solicitações corretamente, seu assistente virtual precisa identificar o modelo de LUIS correto e a habilidade correspondente associada a ele.To dispatch requests properly, your Virtual Assistant needs to identify the correct LUIS model and corresponding skill associated with it. No entanto, o mecanismo de expedição não pode ser usado para atividades de ação de cartão, pois o modelo LUIS associado a uma habilidade pode não ser treinado para textos de ação de cartão, uma vez que são palavras-chave predefinidas, não utterances de um usuário.However, the dispatching mechanism cannot be used for card action activities since the LUIS model associated with a skill may not be trained for card action texts since these are fixed, pre-defined keywords, not utterances from a user.

Resolvemos isso incorporando informações de habilidade na carga de ações do cartão.We have resolved this by embedding skill information in the card action payload. Cada habilidade deve ser incorporada skillId no value campo de ações do cartão.Every skill should embed skillId in the value field of card actions. Esta é a melhor maneira de garantir que cada atividade de ação de cartão tenha as informações de habilidades relevantes e o assistente virtual podem utilizar essas informações para expedição.This is the best way to ensure that each card action activity carries the relevant skill information and Virtual Assistant can utilize this information for dispatching.

Veja a seguir um exemplo de dados de ação de cartão.Below is a card action data sample. Ao fornecer skillId o construtor, garantimos que as informações de habilidades estejam sempre presentes em ações de cartão.By providing skillId in the constructor we ensure that skill information is always present in card actions.

    public class CardActionData
    {
        public CardActionData(string skillId)
        {
            this.SkillId = skillId;
        }

        [JsonProperty("skillId")]
        public string SkillId { get; set; }
    }

    ...
    var button = new CardAction
    {
        Type = ActionTypes.MessageBack,
        Title = "Card action button",
        Text = "card action button text",
        Value = new CardActionData(<SkillId>),
    };

Em seguida, apresentamos SkillCardActionData uma classe no modelo do virtual Assistant para extrair skillId da carga de ação do cartão.Next, we introduce SkillCardActionData class in the Virtual Assistant template to extract skillId from the card action payload.

    // Skill Card action data should contain skillId parameter
    // This class is used to deserialize it and get skillId 
    public class SkillCardActionData
    {
        /// <summary>
        /// Gets the ID of the skil that should handle this card
        /// </summary>
        [JsonProperty("skillId")]
        public string SkillId { get; set; }
    }

Veja a seguir um trecho de código para extrair skillId dados de ação de cartão.Below is a code snippet to extract skillId from card action data. Implementamos como um método de extensão na classe Activity .We implemented it as an extension method in the Activity class.

    public static class ActivityExtensions
    {
        // Fetches skillId from CardAction data if present
        public static string GetSkillId(this Activity activity)
        {
            string skillId = string.Empty;

            try
            {
                if (activity.Type.Equals(ActivityTypes.Message) && activity.Value != null)
                {
                    var data = JsonConvert.DeserializeObject<SkillCardActionData>(activity.Value.ToString());
                    skillId = data.SkillId;
                }
                else if (activity.Type.Equals(ActivityTypes.Invoke) && activity.Value != null)
                {
                    var data = JsonConvert.DeserializeObject<SkillCardActionData>(JObject.Parse(activity.Value.ToString()).SelectToken("data").ToString());
                    skillId = data.SkillId;
                }
            }
            catch
            {
                // If not able to retrive skillId, empty skillId should be returned
            }

            return skillId;
        }
    }

Controlar as interrupções normalmenteHandle interruptions gracefully

O virtual Assistant pode lidar com interrupções em casos em que um usuário tenta invocar uma habilidade enquanto outra está ativa no momento.Virtual Assistant can handle interruptions in cases where a user tries to invoke a skill while another skill is currently active. Apresentamos TeamsSkillDialog e TeamsSwitchSkillDialog , com base no SkillDialog e no SwitchSkillDialogda estrutura de bot, para permitir que os usuários alternem uma experiência de habilidades de ações de cartão.we have introduced TeamsSkillDialog and TeamsSwitchSkillDialog, based on Bot Framework's SkillDialog and SwitchSkillDialog, to enable users to switch a skill experience from card actions. Para lidar com essa solicitação, o virtual Assistant solicita ao usuário uma mensagem de confirmação para trocar de habilidades.To handle this request the Virtual Assistant prompts the user with a confirmation message to switch skills.

Prompt de confirmação ao mudar para uma nova habilidade

Tratamento de solicitações de módulo de tarefaHandling task module requests

Para adicionar recursos de módulo de tarefa a um assistente virtual, dois métodos adicionais estão incluídos no manipulador de atividade do virtual Assistant: OnTeamsTaskModuleFetchAsync e OnTeamsTaskModuleSubmitAsync .To add task module capabilities to a Virtual Assistant, two additional methods are included in the Virtual Assistant activity handler: OnTeamsTaskModuleFetchAsync and OnTeamsTaskModuleSubmitAsync. Esses métodos ouvem as atividades relacionadas ao módulo de tarefas do assistente virtual, identificam a habilidade associada à solicitação e encaminham a solicitação para a habilidade identificada.These methods listen to task module-related activities from Virtual Assistant, identify the skill associated with the request, and forward the request to the identified skill.

O encaminhamento de solicitação é feito por meio do método SkillHttpClient, PostActivityAsync .Request forwarding is done via the SkillHttpClient, PostActivityAsync method. Ele retorna a resposta como InvokeResponse que é analisada e convertida em TaskModuleResponse .It returns the response as InvokeResponse which is parsed and converted to TaskModuleResponse .

    public static TaskModuleResponse GetTaskModuleRespose(this InvokeResponse invokeResponse)
    {
        if (invokeResponse.Body != null)
        {
            return new TaskModuleResponse()
            {
                Task = GetTask(invokeResponse.Body),
            };
        }

        return null;
    }

    private static TaskModuleResponseBase GetTask(object invokeResponseBody)
        {
            JObject resposeBody = (JObject)JToken.FromObject(invokeResponseBody);
            var task = resposeBody.GetValue("task");
            var taskType = task.SelectToken("type").ToString();

            return taskType switch
            {
                "continue" => new TaskModuleContinueResponse()
                {
                    Type = taskType,
                    Value = task.SelectToken("value").ToObject<TaskModuleTaskInfo>(),
                },
                "message" => new TaskModuleMessageResponse()
                {
                    Type = taskType,
                    Value = task.SelectToken("value").ToString(),
                },
                _ => null,
            };
        }

Uma abordagem semelhante é seguida para respostas de ações de cartão e de módulo de tarefa.A similar approach is followed for card action dispatching and task module responses. Os dados de ação buscar e enviar do módulo de tarefa são atualizados para incluir skillId .Task module fetch and submit action data is updated to include skillId. GetSkillIdO método de extensão de atividade extrai skillId da carga que fornece detalhes sobre a habilidade que precisa ser invocada.Activity Extension method GetSkillId extracts skillId from the payload which provides details about the skill that needs to be invoked.

Veja a seguir um trecho de código OnTeamsTaskModuleFetchAsync e OnTeamsTaskModuleSubmitAsync métodos.Below is a code snippet for OnTeamsTaskModuleFetchAsync and OnTeamsTaskModuleSubmitAsync methods.

    // Invoked when a "task/fetch" event is received to invoke task module.
    protected override async Task<TaskModuleResponse> OnTeamsTaskModuleFetchAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
    {
        try
        {
            string skillId = (turnContext.Activity as Activity).GetSkillId();
            var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).First().Value;

            // Forward request to correct skill
            var invokeResponse = await _skillHttpClient.PostActivityAsync(this._appId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken);

            return invokeResponse.GetTaskModuleRespose();
        }
        catch (Exception exception)
        {
            await turnContext.SendActivityAsync(_templateEngine.GenerateActivityForLocale("ErrorMessage"));
            _telemetryClient.TrackException(exception);

            return null;
        }
    }

    // Invoked when a 'task/submit' invoke activity is received for task module submit actions.
    protected override async Task<TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(ITurnContext<IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, CancellationToken cancellationToken)
    {
        try
        {
            string skillId = (turnContext.Activity as Activity).GetSkillId();
            var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).First().Value;

            // Forward request to correct skill
            var invokeResponse = await _skillHttpClient.PostActivityAsync(this._appId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken).ConfigureAwait(false);

            return invokeResponse.GetTaskModuleRespose();
        }
        catch (Exception exception)
        {
            await turnContext.SendActivityAsync(_templateEngine.GenerateActivityForLocale("ErrorMessage"));
            _telemetryClient.TrackException(exception);

            return null;
        }
    }

Além disso, todos os domínios de habilidade devem ser incluídos na validDomains seção no arquivo de manifesto do assistente virtual para que os módulos de tarefa invocados por meio de uma habilidade sejam renderizados adequadamente.Additionally, all skill domains must be included in the validDomains section in Virtual Assistant's manifest file so that task modules invoked via a skill render properly.

Lidando com escopos de aplicativos colaborativosHandling collaborative app scopes

Os aplicativos do teams podem existir em vários escopos, incluindo o chat 1:1, o chat de grupo e os canais.Teams apps can exist in multiple scopes including 1:1 chat, group chat, and channels. O modelo do assistente virtual principal foi projetado para 1:1 chats.The core Virtual Assistant template is designed for 1:1 chats. Como parte do assistente virtual de experiência de integração solicita aos usuários o nome e mantém o estado do usuário.As part of the onboarding experience Virtual Assistant prompts users for name and maintains user state. Como a experiência de integração não é adequada para o chat de grupo/escopos de canal, ela foi removida.Since that onboarding experience is not suited for group chat/channel scopes it has been removed.

As habilidades devem lidar com atividades em vários escopos (1:1 chat, chat de grupo e conversa de canal).Skills should handle activities in multiple scopes (1:1 chat, group chat, and channel conversation). Se qualquer um desses escopos não for suportado, as habilidades devem responder com uma mensagem apropriada.If any of these scopes are not supported, skills should respond with an appropriate message.

As seguintes funções de processamento foram adicionadas ao Core Assistant virtual:The following processing functions have been added to Virtual Assistant core:

  • O assistente virtual pode ser chamado sem nenhuma mensagem de texto de um chat de grupo ou canal.Virtual Assistant can be invoked without any text message from a group chat or channel.
  • Articulations são limpos (ou seja, remova o @mention necessário do bot) antes de enviar a mensagem para o módulo de expedição.Articulations are cleaned (i.e., remove the necessary @mention of the bot) before sending the message to the dispatch module.
    if (innerDc.Context.Activity.Conversation?.IsGroup == true)
    {
        // Remove bot atmentions for teams/groupchat scope
        innerDc.Context.Activity.RemoveRecipientMention();

        // If bot is invoked without any text, reply with FirstPromptMessage
        if (string.IsNullOrWhiteSpace(innerDc.Context.Activity.Text))
        {
            await innerDc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("FirstPromptMessage"));
            return EndOfTurn;
        }
    }

Tratamento de extensões de mensagensHandling messaging extensions

Os comandos para uma extensão de mensagens são declarados no arquivo de manifesto do aplicativo.The commands for a messaging extension are declared in your app manifest file. A interface de usuário de extensão de mensagens é alimentada por esses comandos.The messaging extension user interface is powered by those commands. Para que um assistente virtual Ligue um comando de extensão de mensagens (como uma habilidade anexada), o próprio manifesto do assistente virtual deve conter esses comandos.For a Virtual Assistant to power a messaging extension command (as an attached skill), a Virtual Assistant's own manifest must contain those commands. Os comandos do manifesto de uma habilidade individual também devem ser adicionados ao manifesto do assistente virtual.The commands from an individual skill's manifest should be added to the Virtual Assistant's manifest as well. A ID do comando fornece informações sobre uma habilidade associada acrescentando a ID do aplicativo da habilidade por um separador ( : ).The command ID provides information about an associated skill by appending the skill's app ID via a separator (:).

Veja a seguir um trecho de código do arquivo de manifesto de uma habilidade.Below is a snippet from a skill's manifest file.

 "composeExtensions": [
    {
        "botId": "<Skil_App_Id>",
        "commands": [
            {
                "id": "searchQuery",
                "context": [ "compose", "commandBox" ],
                "description": "Test command to run query",
    ....

E abaixo está o trecho de código do arquivo de manifesto do assistente virtual correspondente.And, below is the corresponding Virtual Assistant manifest file code snippet.

 "composeExtensions": [
    {
        "botId": "<VA_App_Id>",
        "commands": [
            {
                "id": "searchQuery:<skill_id>",
                "context": [ "compose", "commandBox" ],
                "description": "Test command to run query",
    ....

Depois que os comandos são invocados por um usuário, o assistente virtual pode identificar uma habilidade associada analisando a ID do comando, atualizar a atividade removendo o sufixo extra ( :<skill_id> ) da ID de comando e encaminhá-lo à habilidade correspondente.Once the commands are invoked by a user, the Virtual Assistant can identify an associated skill by parsing the command ID, update the activity by removing the extra suffix (:<skill_id>) from the command ID, and forward it to the corresponding skill. O código para uma habilidade não precisa manipular o sufixo extra, portanto, os conflitos entre as IDs de comando nas habilidades são evitados.The code for a skill doesn't need to handle the extra suffix, thus, conflicts between command IDs across skills are avoided. Com essa abordagem, todos os comandos de ação e de pesquisa de uma habilidade dentro de todos os contextos ("redigir", "commandBox" e "mensagem") podem ser alimentados por um assistente virtual.With this approach, all the search and action commands of a skill within all contexts ("compose", "commandBox" and "message") can be powered by a Virtual Assistant.

    const string MessagingExtensionCommandIdSeparator = ":";

    // Invoked when a 'composeExtension/submitAction' invoke activity is received for a messaging extension action command
    protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionSubmitActionAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
    {
        return await ForwardMessagingExtensionActionCommandActivityToSkill(turnContext, action, cancellationToken);
    }

    // Forwards invoke activity to right skill for messaging extension action commands.
    private async Task<MessagingExtensionActionResponse> ForwardMessagingExtensionActionCommandActivityToSkill(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
    {
        var skillId = ExtractSkillIdFromMessagingExtensionActionCommand(turnContext, action);
        var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == skillId).First().Value;
        var invokeResponse = await _skillHttpClient.PostActivityAsync(this._appId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken).ConfigureAwait(false);

        return invokeResponse.GetMessagingExtensionActionResponse();
    }

    // Extracts skill Id from messaging extension command and updates activity value
    private string ExtractSkillIdFromMessagingExtensionActionCommand(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action)
    {
        var commandArray = action.CommandId.Split(MessagingExtensionCommandIdSeparator);
        var skillId = commandArray.Last();

        // Update activity value by removing skill id before forwarding to the skill.
        var activityValue = JsonConvert.DeserializeObject<MessagingExtensionAction>(turnContext.Activity.Value.ToString());
        activityValue.CommandId = string.Join(MessagingExtensionCommandIdSeparator, commandArray, 0 commandArray.Length - 1);
        turnContext.Activity.Value = activityValue;

        return skillId;
    }

Algumas atividades de extensão de mensagens não incluem a ID de comando.Some messaging extension activities do not include the command ID. Por exemplo, composeExtension/selectItem contém apenas o valor da ação chamar toque.For example, composeExtension/selectItem contains only the value of the invoke tap action. Para identificar a habilidade associada, o skillId está anexado a cada cartão de item ao formar uma resposta para o OnTeamsMessagingExtensionQueryAsync .To identify the associated skill, skillId is attached to each item card while forming a response for OnTeamsMessagingExtensionQueryAsync. (Isso é semelhante à abordagem de adição de cartões adaptáveis ao seu assistente virtual.(This is similar to the approach for adding adaptive cards to your Virtual Assistant.

    // Invoked when a 'composeExtension/selectItem' invoke activity is received for compose extension query command.
    protected override async Task<MessagingExtensionResponse> OnTeamsMessagingExtensionSelectItemAsync(ITurnContext<IInvokeActivity> turnContext, JObject query, CancellationToken cancellationToken)
    {
        var data = JsonConvert.DeserializeObject<SkillCardActionData>(query.ToString());
        var skill = _skillsConfig.Skills.Where(s => s.Value.AppId == data.SkillId).First().Value;
        var invokeResponse = await _skillHttpClient.PostActivityAsync(this._appId, skill, _skillsConfig.SkillHostEndpoint, turnContext.Activity as Activity, cancellationToken).ConfigureAwait(false);

        return invokeResponse.GetMessagingExtensionResponse();
    }

Exemplo: converter o modelo de aplicativo de livro-a-Room em uma habilidade de assistente virtualExample: Convert the Book-a-room app template to a Virtual Assistant skill

Book-a-Room é um bot do Microsoft Teams que permite que os usuários encontrem e reservem rapidamente uma sala de reunião para 30 (padrão), 60 ou 90 minutos a partir da hora atual.Book-a-room is a Microsoft Teams bot that lets users quickly find and reserve a meeting room for 30 (default), 60, or 90 minutes starting from the current time. Os escopos de bot de livro-a-Room para conversas pessoais ou de 1:1.The Book-a-room bot scopes to personal or 1:1 conversations.

Assistente virtual com uma habilidade de "reservar uma sala"

A seguir estão as alterações delta introduzidas para convertê-lo em uma habilidade que pode ser anexada a um assistente virtual.Followings are the delta changes introduced to convert it to a skill which can be attached to a Virtual Assistant. Diretrizes semelhantes podem ser seguidas para converter qualquer bot v4 existente em uma habilidade.Similar guidelines can be followed to convert any existing v4 bot to a skill.

Manifesto de habilidadesSkill manifest

Um manifesto de habilidade é um arquivo JSON que expõe o ponto de extremidade de mensagem de uma habilidade, ID, nome e outros metadados relevantes (esse manifesto é diferente do manifesto usado para o Sideload de um aplicativo no Microsoft Teams) um assistente virtual requer um caminho para esse arquivo como uma entrada para anexar uma habilidade.A skill manifest is a JSON file that exposes a skill's messaging endpoint, id, name, and other relevant metadata (this manifest is different than the manifest used for sideloading an app in Microsoft Teams) A Virtual Assistant requires a path to this file as an input to attach a skill. Adicionamos o manifesto a seguir à pasta wwwroot do bot.We have added the following manifest to the bot's wwwroot folder.

botskills connect --remoteManifest "<url to skill's manifest>" ..
{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.1.preview-0.json",
  "$id": "microsoft_teams_apps_bookaroom",
  "name": "microsoft-teams-apps-bookaroom",
  "description": "microsoft-teams-apps-bookaroom description",
  "publisherName": "Your Company",
  "version": "1.1",
  "iconUrl": "<icon url>",
  "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
  "license": "",
  "privacyUrl": "<privacy url>",
  "endpoints": [
    {
      "name": "production",
      "protocol": "BotFrameworkV3",
      "description": "Production endpoint for the skill",
      "endpointUrl": "<endpoint url>",
      "msAppId": "skill app id"
    }
  ],
  "dispatchModels": {
    "languages": {
      "en-us": [
        {
          "id": "microsoft-teams-apps-bookaroom-en",
          "name": "microsoft-teams-apps-bookaroom LU (English)",
          "contentType": "application/lu",
          "url": "file://book-a-meeting.lu",
          "description": "English language model for the skill"
        }
      ]
    }
  },
  "activities": {
    "message": {
      "type": "message",
      "description": "Receives the users utterance and attempts to resolve it using the skill's LU models"
    }
  }
}

Integração do LUISLUIS Integration

O modelo de expedição do virtual Assistant é construído na parte superior dos modelos LUIS da habilidade associada.Virtual Assistant's dispatch model is built on top of attached skills' LUIS models. O modelo de expedição identifica a intenção de cada atividade de texto e descobre a habilidade associada a ela.The dispatch model identifies the intent for every text activity and finds out skill associated with it.

O virtual Assistant requer o modelo de LUIS da habilidade (em .lu formato) como uma entrada ao anexar uma habilidade.Virtual Assistant requires skill's LUIS model (in .lu format) as an input while attaching a skill. LUIS JSON pode ser convertido em .lu Format usando a ferramenta botframework-CLI.LUIS json can be converted to .lu format using botframework-cli tool.

botskills connect --remoteManifest "<url to skill's manifest>" --luisFolder "<path to the folder containing your Skill's .lu files>" --languages "en-us" --cs
npm i -g @microsoft/botframework-cli
bf luis:convert --in <pathToLUIS.json> --out <pathToLuFile>

O bot de livro a sala tem dois comandos principais para os usuários:Book-a-room bot has two main commands for users:

  • Book room
  • Manage Favorites

Criamos um modelo de LUIS que entende esses dois comandos.We have built a LUIS model understanding these two commands. Os segredos correspondentes precisam ser preenchidos cognitivemodels.json .Corresponding secrets need to be populated in cognitivemodels.json. O arquivo JSON LUIS correspondente pode ser encontrado aqui e é assim que o arquivo correspondente se .lu parece.The corresponding LUIS JSON file can be found here and this is how the corresponding .lu file looks like.

> ! Automatically generated by [LUDown CLI](https://github.com/Microsoft/botbuilder-tools/tree/master/Ludown), Tue Mar 31 2020 17:30:32 GMT+0530 (India Standard Time)

> ! Source LUIS JSON file: book-a-meeting.json

> ! Source QnA TSV file: Not Specified

> ! Source QnA Alterations file: Not Specified


> # Intent definitions

## BOOK ROOM
- book a room
- book room
- please book a room
- reserve a room
- i want to book a room
- i want to book a room please
- get me a room please
- get me a room


## MANAGE FAVORITES
- manage favorites
- manage favorite
- please manage my favorite rooms
- manage my favorite rooms please
- manage my favorite rooms
- i want to manage my favorite rooms

## None


> # Entity definitions


> # PREBUILT Entity definitions


> # Phrase list definitions


> # List entities

> # RegEx entities

Com essa abordagem, qualquer problema de comando de um usuário para o assistente virtual relacionado book room ou manage favorites pode ser identificado como um comando associado ao bot de livro a sala e é encaminhado para essa habilidade.With this approach, any command issues by a user to Virtual Assistant related to book room or manage favorites can be identified as a command associated with Book-a-room bot and is forwarded to this skill. Por outro lado, o bot de sala de livros e salas precisa usar o modelo de LUIS para entender esses comandos se não forem digitados como estão (por exemplo: I want to manage my favorite rooms ).On the other hand, Book-a-room room bot needs to use LUIS model to understand these commands if they are not typed as is (for example: I want to manage my favorite rooms).

Suporte a vários idiomasMulti-Language support

Para este exemplo, criamos apenas um modelo LUIS com cultura em inglês.For this example, we have only created a LUIS model with English culture. Você pode criar modelos do LUIS correspondentes a outros idiomas e adicionar entrada ao cognitivemodels.json .You can create LUIS models corresponding to other languages and add entry to cognitivemodels.json.

{
  "defaultLocale": "en-us",
  "languageModels": {
    "en-us": {
      "luisAppId": "",
      "luisApiKey": "",
      "luisApiHost": ""
    },
    "<your_language_culture>": {
      "luisAppId": "",
      "luisApiKey": "",
      "luisApiHost": ""
    }
  }
}

Em paralelo, adicione o .lu arquivo correspondente no caminho luisFolder.In parallel, add corresponding .lu file in luisFolder path. A estrutura de pastas deve ser a seguinte:Folder structure should be as follows:

| - luisFolder

        | - en-us

                | - book-a-meeting.lu

        | - your_language_culture

                | - book-a-meeting.lu

Atualize o comando botskills da seguinte maneira para modificar o languages parâmetro:Update botskills command as follows to modify languages parameter:

botskills connect --remoteManifest "<url to skill's manifest>" --luisFolder "<path to luisFolder>" --languages "en-us, your_language_culture" --cs

O virtual Assistant usa SetLocaleMiddleware para identificar a localidade atual e invocar o modelo de expedição correspondente.Virtual Assistant uses SetLocaleMiddleware to identify current locale and invoke corresponding dispatch model. (A atividade da estrutura do bot tem o campo locale que é usado por este middleware.) Recomendamos usar o mesmo para sua habilidade também.(Bot framework activity has locale field which is used by this middleware.) We recommend to use the same for your skill as well. O bot Book-a-Room não usa esse middleware e, em vez disso, obtém a localidade da entidade clientInfoda atividade da estrutura de bot.Book-a-room bot does not use this middleware and instead gets locale from Bot framework activity's clientInfo entity.

Validação de declaraçãoClaim validation

Adicionamos claimsValidator para restringir os chamadores à habilidade.We have added claimsValidator to restrict callers to the skill. Para permitir que um assistente virtual Chame essa habilidade, preencha a AllowedCallers matriz appsettings com essa ID de aplicativo do assistente virtual específico.To allow a Virtual Assistant to call this skill, populate AllowedCallers array from appsettings with that particular Virtual Assistant's app ID.

"AllowedCallers": [ "<caller_VA1_appId>", "<caller_VA2_appId>" ],

A matriz de chamadores permitidos pode restringir quais consumidores de habilidade podem acessar a habilidade.The allowed callers array can restrict which skill consumers can access the skill. Adicione uma única entrada * a esta matriz para aceitar chamadas de qualquer consumidor de habilidades.Add single entry * to this array, to accept calls from any skill consumer.

"AllowedCallers": [ "*" ],

A documentação detalhada para a adição de validação de declarações a uma habilidade pode ser encontrada aqui.Detailed documentation for adding claims validation to a skill can be found here.

Limitação de atualização de cartãoCard refresh limitation

A atualização da atividade (atualização de cartão) ainda não é suportada por meio do virtual Assistant (problema do GitHub).Updating activity (card refresh) is not supported yet via Virtual Assistant (github issue). Portanto, substituimos todas as chamadas de atualização de cartão ( UpdateActivityAsync ) por postar novas chamadas de cartão ( SendActivityAsync ).Hence, we have replaced all card refresh calls (UpdateActivityAsync) with posting new card calls(SendActivityAsync).

Ações de cartão e fluxos de módulo de tarefaCard actions and task module flows

Para encaminhar as atividades de cartão ou de módulo de tarefa para uma habilidade associada, a habilidade precisa incorporá skillId -la.To forward card action or task module activities to an associated skill, the skill needs to embed skillId to it. A ação de cartão de bot de livro-a-Room, busca e envio de cargas de ação são modificadas para conter skillId como um parâmetro.Book-a-room bot card action, task module fetch and submit action payloads are modified to contain skillId as a parameter.

Para obter mais informações, consulte esta seção nesta documentação.For more information refer this section from this documentation.

Gerenciar atividades de chat de grupo ou escopo de canalHandle activities from group chat or channel scope

O bot de livro-a-Room é projetado apenas para chats privados (escopo pessoal/1:1).Book-a-room bot is designed for private chats (personal/1:1 scope) only. Como o virtual Assistant foi personalizado para oferecer suporte ao chat de grupo e escopos de canal, o assistente virtual pode ser invocado desses escopos e, portanto, o bot de livro-a-Room pode obter atividades para o mesmo.Since we have customized Virtual Assistant to support group chat and channel scopes, the Virtual Assistant might be invoked from these scopes and thus, Book-a-room bot might get activities for the same. Logo, o bot Book-a-Room é personalizado para lidar com essas atividades.Hence Book-a-room bot is customized to handle those activities. O cheque foi colocado em OnMessageActivityAsync métodos do manipulador de atividade do bot do Book-a-Room.The check has been put in OnMessageActivityAsync methods of Book-a-room bot's activity handler.

    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        // Check if activities are from groupchat/ teams scope. This might happen when the bot is consumed by Virtual Assistant.
        if (turnContext.Activity.Conversation.IsGroup == true)
        {
            await ShowNotSupportedInGroupChatCardAsync(turnContext).ConfigureAwait(false);
        }
        else
        {
            ...
        }
    }

Você também pode aproveitar as habilidades existentes do repositório do bot Framework Solutions ou criar uma nova habilidade totalmente a partir do zero.You can also leverage existing skills from Bot Framework Solutions repository or create a new skill altogether from scratch. Os tutoriais do mais recentes podem ser encontrados aqui.Tutorials for the later can be found here. Consulte a documentação do assistente virtual e da arquitetura de habilidades.Please refer to documentation for Virtual Assistant and skills architecture.

Exemplo de código para começarSample code to get started

Limitações conhecidas do assistente virtualVirtual Assistant known limitations

  • EndOfConversation.EndOfConversation. Uma habilidade deve enviar uma endOfConversation atividade ao concluir uma conversa.A skill should send an endOfConversation activity when it finishes a conversation. com base nessa atividade, um assistente virtual termina o contexto com essa determinada habilidade e retorna ao contexto do virtual Assistant (raiz).basis this activity, a Virtual Assistant ends context with that particular skill and gets back into Virtual Assistant's (root) context. Para o bot de livro-a-Room, não há estado claro em que a conversa pode ser concluída.For Book-a-room bot, there is no clear state where conversation can be ended. Portanto, não enviamos endOfConversation o bot de livro a sala e quando o usuário deseja voltar para o contexto raiz eles podem simplesmente fazer isso por start over comando.Hence we have not sent endOfConversation from Book-a-room bot and when user wants to go back to root context they can simply do that by start over command.
  • Atualização de cartão.Card refresh. As atualizações de cartão ainda não são suportadas pelo virtual Assistant.Card refreshes is not yet supported through Virtual Assistant.
  • Extensões de mensagens.:Messaging extensions.:
    • Atualmente, um assistente virtual pode dar suporte a um máximo de dez comandos para extensões de mensagens.Currently, a Virtual Assistant can support a maximum of ten commands for messaging extensions.
    • A configuração de extensões de mensagens não é delimitada por comandos individuais, mas apenas para toda a extensão.Configuration of messaging extensions is not scoped to individual commands but for the entire extension itself. Isso limita a configuração de cada habilidade individual pelo assistente virtual.This limits configuration for each individual skill through Virtual Assistant.
    • As IDs de comando de extensões de mensagens têm um tamanho máximo de 64 caracteres e 37 caracteres serão usados para inserir informações de habilidades.Messaging extensions command IDs have a maximum length of 64 characters and 37 characters will be used for embedding skill information. Portanto, as restrições atualizadas para a ID de comando são limitadas a 27 caracteres.Thus, updated constraints for command ID are limited to 27 characters.