【问题标题】:Webchat Value Exchanging Issue on Botframework V4Botframework V4 上的网络聊天价值交换问题
【发布时间】:2020-05-27 01:50:14
【问题描述】:

我在 Botframework V4 上运行的 bot 上使用 Direct Line、MS Speech Service 和 Webchat.js。
我使用 webchat.js 从网页启动机器人,像这样将值传递给后端应用程序 https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/04.api/d.post-activity-event
用于在网络频道上实例化机器人的代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>FTD Bit_Bot</title>
</head>
<body style="background-color: #fff; background-image: url('img/FTDBackground.jpg');">
    <div id="chatbot" role="main"
         data-cb-width="320px"
         data-cb-height="400px"
         data-cb-border="1px solid #ededed"
         data-cb-border-radius="0px"
         data-cb-background-color="white"
         data-cb-position="fixed"
         data-cb-right="40px"
         data-cb-bottom="100px"
         data-cb-zIndex="1"
         data-cb-bubble-background="rgba(217, 217, 217, 0.15)"
         data-cb-bubble-from-user-background="#e22e2c"
         data-cb-bubble-from-user-text-color="white"
         data-cb-bubble-max-width="600"
         data-cb-bot-avatar-image="http://demo.radical-thinking.net/bella/microsoft/chat-assets/img/Chat-in-day-Workshop-Icon.png"
         data-cb-hide-send-box="false"
         data-cb-hide-upload-button="true"
         data-cb-send-box-button-color="#e22e2c"
         data-cb-send-box-button-color-on-disabled="#CCC"
         data-cb-send-box-button-color-on-focus="#333"
         data-cb-send-box-button-color-on-hover="#333"
         data-cb-send-box-height="30"
         data-cb-suggested-action-text-color="black"
         data-cb-suggested-action-border="solid 2px #e22e2c"
         data-cb-suggested-action-height="30">
    </div>
    <!-- Include ajax library for speech service token request call -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <!-- Include webchat client functionality (https://github.com/Microsoft/BotFramework-WebChat) -->
    <!-- Change to the latest directory to stop the 'No renderer for this activity' error. However the avatar won't show -->
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js" charset="utf-8"></script>
    <script>
        var chatbot = document.getElementById('chatbot');

        // Style modifications
        const styleOptions = {

            // Colors
            bubbleBackground: chatbot.dataset.cbBubbleBackground,
            bubbleFromUserBackground: chatbot.dataset.cbBubbleFromUserBackground,
            bubbleFromUserTextColor: chatbot.dataset.cbBubbleFromUserTextColor,
            bubbleMaxWidth: parseInt(chatbot.dataset.cbBubbleMaxWidth), // maximum width of text message

            // Avatar
            botAvatarImage: chatbot.dataset.cbBotAvatarImage,
            userAvatarInitials: '',

            // Send box
            hideSendBox: JSON.parse(chatbot.dataset.cbHideSendBox),
            hideUploadButton: JSON.parse(chatbot.dataset.cbHideUploadButton),
            sendBoxButtonColor: chatbot.dataset.cbSendBoxButtonColor,
            sendBoxButtonColorOnDisabled: chatbot.dataset.cbSendBoxButtonColorOnDisabled,
            sendBoxButtonColorOnFocus: chatbot.dataset.cbSendBoxButtonColorOnFocus,
            sendBoxButtonColorOnHover: chatbot.dataset.cbSendBoxButtonColorOnHover,
            sendBoxHeight: parseInt(chatbot.dataset.cbSendBoxHeight),

            // Suggested actions
            suggestedActionTextColor: chatbot.dataset.cbSuggestedActionTextColor,
            suggestedActionBorder: chatbot.dataset.cbSuggestedActionBorder,
            suggestedActionHeight: parseInt(chatbot.dataset.cbSuggestedActionHeight),

        }
    </script>
    <script>
        var chatbot = document.getElementById("chatbot");

        //style tag start
        var script = {
            id: 'chatbotStyle',
            type: 'text/css',
            style: document.createElement('style'),
            content: '@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,600"); ::-webkit-scrollbar{width:10px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888}::-webkit-scrollbar-thumb:hover{background:#555} #chatbot{ font-family: Roboto, sans-serif; font-weight: 400; position: fixed; right: 10px; bottom: 20px; text-align: center; } #chatbot img{ margin: auto; } #chatbot small{ display: block; font-size: 9px; } .initLaunchPad{ cursor: pointer; text-align: center; transition: .4s all; } .botHeader{min-height:40px;background:#ededed;border-radius:6px 6px 0 0;display:flex;justify-content:space-between;align-items:center;padding:4px} .botHeader img{float:left;width:32px;height:32px; border-radius:50%;background-color:#f9f9f9}.botHeader h5{float:left;padding:0!important;margin:4px 0 3px 6px} .botHeader h5 small{font-size: 12px;} .botHeader > div{width:40%;display:flex;align-items:center;text-align:left;height:32px} #botClose{cursor:pointer;font-size:12px;font-weight:600;padding:6px 8px;border-radius:4px;background-color:#e22e2c;color:#fff; } #botContainer{ display: none; border-radius: 8px; border:1px solid #cbcbcb; transition:.4s all; width: 310px; height: 420px; max-width:420px; max-height: 420px; margin-bottom: 4px; } #botBody{ height: 366px; } ',
            append: function () {
                this.style.type = this.type;
                this.style.appendChild(document.createTextNode(this.content));
                document.head.appendChild(this.style);
            }
        }; script.append();
        //style tag end

        //initLaunchPad started
        var initLaunchPad = document.createElement('div');
        initLaunchPad.classList.add('initLaunchPad');
        var initBotIcon = document.createElement('img');
        initBotIcon.src = "https://farm5.staticflickr.com/4876/39891228293_13c532f352_o.gif";
        initBotIcon.width = 86;
        initLaunchPad.appendChild(initBotIcon);
        chatbot.appendChild(initLaunchPad);

        $(function getSpeechAuthToken() {
            var params = {
                // Request parameters
            };

            $.ajax({
                url: "https://brazilsouth.api.cognitive.microsoft.com/sts/v1.0/issuetoken" + $.param(params),
                beforeSend: function (xhrObj) {
                    // Request headers
                    xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", "XXXXXX");
                },
                type: "POST",
                // Request body
                data: "{body}",
            })
                .done(function (data) {
                    speechAuthToken = data;
                })
                .fail(function () {
                    alert("error");
                });
        });
        initBotIcon.addEventListener('click', function (e) {
            e.preventDefault();
            initLaunchPad.style.display = "none";
            botContainer.style.display = "block";

            /*Call bot API*/
            (async function () {

                const searchParams = new URLSearchParams(window.location.search);

                //Speech Service Token Generation
                const subscriptionKey = 'XXXXXX';
                const region = 'brazilsouth';
                let webSpeechPonyfillFactory;

                //Speech Service Setting
                webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({
                    credentials: {
                        authorizationToken: speechAuthToken,
                        region: region
                    }
                });

                //Direct-Line BotToken Generation
                const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST', headers: { Authorization: 'Bearer ' + 'XXXXXX' } });
                const { token } = await res.json();

                window.WebChat.renderWebChat({
                    directLine: window.WebChat.createDirectLine({ token }),
                    store,
                    userID: "User",
                    styleOptions,
                    locale: 'pt-BR',
                    selectVoice: (voices, activity) =>
                        activity.locale === 'pt-BR'
                            ? voices.find(({ name }) => /Daniel/iu.test(name))
                            : voices.find(({ name }) => /Daniel/iu.test(name)) ||
                            voices.find(({ name }) => /Daniel/iu.test(name)),
                    webSpeechPonyfillFactory
                }, document.getElementById('botBody'));
                document.querySelector('#botBody > *').focus();

                var mainTag = chatbot.getElementsByClassName('main')[0];
                mainTag.style.borderTop = chatbot.dataset.cbBorder;
            })().catch(err => console.error(err));

            //Bot Message Exchange Setting 
            const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
                if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
                    dispatch({
                        type: 'WEB_CHAT/SEND_EVENT',
                        payload: {
                            name: 'userName',
                            value: Paul
                        }
                    });
                    dispatch({
                        type: 'WEB_CHAT/SEND_EVENT',
                        payload: {
                            name: 'userGenre',
                            value: male
                        }
                    });
                    dispatch({
                        type: 'WEB_CHAT/SEND_EVENT',
                        payload: {
                            name: 'activityName',
                            value: chatBotMission
                        }
                    });
                }
                return next(action);
            });

        //initLaunchPad ended

        var botContainer = document.createElement('div');
        botContainer.id = "botContainer";

        var botHeader = document.createElement('div');
        botHeader.classList.add('botHeader');

        var botClose = document.createElement('a');
        botClose.id = "botClose";
        botClose.innerText = "X";
        botClose.title = "Close";
        botHeader.innerHTML = "<div><img src='" + chatbot.dataset.cbBotAvatarImage + "'/> <h5>Bit_Bot <small>FTD Educação</small> </div></h5>";
        botHeader.appendChild(botClose);

        botClose.addEventListener('click', function (e) {
            e.preventDefault();
            initLaunchPad.style.display = "";
            botContainer.style.display = "none";
            return false;
        });

        botContainer.appendChild(botHeader);

        var botBody = document.createElement('div');
        botBody.id = "botBody";
        botContainer.appendChild(botBody);

        var poweredBy = document.createElement('div');
        poweredBy.innerHTML = "<small>Powered by <img src='http://ainetw.com/img/icon.png' width=12 /> AI Networks</small>";

        chatbot.appendChild(botContainer);
        chatbot.appendChild(poweredBy);
    </script>

</body>
</html>

bot 的代码 sn-p 在我的 bot 中发送数据收集:

 public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            var studentProfile = await _studentProfileAccessor.GetAsync(turnContext, () => new StudentProfile(), cancellationToken);
            DialogContext dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

            //Bot Channel Message Exchange Collection 
            if (turnContext.Activity.Name == "userName")
            {   
                studentProfile.Name = turnContext.Activity.Value.ToString();                   
                studentName = turnContext.Activity.Value.ToString();
            }
            if (turnContext.Activity.Name == "userGenre")
            {
                studentProfile.Gender = turnContext.Activity.Value.ToString();
                conversationSessionID = turnContext.Activity.From.Id;
                if (conversationSessionID.ToLower() == "user")
                {
                    var myConversationSessionID = turnContext.Activity.Id;
                    if (myConversationSessionID.IndexOf("|") != -1)
                    {
                        conversationSessionID = myConversationSessionID.Substring(0, myConversationSessionID.IndexOf("|"));
                    }
                }
                studentGender = turnContext.Activity.Value.ToString();
        //Variables persistance on DB
                SessionVariable SessionVariable = new SessionVariable();
                SessionVariable.AddSessionVariable(BellaMain.GlobalVariable.SystemID, BellaMain.GlobalVariable.CustomerID, conversationSessionID, "StudentName", studentName, "StudentGender", studentGender, "", "", "", "", "", "", "", "", "", "", "", 0);
            }
            if (turnContext.Activity.Name == "activityName")
            {
                if (turnContext.Activity.Value.ToString().ToLower() =="atividade2")
                {
                    var message = $"**Olá {studentName}, bem vindo ao Quant Bot!**";
                    await turnContext.SendActivityAsync(message);
                    await dc.BeginDialogAsync(Activity2MainDialog, "activity2MainDialog", cancellationToken);
                }
                else
                {
                    var message = $"**Olá {studentName}, bem vindo ao Quant Bot!**";
                    await turnContext.SendActivityAsync(message);                    
                }
            }

该应用程序运行良好,但是当有多个用户连接到它时,交换的数据会多次不匹配,例如
Webclient 1 发送用户名:Paul 和性别:男 ==> 应用接收 Paul 和男
Webclient 2 发送用户名:Mary 和性别:女性 ==> 应用程序有时会收到 Paul 和男性!?它应该改为接收玛丽和女性
我感觉发送的数据在 Azure 或其他地方缓冲,每次新的 Web 应用程序机器人实例启动时都需要清除/刷新。
是否有意义?如何修复?谢谢

【问题讨论】:

  • 能否分享您用于嵌入 WebChat 的所有代码?尤其是看看你是否设置了userID
  • 谢谢。刚刚用网络频道的整个机器人实例化代码更新了问题陈述。
  • 接受/投票支持更大的 Stack Overflow 社区和任何有类似问题的人。如果您觉得我的回答足够,请“接受”并点赞。如果没有,请告诉我我还能提供哪些帮助!

标签: botframework


【解决方案1】:

首先,如果您确实这样做,请不要在您的客户端中通过您的 Direct Line 授权。这是一个主要的安全问题,您很容易被破坏。

至于您的问题,请考虑生成唯一的 userID 并将其传递给 createDirectLine() 令牌调用。这样,用户 ID 将被烘焙到令牌中,并且不会专门成为页面的功能。由于令牌应该对每个用户都是唯一的,这应该有助于(如果不能解决)您的用户交叉问题。

如果没有,我建议从您的网络聊天代码中删除 Direct Line 直接 API 调用。就我而言,我有自己的令牌生成服务器,我从网络聊天中调用它。当 Web Chat 调用我的服务器的 API 时,令牌服务器会调用 Direct Line。我还在令牌服务器中生成用户 ID,以便将其烘焙到令牌中,然后返回到网络聊天以供使用。

如果这些选项都不能解决您的问题,那么我会仔细研究您在其他地方提到的外部数据收集。

希望有帮助!

【讨论】:

  • 谢谢!我尝试了两种方法来随机化 Webchat 调用中的UserID. 1- Remove the UserID`,这会生成随机用户 ID 密钥; 2- 生成一个随机的UserID 变量,传递给 WebChat.createDirectLine 调用。两者都未能隔离用户会话。正如我在浏览器开发工具上看到的那样,鉴于随机用户 ID 已确定生成,似乎网络聊天无法正常工作。即使只有一个用户连接到网络聊天,用户也需要点击刷新按钮 2-3 次将变量注入机器人应用程序中。
  • 如果您想查看实际问题,请尝试以下链接。根据需要更改 userName 参数。它应该在第一次和第二次对话开始时运行良好(您应该在聊天窗口中看到提供的名称)。但是,即使从不同的设备访问,它也会在此之后开始混合数据。 bellamspt.azurewebsites.net/forms/Bit_Bot/Staging/…
  • 我只是想知道您是否有一个示例代码 sn-p 来分享您如何从您的网络聊天代码中删除 Direct Line 直接 API 调用。谢谢!
【解决方案2】:

在您的示例中,您将“用户”分配给userID,这是一个静态字符串。

不建议将 userID 分配为静态值,因为这会导致所有用户共享状态。请参阅 API userID entry 了解更多信息。 (source)

从您的 sn-p 中删除用户 ID 部分或将“用户”更改为动态内容。否则状态将被共享,这意味着用户数据将在所有访问机器人的用户之间共享。

userID: "User"

【讨论】:

  • 谢谢!userID 参数已从 web bot 实例化页面中删除,因此现在随机生成用户 ID。但是,它仍然无法正常工作。当新用户实例化机器人时,他会看到其他人的数据。他/她刷新页面的那一刻,他/她就会看到自己的数据。想法?
  • 我还尝试使用户 ID 与 userID: token 等 Direct Line 令牌相同,但问题仍然存在。我想知道我的机器人代码中的外部数据收集可能不好。 if (turnContext.Activity.Name == "userName") { studentProfile.Name = turnContext.Activity.Value.ToString(); studentName = turnContext.Activity.Value.ToString()}
  • 如果您想查看实际问题,请尝试以下链接。根据需要更改userName 参数。它应该在第一次和第二次对话开始时运行良好(您应该在聊天窗口中看到提供的名称)。但是,即使从不同的设备访问,它也会在此之后开始混合数据。 https://bellamspt.azurewebsites.net/forms/Bit_Bot/Staging/activities.html?userName=Mick&amp;userGenre=Male&amp;activity=atividade2#loaded
【解决方案3】:

感谢大家对此的支持。 分享我们如何找到案例的解决方案。 首先,我们删除了 userID: "User" 条目。 所以每个机器人会话都会有自己的随机 ID。 然后我们只创建了一个“网站到机器人”数据交换变量。 这将确保所有数据将在一个浏览器周期内发送。 这似乎是导致我们应用程序出现问题的原因。 代码sn-p如下:
var enviromentContextData = 'studentName=&' + userName + '&studentGender=|' + userGenre + '|'; //Bot Message Exchange Setting const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => { if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') { dispatch({ type: 'WEB_CHAT/SEND_EVENT', payload: { name: 'enviromentContextDataPass', value: enviromentContextData } });
} return next(action); });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多