首页 > 解决方案 > Botframework V4 上的网络聊天价值交换问题

问题描述

我在 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>

机器人的代码片段在我的机器人中发送了数据收集:

 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 和 Gender:男性 ==> 应用程序接收 Paul 和男性
Webclient 2 发送用户名:Mary 和 Gender : 女性 ==> 应用有时会收到保罗和男性!?它应该接收 Mary 和 female,而不是
我感觉发送的数据在 Azure 或其他地方缓冲,每次新的 Web 应用程序 bot 实例启动时都需要清除/刷新。
是否有意义?如何修复?谢谢

标签: botframework

解决方案


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

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

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

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

希望有帮助!


推荐阅读