有没有办法让机器人知道他们在哪个页面上?

Is there a way to make bots aware of what page they are on?

我有一个聊天机器人,最终将部署在多个网站上,有一些数字或变量需要根据网站进行更改(例如语言、QnA 数据库、对话框等)。我想用一个机器人来做这件事,只传递一个变量,这样它就知道它在哪个页面上呈现(举个简单的例子,让我们假设国家页面:我们、法国、德国等)。我未能成功将此信息传递给机器人。

理想情况下,这是在欢迎消息触发之前,但我根本无法发送它。我有一个自定义商店设置:

            const store = window.WebChat.createStore({}, function(dispatch) { return function(next) { return function(action) {
                if (action.type === 'WEB_CHAT/SEND_MESSAGE') {
                    // Message sent by the user
                    PageTitleNotification.Off();
                    clearTimeout(interval);
                } else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' && action.payload.activity.name !== "inactive") {
                    // Message sent by the bot
                    clearInterval(interval);
                    interval = setTimeout(function() {
                        // Change title to flash the page
                        PageTitleNotification.On('Are you still there?');
                        
                        // Notify bot the user has been inactive
                        dispatch.dispatch({
                            type: 'WEB_CHAT/SEND_EVENT',
                            payload: {
                                name: 'inactive',
                                value: ''
                            }
                        });
                        
                    }, 300000)
                }

                return next(action);
            }}});

但对于我的用例,我认为其中的内容并不重要,重要的是它已定义。这里的功能只是 1) 清除用户发送消息时的时间间隔和 2) 设置新的时间间隔并向 bot 发送 inactivity 消息。

我还有一条发送消息 activity,点击按钮即可获取文字记录。它看起来像这样:

            document.querySelector('#transcriptButton').addEventListener('click', function()  {
                return store.dispatch({
                    type: 'WEB_CHAT/SEND_MESSAGE',
                    payload: { text: 'Email me a transcript' }
                });
                /*return store.dispatch({
                    type: 'WEB_CHAT/SEND_EVENT',
                        payload: {
                            name: 'siteContext',
                            value: 'eatonchatbot indexBackup.html'
                    }
                });*/
            });

这会发送一条“前台通道”消息(我可以在 bot 中看到)来请求转录,这会启动对话。这样可行。注释掉的部分暗示了我正在尝试做的事情。我有一个单独的调度语句,如下所示,它具有与上面注释掉的完全相同的 SEND_EVENT 代码。 SEND_EVENT 在按下按钮时按预期工作。

这是我添加的附加代码。这是不工作的部分。我想要的是,在呈现机器人时(但最好是在欢迎消息之前),将此 siteContext 事件发送到机器人,以便我知道机器人的呈现位置。我在使用此代码的机器人中没有得到任何 activity。我也尝试用 SEND_MESSAGE 而不是 SEND_EVENT 替换它,在上面的一种反向测试中,但这也没有用。

            // Test setting site context
            store.dispatch({
                type: 'WEB_CHAT/SEND_EVENT',
                    payload: {
                    name: 'siteContext',
                    value: 'eatonchatbot indexBackup.html'
                }
            });

            /*store.dispatch({
                type: 'WEB_CHAT/SEND_MESSAGE',
                payload: {
                    text: 'eatonchatbot indexBackup.html'
                }
            });*/

我刚刚想到这个语句可能是 运行 在机器人被渲染之前。所以我把它放在一个间隔中,这确实有效。但是,在发送欢迎消息之前它不会触发消息。

            setTimeout(function() {
                store.dispatch({
                    type: 'WEB_CHAT/SEND_EVENT',
                    payload: {
                        name: 'siteContext',
                        value: 'eatonchatbot indexBackup.html'
                    }
                });
                        
            }, 5000);

所以这种方法可行,但如果需要此 siteContext 值来确定欢迎消息的语言,这显然会失败。所以我在这里的主要问题是,是否有更好的方法来尝试传递这样的 siteContext 值,或者是否有某种方法可以确保接收到上下文并可以在欢迎之前由机器人使用message fires? 我确实看到在 renderWebChat 方法中有一个区域设置,但我不知道我是否以及如何在 bot 中访问它,此外它可能不够精细,具体取决于业务需要。但似乎如果我可以在该 renderWebChat 对象中发送某种值,那可能会避免我尝试做的所有其他疯狂的事情。

在@Hessel 和 this issue 的帮助下,我在 GitHub 上找到了解决方案。如果您需要更改欢迎消息中的内容(例如,语言、用户名,或一共不同的消息)。 onMembersAdded 仍然会在可以设置值之前触发,至少如果您在 userState 中设置它们。关键是在 onEvent 中为直线和所有其他渠道设置单独的欢迎消息(我没有像示例中那样包括网络聊天,因为我没有为该渠道发送任何事件)。

这是我使用的 onEvent 函数:

        this.onEvent(async (context, next) => {

                // Check for inactivity
                if (context.activity.name && context.activity.name === 'inactive') {
                    await context.sendActivity({
                        text: 'Are you still there? Is there anything else I can help you with?',
                        name: 'inactive'
                    });
                }

                // Check for webchat/join event (directline conversation initiation)
                if (context.activity.name && context.activity.name === 'webchat/join') {
                    const userData = await this.userDialogStateAccessor.get(context, {});
                    userData.siteContext = context.activity.value;
                    
                    // Debug
                    console.log(`The current language is: ${userData.siteContext.language}`);
                    console.log(`The current page is: ${userData.siteContext.page}`);
                    //await context.sendActivity(`The current language is: ${userData.siteContext.language}`);
                    //await context.sendActivity(`The current page is: ${userData.siteContext.page}`);
                    
                    if (!userData.accountNumber) {
                        const dc = await this.dialogs.createContext(context);
                        await dc.beginDialog(AUTH_DIALOG);
                        await this.conversationState.saveChanges(context);
                        await this.userState.saveChanges(context);
                    } else {
                        if (context.activity.channelId == 'msteams') {
                            var welcomeCard = CardHelper.GetMenuCardTeams(welcomeMessage,'Y','Y');
                        } else {
                            var welcomeCard = CardHelper.GetMenuCard(welcomeMessage,'Y','Y');
                        }
                        await context.sendActivity(welcomeCard);
                        this.appInsightsClient.trackEvent({name:'conversationStart', properties:{accountNumber:userData.accountNumber}});
                    }

                    await this.userState.saveChanges(context);
                    
                }
            
            // By calling next() you ensure that the next BotHandler is run.
            await next();
        });

我在自定义商店中使用的事件与上面几乎相同,除了我更新它以引入最喜欢的语言和当前 url(在上面硬编码)。

          store = window.WebChat.createStore({}, function (dispatch) {
            return function (next) {
              return function (action) {
                if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
                  dispatch.dispatch({
                    type: 'WEB_CHAT/SEND_EVENT',
                    payload: {
                      name: 'webchat/join',
                      value: {
                        language: navigator.languages[0],
                        page: window.location.href
                      }
                    }
                  });
                }

                return next(action);
              };
            };
          });

如果您的 renderWebChat 方法位于您可以调用的函数中,这样您的机器人就不会自动启动(我有一个浮动图标会导致机器人加载 onclick),这应该在该函数之外。