【问题标题】:Intergrating Bing Web Search API with QnA chat bot将 Bing Web 搜索 API 与 QnA 聊天机器人集成
【发布时间】:2018-11-24 18:31:27
【问题描述】:

我正在使用 QnA 模板 (Microsoft Azure) 制作聊天机器人。基本上,用户提出问题,机器人将尝试在常见问题解答文档中找到答案。如果失败,我希望它使用用户的查询运行 Bing 搜索并以最准确的答案回复。我发现了这个使用 Bing Web Search API 的示例:https://docs.microsoft.com/en-us/azure/cognitive-services/bing-web-search/quickstarts/nodejs。现在,我只想让机器人回复搜索的第一个链接。 但是,我不知道如何将链接中的代码与生成的 QnA Bot 代码(在 Node.js 中)合并:

var restify = require('restify');
var builder = require('botbuilder');
var botbuilder_azure = require("botbuilder-azure");
var builder_cognitiveservices = require("botbuilder-cognitiveservices");
var request = require('request');

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
    console.log('%s listening to %s', server.name, server.url); 
});

// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword,
    openIdMetadata: process.env.BotOpenIdMetadata 
});

// Listen for messages from users 
server.post('/api/messages', connector.listen());

var tableName = 'botdata';
var azureTableClient = new botbuilder_azure.AzureTableClient(tableName, process.env['AzureWebJobsStorage']);
var tableStorage = new botbuilder_azure.AzureBotStorage({ gzipData: false }, azureTableClient);

// Create your bot with a function to receive messages from the user
var bot = new builder.UniversalBot(connector);
bot.set('storage', tableStorage);

// Recognizer and and Dialog for GA QnAMaker service
var recognizer = new builder_cognitiveservices.QnAMakerRecognizer({
    knowledgeBaseId: process.env.QnAKnowledgebaseId,
    authKey: process.env.QnAAuthKey || process.env.QnASubscriptionKey, // Backward compatibility with QnAMaker (Preview)
    endpointHostName: process.env.QnAEndpointHostName
});

var basicQnAMakerDialog = new builder_cognitiveservices.QnAMakerDialog({
    recognizers: [recognizer],
    defaultMessage: 'Sorry, I cannot find anything on that topic',
    qnaThreshold: 0.3
});

// Override the invokeAnswer function from QnAMakerDialog 
builder_cognitiveservices.QnAMakerDialog.prototype.invokeAnswer = function (session, recognizeResult, threshold, noMatchMessage) {
    var qnaMakerResult = recognizeResult;
    session.privateConversationData.qnaFeedbackUserQuestion = session.message.text;
    if (qnaMakerResult.score >= threshold && qnaMakerResult.answers.length > 0) {
        if (this.isConfidentAnswer(qnaMakerResult) || this.qnaMakerTools == null) {
            this.respondFromQnAMakerResult(session, qnaMakerResult);
            this.defaultWaitNextMessage(session, qnaMakerResult);
        }
        else {
            this.qnaFeedbackStep(session, qnaMakerResult);
        }
    }
    else {
        this.noMatch(session, noMatchMessage, qnaMakerResult);
    }
};

// API call to Bing
basicQnAMakerDialog.noMatch = function (session, noMatchMessage, qnaMakerResult) {
    var term = session.message.text;
    var key = 'i hid it';

    var options = {
            url: "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + term,
            method: 'GET',
            headers : {
        'Ocp-Apim-Subscription-Key' : key
    }
    }; 

    request(options, function(err,res, body){
        if(err){
            console.error(err);
            session.send(noMatchMessage);
        }
        body = JSON.parse(body);
        session.send("I found a thing: " + body["webPages"]["value"][0]["name"]);
    });
};

bot.dialog('basicQnAMakerDialog', basicQnAMakerDialog);

bot.dialog('/', //basicQnAMakerDialog);
        [ 
         function (session, results) {
             session.replaceDialog('basicQnAMakerDialog');
         },

         ]);

在bot.dialog里面的函数中,我想我应该添加一个条件,比如:如果bot返回默认消息,打开一个网页,让要搜索的“term”成为用户的最后一条消息。但是,我不知道如何准确编码,以及在哪里编码。另外,我不知道如何退出 replaceDialog 函数,以便回复默认消息或常见问题解答中的答案以外的其他内容。

PS:总的来说,我对 javascript 或 Web 开发没有太多经验。任何帮助将不胜感激:)

【问题讨论】:

    标签: node.js azure botframework


    【解决方案1】:

    您正在实现的内容涉及两个步骤,将“noMatch”案例提取到一个方法中以便您可以做出完整的响应消息,然后是 API 调用本身。

    “noMatch”方法。

    首先,您需要覆盖 QnAMakerDialog 中的 invokeAnswer 函数(此覆盖不会改变任何内容,只是为 noMatch 情况添加对单独方法的调用。)

    builder_cognitiveservices.QnAMakerDialog.prototype.invokeAnswer = function (session, recognizeResult, threshold, noMatchMessage) {
            var qnaMakerResult = recognizeResult;
            session.privateConversationData.qnaFeedbackUserQuestion = session.message.text;
            if (qnaMakerResult.score >= threshold && qnaMakerResult.answers.length > 0) {
                if (this.isConfidentAnswer(qnaMakerResult) || this.qnaMakerTools == null) {
                    this.respondFromQnAMakerResult(session, qnaMakerResult);
                    this.defaultWaitNextMessage(session, qnaMakerResult);
                }
                else {
                    this.qnaFeedbackStep(session, qnaMakerResult);
                }
            }
            else {
                    this.noMatch(session, noMatchMessage, qnaMakerResult);
            }
        };
    

    在此之后,您将像往常一样定义您的 basicQnAMakerDialog,但请考虑将默认消息字段设置为错误情况或“未找到结果”。 (这并不重要,因为您可以任意决定在 noMatch 方法中返回什么,但最好有默认值)

    var basicQnAMakerDialog = new builder_cognitiveservices.QnAMakerDialog({
        recognizers: [recognizer],
        defaultMessage: 'Sorry, I can't find anything on that topic'
        qnaThreshold: 0.3
    });
    

    在此之后,您可以单独定义 noMatch 方法。

    basicQnAMakerDialog.noMatch = function (session, noMatchMessage, qnaMakerResult) {
                session.send(noMatchMessage); //Contains the default message
                this.defaultWaitNextMessage(session, qnaMakerResult);
    }
    

    在这个方法中,我们可以调用 API 或做任何我们想做的事情。

    Credit to gliddell on this override

    API 调用。

    在 noMatch 方法中,我们将对 Bing 进行 API 调用

    basicQnAMakerDialog.noMatch = function (session, noMatchMessage, qnaMakerResult) {
        var term = session.message.text;
        var key = <Environment Var containing the Bing key>;
    
        var options = {
            url: "https://api.cognitive.microsoft.com/bing/v7.0/search?q=" + term,
            method: 'GET',
            headers : {
                'Ocp-Apim-Subscription-Key' : key
            }
        }; 
        request(options, function(err,res, body){
            if(err){
                console.error(err);
                session.send(noMatchMessage);
            }
            body = JSON.parse(body);
            session.send("I found a thing: " + body["webPages"]["value"][0]["name"]);
        });
    };
    

    在获得搜索结果后,您可以根据需要自定义要发回的消息。

    【讨论】:

    • 感谢您的周到回答!所以我更改了 basicQnAMakerDialog 的默认消息,复制了你的 invokeAnswer 和第二个 noMatch 函数(我添加了 http 模块并在请求函数之前添加了 'http.' ),并将 Bing 键放置在 key 变量中。我运行了代码,当我使用第二个 noMatch 函数(通过 API 调用 Bing)输入知识库中没有的内容时,机器人随后什么也没说。但是对于第一个 noMatch 函数,它会使用默认消息进行回答。我做错了什么?
    • 多一些代码会更容易确认,但是这个版本使用的是“request”模块,而不是http。
    • 好的,我忘记添加了。它现在可以工作了,非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 2022-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    相关资源
    最近更新 更多