如何使用 JavaScript 从 UI 向直线聊天机器人发送消息

how to send a message to direct line chat bot from the UI using JavaScript

我正在开发一个聊天机器人(使用 MS Azure 机器人框架和 QnAmaker 的 v4),

我在其中添加了一个功能,即当用户开始输入问题时,机器人会得到提示并从 QnAmaker 中显示相关问题,用户可以 select 其中一个,然后该特定问题将发送给机器人。

以下是我正在使用的完整代码,

<html>
<body>
    <div id="webchat" role="main"></div>
    <script>
        (async function () {

            const styleOptions = {
                hideUploadButton: true,
                bubbleBackground: '#D8F4FF',
                bubbleFromUserBackground: '#E8E8E8',
                botAvatarImage: '../botavatar.PNG',
                botAvatarInitials: 'bot',
                userAvatarInitials: initial,
                userAvatarImage: userimg,
                rootHeight: '100%',
                rootWidth: '50%'

            };

            const styleSet = window.WebChat.createStyleSet({
                bubbleBackground: 'rgba(0, 0, 255, .1)',
                bubbleFromUserBackground: 'rgba(0, 255, 0, .1)'
            });

            styleSet.textContent = {
                fontFamily: "'Comic Sans MS', 'Arial', sans-serif",
                fontWeight: 'bold'
            };
            const secret = secret;
            const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate',
                {
                    headers: {
                        Authorization: `Bearer ${secret}`,
                    },
                    method: 'POST'
                });
            const { token } = await res.json();

            const store = window.WebChat.createStore(
                {},
                ({ dispatch }) => next => action => {
                    if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
                        dispatch({
                            type: 'WEB_CHAT/SEND_EVENT',
                            payload: {
                                name: 'webchat/join',
                            }
                        });
                    }
                    return next(action);
                }
            );

            window.WebChat.renderWebChat({
                directLine: window.WebChat.createDirectLine({ token }),
                store,
                styleOptions,
                userID: emailid,
                username: fullname,
                locale: 'en-US',
                userAvatarInitials: initial
            }, document.getElementById('webchat'));
            document.querySelector('#webchat > *').focus();
            document.querySelectorAll('[aria-label="Sendbox"]')[0].placeholder = "Type your question and press enter";

            $("[aria-label='Sendbox']").keypress(function () {

                if ($("[aria-label='Sendbox']")[0].defaultValue.length > 4) {

                    getquestion(this.value);
                } else {
                    $('#ques').remove();
                }

            });
            $('div.probing').click(function () { alert(this.innerText); });

            $('div.probing').click(function () {
                document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
                document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
                $('.css-115fwte').trigger('click');
                $('#ques').remove();
            });

        })().catch(err => console.error(err));


        function getquestion(value) {
            var token = secret;
            var questionquery =
            {
                question: value,
                top: 2,
                scoreThreshold: 50,
                "strictFilters": [
                    {
                        "name": "message",
                        "value": "text"
                    }],
            }
            $.ajax({
                type: "POST",
                url: "https://endpoint/qnamaker/knowledgebases/KBID/generateAnswer",

                data: JSON.stringify(questionquery),
                beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', secret);
                },
                dataType: "json",
                contentType: "application/json",
                success: function (data) {    
                    var questions = "";
                    $('#ques').remove();

                    for (var i = 0; i < 4; i++) {
                        if (data.answers[0].questions[i] != null && data.answers[0].questions[i] != 'undefined')
                            questions = questions + "<div class='probing'>" + data.answers[0].questions[i] + "</div>";
                    }
                    $('.content').last().append("<div id='ques'>" + questions + "</div>");
                    $('div.probing').click(function () {
                        document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
                        document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
                        $('.css-115fwte').trigger('click');
                        $('#ques').remove();
                    });
                },
                error: function (data) {
                    alert(data.responseText);
                }
            });
        }

    </script>
</body>
</html>

请检查我的机器人的下图以及提示的问题,它看起来像这样,这些问题附加到机器人给出的最后回复,在select提出问题后,div 将被删除。在下一个问题上,这个循环将再次继续。

我面临的问题在这里,使用以下代码在输入框中输入值,但是机器人没有收到任何问题,因此它失败了回答。

$('div.probing').click(function () {
                        document.querySelectorAll('[aria-label="Sendbox"]')[0].value = (this.innerText);
                        document.querySelectorAll('[aria-label="Sendbox"]')[0].defaultValue = (this.innerText);
                        $('.css-115fwte').trigger('click');
                        $('#ques').remove();
                    });

使用此代码在输入框中输入值,但是机器人没有收到任何问题,因此无法回答。

这是通过脚本添加问题后在控制台中的显示方式。 请注意,我在我的代码中使用了所有必需的参考 JS 和 CSS 文件。 所以请用正确的方法帮助我实现我的要求,在此先感谢。

这是一个可以帮助您入门的工作演示,使用来自 the sample:

的类似方法
<!DOCTYPE html>
<html lang="en-US">

<head>
    <title>Web Chat: Programmatic access to post activity</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!--
      This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to pointing to Web Chat's MyGet feed:
      https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
    -->
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <style>
        html,
        body {
            height: 100%;
        }

        body {
            margin: 0;
        }

        #webchat {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>
    <div id="webchat" role="main"></div>
    <script>
        (async function () {
            // In this demo, we are using Direct Line token from MockBot.
            // Your client code must provide either a secret or a token to talk to your bot.
            // Tokens are more secure. To learn about the differences between secrets and tokens
            // and to understand the risks associated with using secrets, visit https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication?view=azure-bot-service-4.0

            // We are creating the Web Chat store here so we can dispatch WEB_CHAT/SEND_MESSAGE action later.
            const store = window.WebChat.createStore();

            window.WebChat.renderWebChat(
                {
                    directLine: window.WebChat.createDirectLine({ token: '<your token>' }),
                    // We are passing our own version of Web Chat store.
                    store
                },
                document.getElementById('webchat')
            );

            document.querySelector('#webchat > *').focus();

// THIS IS THE IMPORTANT STUFF

            const sendbox = document.querySelector("[aria-label='Sendbox']");

            function removeQuestions() {
                const questionDivs = document.querySelectorAll('.questions');
                    questionDivs.forEach((div) => {
                        div.remove();
                    })
            }

            // This ensures that we create unique listeners for each question
            let totalQuestions = 0;

            // Track the keypress events in the Send Box
            sendbox.addEventListener('keypress', () => {
                if (sendbox.defaultValue.length > 4) {
                    getQuestion();
                } else {
                    removeQuestions();
                }
            });

            // Send a message containing the innerText of the target element
            function send(event) {
                store.dispatch({
                    type: 'WEB_CHAT/SEND_MESSAGE',
                    payload: { text: event.currentTarget.innerText }
                });
                event.currentTarget.remove();
            }

            // This generates some test questions
            function getQuestion() {
                // Create questions div
                const questions = document.createElement('DIV');
                questions.setAttribute('class', 'questions');
                document.querySelector('.content').appendChild(questions);

                // Generate test questions
                for (var i = 0; i < 4; i++) {
                    // Create question div
                    const question = document.createElement('DIV');
                    question.setAttribute('id', `question${totalQuestions}`);
                    question.setAttribute('class', 'probing');
                    question.innerText = `this is a test ${totalQuestions}`;
                    questions.appendChild(question);

                    // Create listener for question
                    const element = document.querySelector(`#question${totalQuestions}`);
                    element.addEventListener('click', send, false);
                    totalQuestions++;
                }
            }
        })().catch(err => console.error(err));
    </script>
</body>

</html>

可能有更优雅的方法来做到这一点,但我想尽快给您答复。

注意:我使用 vanilla javascript 而不是 jQuery 来减少页面加载时间,因为我更熟悉它。