Power Virtual Agents로 Microsoft Bot Framework 봇 사용

이 문서는 Microsoft Bot Framework 디스패처를 사용하여 기존 봇을 Power Virtual Agents 봇과 통합하는 방법을 다룹니다. 개발자 도구, 유틸리티 및 통합 개발 환경(IDE)에 대해 잘 알고 있는 IT 관리자나 개발자와 같은 숙련된 IT 전문가를 대상으로 합니다.

필수 구성 요소

코드 샘플 및 종속성

이 문서에서 사용된 코드 조각은 다음 문서에서 볼 수 있습니다.

Power Virtual Agents 환경에서 토픽 및 발화 검색

Power Virtual Agents 봇의 콘텐츠(토픽 및 발화), 테넌트의 끝점 및 Direct Line 암호를 검색해야 합니다.

봇에서 봇 ID 및 테넌트 ID 검색

  1. Microsoft Edge에서 F12를 선택하여 DevTools를 엽니다. (참고: 다른 브라우저의 경우 비슷한 명령 및 기능을 사용하십시오.)

  2. Azure Active Directory(Azure AD) 자격 증명을 사용하여 Power Virtual Agents 환경에 로그인합니다.

  3. 네트워크 탭으로 이동합니다.

    네트워크 탭을 표시하는 Microsoft Edge 브라우저의 DevTools

  4. 클라이언트 요청을 필터링하고 찾으십시오.

  5. 다음 세부 정보를 복사합니다.

    signedInUserAccountInfo.defaultBot.aadTenantId
    signedInUserAccountInfo.defaultBot.id
    signedInUserAccountInfo.defaultBot.name
    
  6. 위의 정보를 파일에 저장하십시오. 나중에 필요합니다.

봇에서 토픽 및 발화 검색

  1. Common Data Service에서 BotContentAnnotations를 내보냅니다. 데이터를 내보내는 방법을 검토합니다.

  2. Zip 파일을 다운로드하고 압축 해제하여 두 개의 CSV 파일 annotations.csvmsdynce_botcontents.csv를 찾으십시오.

내보낸 콘텐츠를 .LU 형식으로 변환

  1. ContentConverter 유틸리티를 사용하여 봇 콘텐츠를 .lu 형식으로 변환하십시오.

    참고

    이 유틸리티를 컴파일하고 실행하려면 dotnet 코어 런타임을 다운로드, 추출 및 보유해야 합니다.

  2. 이 코드 샘플을 컴파일하고 실행하려면 다음 명령을 사용하십시오.

    dotnet run -p ContentConverter.csproj -c Release -- -i <path to msdynce_botcontents.csv> -c <path to annotations.csv> -b <your bot id>
    
  3. Content.lu 파일을 LUIS JSON 파일 형식으로 변환하십시오.

    ludown parse ToLuis --in Content.lu
    

Power Virtual Agents 토픽으로 디스패처 사용자 지정 모델 교육

디스패처 도구를 사용하여 디스패처 앱을 훈련 및 재작성하고 기존 Cognitive Service 의도(예: LUIS 및 / 또는 QnA Maker)로 내보낸 토픽과 발화를 추가하십시오. 자세한 내용은 디스패치 도구 자습서의 지침을 따르십시오.

  1. NuGet 패키지 관리자를 사용하여 디스패치 도구를 설치하십시오.

    CMD> npm install -g botdispatch
    
  2. 디스패치 도구를 사용하여 이전에 내보낸 토픽과 발화를 추가하십시오.

    CMD> dispatch add -type file -name l_dynamicsbot -f luis.json
    Enter required fields below.
    
    What name would you like for your dispatch:
    l_dynamicsbot
    What's your LUIS authoring key (from https://www.luis.ai/user/settings):
    <enter authoring key from URL above>
    What's your LUIS authoring region [westus, westeurope, australiaeast]:
    <pick your region: eg. westus>
    File: Content.lu added to l_dynamicsbot.dispatch
    
  3. 내보낸 토픽과 발화가 포함된 디스패치 모델을 생성하십시오.

    참고

    더 많은 토픽이 추가되면 디스패치 모델을 다시 훈련시켜야 합니다.

    CMD> dispatch create
    
    Exporting services for dispatch...
    Creating dispatch LUIS model json...
    Creating training data...
    Updating l_dynamicsbot model...
    Importing l_dynamicsbot model...
    Setting up intents to child services mapping for l_dynamicsbot...
    Add subscription key and publish child LUIS apps...
    Training l_dynamicsbot model...
    Publishing l_dynamicsbot model...
    Writing summary file ('test_prediction')...
    {
      "authoringRegion": "westus",
      "hierarchical": true,
      "useAllTrainingData": false,
      "dontReviseUtterance": false,
      "copyLuisData": true,
      "services": [
        {
          "path": "luis.json",
          "type": "file",
          "name": "l_dynamicsbot"
        }
      ],
      "serviceIds": [
        "1"
      ],
      "appId": "<REDACTED>",
      "authoringKey": "<REDACTED>",
      "version": "Dispatch",
      "region": "westus",
      "type": "dispatch",
      "name": "l_dynamicsbot"
    }
    Please review your dispatch model in ..\Summary.html
    

코드에서 새 디스패치 끝점 등록 및 트리거

다음 단계에서는 새 디스패치 끝점을 등록하고 사용자의 발화 의도와 일치할 때마다 트리거하는 코드를 추가해야 합니다. 우리는 Microsoft Bot Framework에서 제공된 샘플을 사용합니다.

  1. 디스패처 앱에서 appsettings.json을 업데이트하여 Power Virtual Agents 봇에 대한 새 끝점을 포함합니다.

    {
      "DynamicsBotId": "<Bot Id>",
      "DynamicsBotTenantId": "<Tenant Id>",
      "DynamicsBotName": "<Bot Name>",
      "DynamicsBotTokenEndpoint": "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken",
    }
    
  2. 프로젝트에 새 DynamicsBot 클래스를 추가합니다.

    public class DynamicsBotService
    {
      private readonly HttpClient _httpClient;
    
      public DynamicsBotService(DynamicsBotEndpoint endpoint, string botName)
      {
        Endpoint = endpoint;
        BotName = botName;
        ChannelData = new DynamicsBotChannelData(endpoint.BotId, endpoint.TenantId);
        _httpClient = new HttpClient();
      }
    
      public string BotName { get; }
    
      public DynamicsBotChannelData ChannelData { get; }
      public DynamicsBotEndpoint Endpoint { get; }
    
      public async Task<string> GetTokenAsync()
      {
        var httpRequest = new HttpRequestMessage();
        httpRequest.Method = new HttpMethod("GET");
        httpRequest.RequestUri = Endpoint.TokenUrl;
        var response = await _httpClient.SendAsync(httpRequest);
        var responseStr = await response.Content.ReadAsStringAsync();
        return SafeJsonConvert.DeserializeObject<DirectLineToken>(responseStr).token;
      }
    }
    
    public class DynamicsBotChannelData
    {
      public DynamicsBotChannelData(string botId, string tenantId)
      {
          DynamicsBotId = botId;
          DynamicsTenantId = tenantId;
      }
    
      // DO NOT CHANGE property name
      [JsonProperty("cci_bot_id")]
      public string DynamicsBotId { get; }
    
      // DO NOT CHANGE property name
      [JsonProperty("cci_tenant_id")]
      public string DynamicsTenantId { get; }
    }
    
    public class DynamicsBotEndpoint
    {
      public DynamicsBotEndpoint(string botId, string tenantId, string tokenEndPoint)
      {
        BotId = botId;
        TenantId = tenantId;
        UriBuilder uriBuilder = new UriBuilder(tokenEndPoint);
        uriBuilder.Query = $"botId={BotId}&tenantId={TenantId}";
        TokenUrl = uriBuilder.Uri;
      }
    
      public string BotId { get; }
    
      public string TenantId { get; }
    
      public Uri TokenUrl { get; }
    }
    
    public class DirectLineToken
    {
      public string token { get; set; }
    }
    
  3. IBotServices.cs 파일에 Power Virtual Agents 봇에 대한 참조를 추가합니다.

    public interface IBotService
    {
      LuisRecognizer Dispatch { get; }
      QnAMaker SampleQnA { get; }
      DynamicsBotService DynamicsBotService { get; }
    }
    
  4. BotServices 생성자를 업데이트하여 BotServices.cs 파일에서 DynamicsBotService를 인스턴스화합니다.

    DynamicsBotService = new DynamicsBotService(new DynamicsBotEndpoint(
        configuration["DynamicsBotId"],
        configuration["DynamicsBotTenantId"],
        configuration["DynamicsBotTokenEndpoint"]),
        configuration["DynamicsBotName"]
    );
    
  5. DispatchBot.cs를 업데이트하여 의도 일치에서 Power Virtual Agents 봇에 대한 트리거를 추가합니다.

    private async Task ProcessDynamicsBotAsync(ITurnContext<Microsoft.Bot.Schema.IMessageActivity> turnContext, CancellationToken     cancellationToken)
    {
        var token = await _botService.DynamicsBotService.GetTokenAsync();
    
        using (var directLineClient = new DirectLineClient(token))
        {
            var conversation = await directLineClient.Conversations.StartConversationAsync();
            var conversationtId = conversation.ConversationId;
    
            var response = await directLineClient.Conversations.PostActivityAsync(conversationtId, new Microsoft.Bot.Connector.DirectLine.Activity()
            {
                Type = Microsoft.Bot.Connector.DirectLine.ActivityTypes.Message,
                From = new Microsoft.Bot.Connector.DirectLine.ChannelAccount { Id = "userId", Name = "userName" },
                Text = turnContext.Activity.Text,
                ChannelData = JObject.FromObject(_botService.DynamicsBotService.ChannelData),
                TextFormat = "plain",
                Locale = "en-Us",
            });
    
            Thread.Sleep(4000);
    
            var activities = await GetActivitiesAsync(directLineClient, conversationtId, _botService.DynamicsBotService.BotName);
    
            var activity = turnContext.Activity as Microsoft.Bot.Schema.Activity;
    
            await turnContext.SendActivitiesAsync(
                       activities
                       .Select(message =>
                       {
                           var reply = activity.CreateReply(message.Text);
                           reply.Attachments = message?.Attachments?.Select(a => new Microsoft.Bot.Schema.Attachment()
                           {
                               Content = a.Content,
                               ContentType = a.ContentType,
                               ContentUrl = a.ContentUrl
                           }).ToList();
    
                           reply.SuggestedActions = new Microsoft.Bot.Schema.SuggestedActions()
                           {
                               Actions = message?.SuggestedActions?.Actions?.Select(a => new Microsoft.Bot.Schema.CardAction()
                               {
                                   Title = a.Title,
                                   Value = a.Value,
                                   Type = a.Type,
                                   Image = a.Image
                               }).ToList(),
                           };
    
                           return reply;
                       })
                       .ToArray());
        }
    }
    
    private async Task<List<Microsoft.Bot.Connector.DirectLine.Activity>> GetActivitiesAsync(DirectLineClient directLineClient, string conversationtId, string botName)
    {
        ActivitySet response = null;
        List<Microsoft.Bot.Connector.DirectLine.Activity> result = new List<Microsoft.Bot.Connector.DirectLine.Activity>();
        string watermark = null;
    
        do
        {
            response = await directLineClient.Conversations.GetActivitiesAsync(conversationtId, watermark);
            watermark = response.Watermark;
    
            result = response?.Activities?.Where(x =>
              x.Type == Microsoft.Bot.Connector.DirectLine.ActivityTypes.Message &&
                string.Equals(x.From.Name, botName, StringComparison.Ordinal)).ToList();
    
            if (result != null && result.Any())
            { return result; }
    
            Thread.Sleep(1000);
        } while (response.Activities.Any());
    
        return result;
    }
    
  6. Power Virtual Agents 봇이 단일 대체에 대해 일치하지 않는 의도를 처리하길 원하는 경우 DispatchToTopIntentAsync 메서드를 업데이트합니다.

    case "l_dynamicsbot":
    case "None":
    default:
        await ProcessDynamicsBotAsync(turnContext, cancellationToken);
        break;
    

봇 배포 및 디스패처 테스트

디스패처를 테스트하여 DynamicsBot과 다른 봇 간의 원활한 상호 작용을 보장할 준비가 되었습니다.

  1. 데모 웹 사이트에 봇 게시.

    봇 배포

  2. 디스패처 앱을 빌드(Ctrl + Shift + B)하고 실행(F5)합니다.

  3. 봇에 이름과 끝점을 추가하는 봇 에뮬레이터를 엽니다.

    봇 에뮬레이터에서 새 봇을 만들기 위한 대화