Chatbot - 사용자 환영하기


사용자에게 환영 메세지 보내기

봇 예제에서는 아래 그림과 같이 플로우가 발생한다.

welcome-user-flow

  • OnMembersAddedAsync : 봇에 새 사용자가 연결될 때마다 호출
  • OnMessageActivityAsync : 새 사용자 입력이 수신될때마다 호출. message 작업을 처리하도록 한다.

새 사용자가 연결될 떄마다 봇이 WelcomMessage, InfoMessage, PatternMessage를 표시한다.

새로운 사용자 입력이 들어오면 봇이 WelcomeUsertate의 DidBotWelcomeUser를 체크한다.

만약 false이면 환영 메세지를 보낸다.

사용자 상태 만들기

사용자 상태 개체는 시작시 만들어지고 종속성이 봇 생성자에 들어간다.

Startup.cs

// Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
services.AddSingleton<IStorage, MemoryStorage>();

// Create the User state.
services.AddSingleton<UserState>();

Bots/WelcomeUserBot.cs

private BotState _userState;

// Initializes a new instance of the "WelcomeUserBot" class.
public WelcomeUserBot(UserState userState)
{
    _userState = userState;
}

속성 접근자 만들기

OnMessageActivityAsync method에서 WelcomeUserState 에 대한 핸들을 제공하는 속성 접근자를 만든다. 이 속성 접근자를 만드는 거는 대화 및 상태 저장에서 다뤘었다.

속성 접근자를 만든다음, GetAsync method를 호출하여(getasync를 사용해서 상태 속성과 연결된 올바른 범위의 키를 가져온다고 했었다.) 올바른 범위로 저장된 키를 가져온다.

그리고 SaveChangesAsync method를 사용하여 상태 데이터를 저장한다.

Bots/WelcomeUserBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
    var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState());
    
    // Save any state changes.
    await _userState.SaveChangesAsync(turnContext);
}

새로 연결된 사용자 감지 및 인사하기

WelcomeUserBot에서 OnMembersAddedAsync()를 통해 활동 업데이트를 확인하여 새로운 사용자가 대화에 추가되었는지 본 다음,

초기에 환영 메세지 3개(WelcomMessage, InfoMessage, PatternMessage)를 전송한다.

Bots/WelcomeUserBot.cs

protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (var member in membersAdded)
    {
        if (member.Id != turnContext.Activity.Recipient.Id)
        {
            await turnContext.SendActivityAsync($"Hi there - {member.Name}. {WelcomeMessage}", cancellationToken: cancellationToken);
            await turnContext.SendActivityAsync(InfoMessage, cancellationToken: cancellationToken);
            await turnContext.SendActivityAsync(PatternMessage, cancellationToken: cancellationToken);
        }
    }
}

새 사용자를 환영하고 초기 입력 무시

사용자 입력에 유용한 정보가 포함되었는지 확인하는 것도 중요하다. didBotWelcomeUser 상태 플래그를 확인해서 “False”인 경우 초기 사용자 입력을 처리하지 않고, 대신 초기 환영 메세지를 전송한다.

전송 후에는 welcomedUserProperty bool값이 “true”로 설정되어 UserState에 저장된다.

그리고 사용자 입력을 처리할 수 있게 하는 것 같다.

Bots/WelcomeUserBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
    var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState());

    if (didBotWelcomeUser.DidBotWelcomeUser == false)
    {
        didBotWelcomeUser.DidBotWelcomeUser = true;

        // the channel should sends the user name in the 'From' object
        var userName = turnContext.Activity.From.Name;

        await turnContext.SendActivityAsync($"You are seeing this message because this was your first message ever to this bot.", cancellationToken: cancellationToken);
        await turnContext.SendActivityAsync($"It is a good practice to welcome the user and provide personal greeting. For example, welcome {userName}.", cancellationToken: cancellationToken);
    }
    else
    {
    }

    // Save any state changes.
    await _userState.SaveChangesAsync(turnContext);
}

## 추가 입력 처리

사용하자한테 환영 메세지를 보낸 후에는 봇이 사용자 입력에 따라 응답을 제공한다.

"intro"나 "help"를 입력하면 SendIntroCardAsync method가 호출되고 herocard를 보여준다.

```C#
// This example hardcodes specific utterances. You should use LUIS or QnA for more advance language understanding.
var text = turnContext.Activity.Text.ToLowerInvariant();
switch (text)
{
    case "hello":
    case "hi":
        await turnContext.SendActivityAsync($"You said {text}.", cancellationToken: cancellationToken);
        break;
    case "intro":
    case "help":
        await SendIntroCardAsync(turnContext, cancellationToken);
        break;
    default:
        await turnContext.SendActivityAsync(WelcomeMessage, cancellationToken: cancellationToken);
        break;
}

Herocard 사용

private static async Task SendIntroCardAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
    var card = new HeroCard();
    card.Title = "Welcome to Bot Framework!";
    card.Text = @"Welcome to Welcome Users bot sample! This Introduction card
                 is a great way to introduce your Bot to the user and suggest
                 some things to get them started. We use this opportunity to
                 recommend a few next steps for learning more creating and deploying bots.";
    card.Images = new List<CardImage>() { new CardImage("https://aka.ms/bf-welcome-card-image") };
    card.Buttons = new List<CardAction>()
    {
        new CardAction(ActionTypes.OpenUrl, "Get an overview", null, "Get an overview", "Get an overview", "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"),
        new CardAction(ActionTypes.OpenUrl, "Ask a question", null, "Ask a question", "Ask a question", "https://stackoverflow.com/questions/tagged/botframework"),
        new CardAction(ActionTypes.OpenUrl, "Learn how to deploy", null, "Learn how to deploy", "Learn how to deploy", "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"),
    };
    
    var response = MessageFactory.Attachment(card.ToAttachment());
    await turnContext.SendActivityAsync(response, cancellationToken);
}

처음에 사용자가 입장했을때 바로 환영 인사를 띄우는 거에 이거를 사용해야겠다.