当我第二次尝试相同的输入时,LUIS 无法识别意图

LUIS is not recognizing the intent when I try the same input second time

我第一次在同一代码中将 LUIS 用于 Azure 搜索和 QnA 识别器。

我正在使用 intent.match 来匹配识别器。

我的问题是:

第一次,如果我问一个符合 QnA 意图的问题,它 returns 来自 QnA 库的答案。

后面是与 azuresearch 意图匹配的问题。 Azure 搜索也提供结果。

但是如果我重复必须与 QnA 匹配的问题,它会说 "no intent handler found for null"

var util = require('util');
var _ = require('lodash');
var builder = require('botbuilder');
var restify = require('restify');
var cognitiveservices = require('botbuilder-cognitiveservices');
/// <reference path="../SearchDialogLibrary/index.d.ts" />
var SearchLibrary = require('../SearchDialogLibrary');
var AzureSearch = require('../SearchProviders/azure-search');

var qintent;
// 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 bot and listen for messages
var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD

});
server.post('/api/messages', connector.listen());
// Bot Storage: Here we register the state storage for your bot. 
// Default store: volatile in-memory store - Only for prototyping!
// We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
// For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
var inMemoryStorage = new builder.MemoryBotStorage();

var qnarecognizer = new cognitiveservices.QnAMakerRecognizer({
    knowledgeBaseId: '6b30ac2a-5ce9-4576-a1cb-c89abfb73889',
    authKey: 'd457c897-71cf-46bf-a3d9-9a1f51246fad',
    endpointHostName: 'https://qnadispatchwg.azurewebsites.net/qnamaker'
    });

const LuisModelUrl = 'https://westeurope.api.cognitive.microsoft.com/luis/v2.0/apps/180a9aaa-9d67-4d40-b3d3-121917f4dbb8?subscription-key=39155bb750dc4b2abd84d410d80fce21&timezoneOffset=0&q=';
var recognizer = new builder.LuisRecognizer(LuisModelUrl);
// Bot with main dialog that triggers search and display its results
var bot  = new builder.UniversalBot(connector);
bot.set('storage', inMemoryStorage);

var intents = new builder.IntentDialog({ recognizers: [recognizer, qnarecognizer] });
bot.dialog('/', intents);

intents.matches('Greeting',  (session) => {
    session.send('You reached the Greeting intent. You said \'%s\'.', session.message.text);
    session.endDialog();
});

intents.matches('qna', [
    function (session, args) {
        console.log("my args in qna:=========================================================================================== %o", args);
        var answerEntity = builder.EntityRecognizer.findEntity(args.entities, 'answer');
        session.send(answerEntity.entity);
    }
]);

intents.matches('Search.Aco', [
    function (session, args, next) {
        console.log("my args in SearchDialog:=========================================================================================== %o", args);
        var intent = args.intent;
        console.log("our intent is " + intent);
        var entities = builder.EntityRecognizer.findEntity(args.entities, 'businessterm');
        console.log("recognnized entitiy is: "+ entities.entity);
       // qintent = title;
        //session.send('You reached the Search.Aco intent. You enquire for the entitiy \'%s\'.', qintent);
        //console.log(" SearchDialog: before updating the  session.message.text------------->" + session.message.text);
        session.message.text= entities.entity;
        //console.log(" SearchDialog: after updating the  session.message.text------------->" + session.message.text);
        SearchLibrary.begin(session);
    },

    function (session, args, results) {
        // Process selected search results
        session.send(
            'Done! For future reference, you selected these properties: %s',
            args.selection.map(function (i) { return i.key; }).join(', '));
    }
]);

var azureSearchClient = AzureSearch.create('aco-intel2', '4105C6676D0CDD9B2E7891952B9E9E00', 'azureblob-index');
var jobsResultsMapper = SearchLibrary.defaultResultsMapper(jobToSearchHit);

// Register Search Dialogs Library with bot
bot.library(SearchLibrary.create({
    multipleSelection: true,
    search: function (query) { return azureSearchClient.search(query).then(jobsResultsMapper); },
    refiners: ['people', 'content', 'location']
}));

// Maps the AzureSearch Job Document into a SearchHit that the Search Library can use
function jobToSearchHit(acosearch) {
    console.log("inside jobToSearchHit");
    console.log("inside acosearch.DocUrl" + acosearch.DocUrl + "-------" + acosearch.metadata_storage_name);
    return {
        key: acosearch.id,
        title: acosearch.metadata_storage_name,
        description: acosearch.content.substring(0, 100)+"...",
        documenturl:acosearch.DocUrl,
        imageUrl: acosearch.imageurl
    };
}

module.exports = { qintent:  "qintent"};

第二次,如果我正在混合 这是它的显示方式:

Emulator output

你能帮我理解 intent.match 和对话匹配之间的区别吗?我也尝试了以下方式,但它无法识别应答实体。如何从以下代码调用 QnA?

var util = require('util');
var _ = require('lodash');
var builder = require('botbuilder');
var restify = require('restify');
var cognitiveservices = require('botbuilder-cognitiveservices');
/// <reference path="../SearchDialogLibrary/index.d.ts" />
var SearchLibrary = require('../SearchDialogLibrary');
var AzureSearch = require('../SearchProviders/azure-search');

var qintent;
// 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 bot and listen for messages
var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD

});
server.post('/api/messages', connector.listen());
// Bot Storage: Here we register the state storage for your bot. 
// Default store: volatile in-memory store - Only for prototyping!
// We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
// For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
var inMemoryStorage = new builder.MemoryBotStorage();

var qnarecognizer = new cognitiveservices.QnAMakerRecognizer({
    knowledgeBaseId: '6b30ac2a-5ce9-4576-a1cb-c89abfb73889',
    authKey: 'd457c897-71cf-46bf-a3d9-9a1f51246fad',
    endpointHostName: 'https://qnadispatchwg.azurewebsites.net/qnamaker'
    });

const LuisModelUrl = 'https://westeurope.api.cognitive.microsoft.com/luis/v2.0/apps/180a9aaa-9d67-4d40-b3d3-121917f4dbb8?subscription-key=39155bb750dc4b2abd84d410d80fce21&timezoneOffset=0&q=';
var recognizer = new builder.LuisRecognizer(LuisModelUrl);
// Bot with main dialog that triggers search and display its results
var bot = new builder.UniversalBot(connector, function (session, args) {
    session.send('You reached the default message handler. You said \'%s\'.', session.message.text);
}).set('storage', inMemoryStorage);

bot.recognizer(recognizer, qnarecognizer);

bot.dialog('GreetingDialog',
    (session) => {
        session.send('You reached the Greeting intent. You said \'%s\'.', session.message.text);
        session.endDialog();
    }
).triggerAction({
    matches: 'Greeting'
})

bot.dialog('HelpDialog',
    (session) => {
        session.send('You reached the Help intent. You said \'%s\'.', session.message.text);
        session.endDialog();
    }
).triggerAction({
    matches: 'Help'
})

bot.dialog('CancelDialog',
    (session) => {
        session.send('You reached the Cancel intent. You said \'%s\'.', session.message.text);
        session.endDialog();
    }
).triggerAction({
    matches: 'Cancel'
})

bot.dialog('QnADialog',[
    function (session, args, next) {
        var answerEntity = builder.EntityRecognizer.findEntity(args.entities, 'answer');
        console.log(answerEntity);
        session.send(answerEntity.entity);
    }
]).triggerAction({
    matches: 'Search.QnA'
})

bot.dialog('SearchDialog', [
    function (session, args) {
        console.log("my args in SearchDialog:=========================================================================================== %o", args);
        var intent = args.intent;
        title = builder.EntityRecognizer.findEntity(intent.entities, 'businessterm');
        console.log(title.entity);
        qintent = title.entity;
        //session.send('You reached the Search.Aco intent. You enquire for the entitiy \'%s\'.', qintent);
        //console.log(" SearchDialog: before updating the  session.message.text------------->" + session.message.text);
        session.message.text= qintent;
        //console.log(" SearchDialog: after updating the  session.message.text------------->" + session.message.text);
        SearchLibrary.begin(session);
    },

    function (session, args, results) {
        // Process selected search results
        session.send(
            'Done! For future reference, you selected these properties: %s',
            args.selection.map(function (i) { return i.key; }).join(', '));
    }
]).triggerAction({
    matches: 'Search.Aco'
});

var azureSearchClient = AzureSearch.create('aco-intel2', '4105C6676D0CDD9B2E7891952B9E9E00', 'azureblob-index');
var jobsResultsMapper = SearchLibrary.defaultResultsMapper(jobToSearchHit);

// Register Search Dialogs Library with bot
bot.library(SearchLibrary.create({
    multipleSelection: true,
    search: function (query) { return azureSearchClient.search(query).then(jobsResultsMapper); },
    refiners: ['people', 'content', 'location']
}));

// Maps the AzureSearch Job Document into a SearchHit that the Search Library can use
function jobToSearchHit(acosearch) {
    console.log("inside jobToSearchHit");
    console.log("inside acosearch.DocUrl" + acosearch.DocUrl + "-------" + acosearch.metadata_storage_name);
    return {
        key: acosearch.id,
        title: acosearch.metadata_storage_name,
        description: acosearch.content.substring(0, 100)+"...",
        documenturl:acosearch.DocUrl,
        imageUrl: acosearch.imageurl
    };
}

module.exports = { qintent:  "qintent"};

这段代码给我的痕迹如下: logs

请帮助我理解上面的代码有什么问题。会有很大的帮助。 此外,intent.match 和对话框匹配之间的差异。根据我的理解,bot 识别 session.message 并将其与 'match:' 参数匹配并调用对话框。所以它可以在对话框之间来回跳转。

在第一种情况下,我觉得很奇怪,因为第二次没有这样做。

提前致谢, 维维克

使用 IntentDialog class(例如 var intents = new builder.IntentDialog( ...)不允许以直接向机器人注册对话的方式进行意图中断。

给定以下示例对话框:

const bot = new UniversalBot(connector); // Assume an already created ChatConnector
bot.recognizer(new LuisRecognizer(LuisModelUrl); // LUIS model with HowAreYou and Weather intents.

bot.dialog('HowAreYou',[
  function (session, args, next) {
    builder.Prompts.text(session, `I\'m doing great! How are you?`);
  },
  function (session, args) {
    var result = session.message.text;
    session.send(`I\'m glad to hear you\'re doing ${result}!`);
]).triggerAction({
  matches: 'HowAreYou'
});

bot.dialog('Weather', [
  function (session, args) {
    builder.Prompts.text(session `Which city do you want to find the weather forecast for?`);
  },
  function (session, args) {
    // some logic to handle the response and call a weather api
  }
  ]).triggerAction({
    matches: 'Weather'
  });

当用户询问 "How are you?" 时,LUIS 会检测到 'HowAreYou' 意图,并且机器人会开始相应的对话。然后机器人会提示用户 "I'm doing great! How are you?'。如果用户随后对机器人说 "Show me the weather",该机器人将收到该消息并检测 "Weather" 意图。这样做之后,它将 "Weather" 对话框添加到对话框堆栈的顶部并开始天气对话框。

UniversalBot 不会阻止您在检测到新意图时切换对话框。在意图对话框的 code 中,它会继续您已经在的任何对话框,并且不支持切换到新的 intent/dialog。