当我第二次尝试相同的输入时,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。
我第一次在同一代码中将 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。