向用户发送欢迎消息

适用于:SDK v4

创建任何机器人的主要目标都是让用户参与富有意义的聊天。 实现此目标的最佳方法之一是确保从用户首次连接的那一刻起,他们就了解你的机器人的主要用途和功能,以及创建机器人的原因。 本文提供了帮助你欢迎用户使用机器人的代码示例。

注意

Bot Framework JavaScript、C# 和 Python SDK 将继续受支持,但 Java SDK 即将停用,最终长期支持将于 2023 年 11 月结束。

使用 Java SDK 构建的现有机器人将继续正常运行。

要生成新的机器人,请考虑使用 Microsoft Copilot Studio 并阅读选择正确的助理解决方案

有关详细信息,请参阅机器人构建的未来

先决条件

关于此示例代码

此示例代码演示如何在新用户开始连接到机器人时检测到他们并发送欢迎消息。 下图显示了此机器人的逻辑流。

机器人遇到的两个主要事件为:

  • OnMembersAddedAsync,在新用户连接到机器人时调用。
  • OnMessageActivityAsync,在机器人收到新用户输入时调用。

C# 示例的逻辑流图。

只要有新用户进行连接,机器人就会向其提供 WelcomeMessageInfoMessagePatternMessage。 收到新用户输入以后,系统会检查 WelcomeUserState,看是否已将 DidBotWelcomeUser 设置为 true。 如果否,则会将初始的欢迎用户消息返回给用户。

创建用户状态

用户状态对象在启动时创建,依赖项会注入机器人构造函数中。

Startup.cs


// Create the Bot Framework Authentication to be used with the Bot Adapter.
services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

// Create the Bot Adapter with error handling enabled.

Bots\WelcomeUserBot.cs


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

创建属性访问器

现在,我们创建了一个属性访问器,它为我们提供了 OnMessageActivityAsync 方法中 WelcomeUserState 的句柄。 接下来,调用 GetAsync 方法,获取已正确设置了范围的密钥。 然后,使用 SaveChangesAsync 方法在每次用户输入迭代以后保存用户状态数据。

Bots\WelcomeUserState.cs

// Gets or sets whether the user has been welcomed in the conversation.
public bool DidBotWelcomeUser { get; set; } = false;

Bots\WelcomeUserBot.cs

var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState(), cancellationToken);

await _userState.SaveChangesAsync(turnContext, cancellationToken: cancellationToken);
}

检测并问候新连接的用户

WelcomeUserBot 中使用 OnMembersAddedAsync() 检查活动更新即可了解是否已将新用户添加到聊天中,然后向该用户发送一组(共三条)初始的欢迎消息:WelcomeMessageInfoMessagePatternMessage。 此交互的完整代码显示在下面。

Bots\WelcomeUserBot.cs

public class WelcomeUserBot : ActivityHandler
{
    // Messages sent to the user.
    private const string WelcomeMessage = "This is a simple Welcome Bot sample. This bot will introduce you " +
                                            "to welcoming and greeting users. You can say 'intro' to see the " +
                                            "introduction card. If you are running this bot in the Bot Framework " +
                                            "Emulator, press the 'Start Over' button to simulate user joining " +
                                            "a bot or a channel";

    private const string InfoMessage = "You are seeing this message because the bot received at least one " +
                                        "'ConversationUpdate' event, indicating you (and possibly others) " +
                                        "joined the conversation. If you are using the emulator, pressing " +
                                        "the 'Start Over' button to trigger this event again. The specifics " +
                                        "of the 'ConversationUpdate' event depends on the channel. You can " +
                                        "read more information at: " +
                                        "https://aka.ms/about-botframework-welcome-user";

    private const string LocaleMessage = "You can use the activity's 'GetLocale()' method to welcome the user " +
                                         "using the locale received from the channel. " + 
                                         "If you are using the Emulator, you can set this value in Settings.";
{
    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($"{LocaleMessage} Current locale is '{turnContext.Activity.GetLocale()}'.", cancellationToken: cancellationToken);
            await turnContext.SendActivityAsync(PatternMessage, cancellationToken: cancellationToken);
        }
    }
}

欢迎新用户并放弃初始输入

此外还必须考虑在实际情况下用户的输入何时可能包含有用信息,这可能因通道而异。 为确保用户在所有可能的通道上获得良好的体验,我们将检查状态标志 didBotWelcomeUser。如果其值为“false”,我们将不处理初始用户输入。 而是向用户提供初始欢迎消息。 然后,布尔型 welcomedUserProperty 会被设置为“true”并存储在 UserState 中。现在,代码将处理此用户在所有其他消息活动中的输入。

Bots\WelcomeUserBot.cs

{
    var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
    var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState(), cancellationToken);

    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
await _userState.SaveChangesAsync(turnContext, cancellationToken: cancellationToken);
}

处理其他输入

欢迎新用户以后,机器人将针对每个消息轮次评估用户输入信息,并根据该用户输入的上下文提供响应。 以下代码显示用于生成该响应的决策逻辑。

输入为“简介”或“帮助”时,会调用函数 SendIntroCardAsync,为用户呈现一张说明性的英雄卡。 我们会在本文下一部分详细分析该代码。

Bots\WelcomeUserBot.cs

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

使用英雄卡问候语

如上所述,某些用户输入会导致系统生成一张英雄卡来响应用户请求。 可以在此处详细了解英雄卡问候语:发送简介卡。 下面是创建此机器人的英雄卡响应所需的代码。

Bots\WelcomeUserBot.cs

    {
        var card = new HeroCard
        {
            Title = "Welcome to Bot Framework!",
            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.",
            Images = new List<CardImage>() { new CardImage("https://aka.ms/bf-welcome-card-image") },
            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);
    }
}

测试机器人

下载并安装最新的 Bot Framework Emulator

  1. 在计算机本地运行示例。 如需说明,请参阅 C# 示例JavaScript 示例README 文件。
  2. 打开 Emulator 测试机器人。
    1. 当你开始与机器人对话时,它会向你发送一系列欢迎消息。

    2. 首次发送“hello”消息时,机器人会回复一些建议。

    3. 发送后续的“hello”消息时,机器人会回答“You said hello”。

      Emulator 中与机器人的初始交互的屏幕截图。

    4. 向机器人发送消息“help”。 它通过发送主图卡做出响应。

      Emulator 中帮助消息和机器人响应的屏幕截图。

其他资源

向消息添加媒体一文中详细了解各种媒体响应。

后续步骤