beginDialogAction 不重新提示
beginDialogAction doesn't reprompt
我目前正在使用带有 node.js 的 Microsoft Bot Framework 来编写一个通过 API 遍历决策树的机器人。我想允许用户在对话框中的任何时候取消树,这样他就不必遍历整个(可能是巨大的)树来退出。因为如果会话关闭,我需要向 API 发送消息,所以我使用 Dialog.beginDialogAction()
来启动 "cancel"-Dialog,而不是 Dialog.cancelAction()
,这样我可以提示用户确认以及关闭会话。
现在我已经准备好了,取消树就可以了,但是如果用户选择对确认提示说 "no" 并且机器人实际上应该重新提示最后一个问题,它有时使用 "no" 自动回答上一个问题(或抛出错误)。这仅在问题的 valueType 为 "string" 且显示 Prompts.choice
对话框时出现,对于 Prompts.number
和 Prompts.time
会产生预期的行为。
我搜索了所有我能找到的文档,但没有关于某些不支持 DialogActions 或类似内容的提示的信息。我只使用 session.beginDialog
、session.endDialog
、session.endConversation
和 builder.Prompts
来控制对话框堆栈。
代码如下所示:
//This dialog gets the next question node of the tree passed in args[1].
bot.dialog('select', [
function(session, args, next) {
//Depending on the value type of the question, different prompts are used.
switch (args[1].valueType) {
case "string":
builder.Prompts.choice(session, args[1].text, args[1].answerValues, {
listStyle: builder.ListStyle.button,
maxRetries: 0
});
break;
case "number":
builder.Prompts.number(session, args[1].text, {
integerOnly: true,
maxValue: 100,
minValue: 0
})
break;
case "datetime":
builder.Prompts.time(session, message + "\nPlease enter a date in the format 'yyyy-mm-dd'.");
break;
}
},
function(session, results) {
//Use the answer to proceed the tree.
//...
//With the new question node start over.
session.beginDialog('select', [sessionId, questionNode]);
}
]).beginDialogAction('cancelSelect', 'cancel', {
matches: /^stop$/i
});
//This dialog is used for cancelling.
bot.dialog('cancel', [
function(session, next) {
builder.Prompts.confirm(session, 'Do you really want to quit?');
},
function(session, results) {
if (results.response) {
finishSession();
session.endConversation('Session was closed.')
} else {
//Here the bot should stop this cancel-Dialog and reprompt the previous question
session.endDialog();
}
}
])
但机器人并没有重新提示,而是跳转到 'select'-Dialog 中的 function (session, results)
,在那里它尝试解析答案 "no",但显然失败了。
这里是我的 app.js 的完整副本。如果不模拟我们产品的 esc-API,您将无法 运行 它,但它表明我只使用 session.beginDialog
、session.endDialog
、session.endConversation
和 builder.Prompts
。我所做的唯一更改是删除私人信息并将消息翻译成英文。
/*---------
-- Setup --
---------*/
//esc and esc_auth are product specific, so obviously i cant share them. They handle the API of our product.
const esc = require("./esc");
const esc_auth = require("./esc_auth");
var restify = require("restify");
var builder = require("botbuilder");
var server = restify.createServer();
server.listen(process.env.PORT || process.env.port || 3978, function() {
console.log(`${server.name} listening to ${server.url}`);
});
var connector = new builder.ChatConnector({
//Cant share these as well
appId: "",
appPassword: ""
});
server.post("/api/messages", connector.listen());
var esc_header;
var esc_session;
var esc_attribs = {};
var treeNames = [];
/*---------
-- Start --
---------*/
//This function is called when no other dialog is currently running.
//It gets the authorization token from the API, reads concepts from the input and searches for matching decision trees.
//If not concepts or trees were found, a text search on the API is cone.
var bot = new builder.UniversalBot(connector, [
function(session) {
var esc_token;
esc_attribs = {};
console.log("Getting token...");
esc.escAccessToken(esc_auth.esc_system, esc_auth.esc_apiUser)
.then(function(result) {
esc_token = result;
esc_header = {
"Content-Type": "application/json",
"Authorization": "Bearer " + esc_token
};
console.log("Got token.");
//Look for concepts in the message.
esc.escAnnotateQuery(esc_header, session.message.text)
.then(function(result) {
for(i in result.concepts) {
for(j in result.concepts[i]) {
esc_attribs[i] = j;
}
}
//If concepts were found, look for trees and solutions with them
if(Object.keys(esc_attribs).length > 0) {
esc.escSearchIndexWithConcepts(esc_header, esc_attribs)
.then(function(result) {
var treeIds = [];
treeNames = [];
result = result;
result.records.forEach(function(entry) {
//Check which tree the found tree is or found solution is in.
if(entry.DecisionTree && !treeIds.includes(entry.DecisionTree)) {
treeIds.push(entry.DecisionTree);
}
})
if(treeIds.length != 0) {
esc.escSearchTrees(esc_header)
.then(function(result) {
console.log("Trees found.");
result.records.forEach(function(tree) {
if(treeIds.includes(tree.DecisionTree)) {
treeNames.push({id:tree.DecisionTree, name: tree.Label})
console.log("Tree: ", tree.DecisionTree, tree.Label);
}
})
session.beginDialog("tree", treeNames);
})
} else {
console.log("No tree found for " + session.message.text);
treeNames = [];
session.beginDialog("textSearch");
return;
}
})
} else {
console.log("No concepts found.");
session.beginDialog("textSearch");
return;
}
})
})
},
function(session, results) {
session.endConversation("You may now start a new search.");
}
]);
//Searches for trees by text.
bot.dialog("textSearch", [
function(session) {
session.send("No concepts were found in your input.");
builder.Prompts.confirm(session, "Start a text search instead?", {"listStyle": builder.ListStyle.button});
},
function(session, results) {
if(results.response) {
builder.Prompts.text(session, "Please enter your new search prompt in keywords.")
} else {
session.endDialog("Ok, back to concept search.")
}
},
function(session) {
//Search gives better results without mutated vowels
esc.escSearchIndex(esc_header, undoMutation(session.message.text))
.then(function(result) {
var treeIds = [];
treeNames = [];
result.records.forEach(function(entry) {
//Check which tree the found document is in.
if(entry.DecisionTree && !treeIds.includes(entry.DecisionTree)) {
treeIds.push(entry.DecisionTree);
}
})
if(treeIds.length != 0) {
esc.escSearchTrees(esc_header)
.then(function(result) {
console.log("Trees found.");
result.records.forEach(function(tree) {
if(treeIds.includes(tree.DecisionTree)) {
treeNames.push({id:tree.DecisionTree, name: tree.Label})
console.log("Tree: ", tree.DecisionTree, tree.Label);
}
})
session.beginDialog("tree", treeNames);
})
} else {
console.log("No tree found for " + session.message.text);
treeNames = [];
session.endConversation("No trees were found for this search.");
}
})
}
])
//The cancel dialog.
bot.dialog("cancel", [
function(session) {
builder.Prompts.confirm(session, "Do you really want to cancel?", {"listStyle": builder.ListStyle.button});
},
function(session, results) {
if(results.response) {
if(esc_session) {
esc.escFinishSession(esc_header, esc_session.sessionId)
.then(function(result) {
esc_session = undefined;
session.endConversation("Session was cancelled.")
})
} else {
session.endConversation("Session was cancelled.")
}
} else {
session.endDialog();
}
}
])
/*-------------------------
-- Decision tree dialogs --
-------------------------*/
//This dialog presents the found decision trees and lets the user select one.
bot.dialog("tree", [
function(session, treeArray) {
var opts = [];
treeArray.forEach(function(t) {
opts.push(t.name);
});
builder.Prompts.choice(session, "Following trees were found:", opts, {listStyle: builder.ListStyle.button})
},
function(session, results) {
let answer = results.response.entity;
console.log("Tree selected:", answer);
let id;
treeNames.forEach(function(t) {
if(t.name === answer && !id) {
id = t.id;
}
})
console.log("Starting session...");
esc.escStartSession(esc_header, id, esc_attribs)
.then(function(result) {
esc_session = result;
for(i in esc_session.concepts) {
for(j in esc_session.concepts[i]) {
esc_attribs[i] = j;
}
}
console.log("Started session.");
session.beginDialog(esc_session.questions[0].nodeType,[esc_session.sessionId, esc_session.questions[0]]);
})
.catch(function(err) {
console.log("Error starting ESC session.");
console.log(err);
})
}
]).beginDialogAction("cancelTree", "cancel", {matches: /^cancel$|^end$|^stop$|^halt/i});
//This dialog is for selection answers on a question node. It also saves recognized concepts within the answer.
bot.dialog("select", [
function(session, args) {
console.log("Select");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.userData = args;
var opts = new Array();
switch(args[1].valueType) {
case "string":
for(var i = 0; i < args[1].answerValues.length; i++) {
opts[i] = args[1].answerValues[i].value;
}
builder.Prompts.choice(session, message, opts, {listStyle: builder.ListStyle.button, maxRetries: 0});
break;
case "number":
for(var i = 0; i < args[1].answerIntervals.length; i++) {
opts[i] = args[1].answerIntervals[i].value;
}
builder.Prompts.number(session, message, {integerOnly: true, maxValue: 100, minValue: 0});
break;
case "datetime":
for(var i = 0; i < args[1].answerIntervals.length; i++) {
opts[i] = args[1].answerIntervals[i].value;
}
builder.Prompts.time(session, message + "\nPlease enter a date in format 'yyyy-mm-dd'.");
break;
}
},
function(session, results) {
let args = session.userData;
let answer;
//An answer was given.
if(results.response != null && results.response.entity != null) {
answer = results.response.entity;
} else if (results.response != null) {
answer = results.response;
} else {
//No answer (to a choice prompt) was given, check if concepts were recognized and try again.
}
esc.escAnnotateQuery(esc_header, session.message.text)
.then(function(result) {
for(i in result.concepts) {
for(j in result.concepts[i]) {
esc_attribs[i] = j;
}
}
console.log("Proceeding tree with answer %s", answer);
esc.escProceedTree(esc_header, args[0], args[1].nodeId, args[1].treeId, answer, esc_attribs)
.then(function(result) {
if(result.questions[0].nodeType === "error") {
//If no concept answers the question, ask again.
session.send("No answer was given.")
session.beginDialog("select", [esc_session.sessionId, esc_session.questions[0]])
} else {
esc_session = result;
console.log("Initiating new Dialog %s", esc_session.questions[0].nodeType);
//the nodeType is either "select", "info" or "solution"
session.beginDialog(esc_session.questions[0].nodeType, [esc_session.sessionId, esc_session.questions[0]])
}
})
.catch(function(err) {
console.log("Error proceeding tree.");
console.log(err);
});
})
}
]).beginDialogAction("cancelSelect", "cancel", {matches: /^abbrechen$|^beenden$|^stop$|^halt/i});
//This dialog is for showing hint nodes. It then automatically proceeds the tree.
bot.dialog("info", [
function(session, args) {
console.log("Info");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.send(message);
console.log("Proceeding tree without answer.");
esc.escProceedTree(esc_header, args[0], args[1].nodeId, args[1].treeId, "OK", esc_attribs)
.then(function(result) {
esc_session = result;
console.log("Initiating new Dialog %s", esc_session.questions[0].nodeType);
session.beginDialog(esc_session.questions[0].nodeType, [esc_session.sessionId, esc_session.questions[0]]);
})
.catch(function(err) {
console.log("Error proceeding tree.");
console.log(err);
});
}
])
//This dialog displays the reached solution. It then ends the dialog, erasing the concepts of this session.
bot.dialog("solution", [
function(session, args) {
console.log("Solution");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.send(message);
esc.escFinishSession(esc_header, args[0])
.then(function(result) {
console.log("Finished Session " + args[0]);
esc_session = undefined;
})
.catch(function(err) {
console.log("Error finishing session.");
console.log(err);
})
console.log("Ending dialog.");
session.endDialog("I hope i could help you.");
}
])
/*-----------
-- Manners --
-----------*/
// Greetings
bot.on("conversationUpdate", function (message) {
if (message.membersAdded && message.membersAdded.length > 0) {
// Don"t greet yourself
if(message.membersAdded[0].id !== message.address.bot.id) {
// Say hello
var reply = new builder.Message()
.address(message.address)
.text("Welcome to the Chatbot. Please enter your search.");
bot.send(reply);
}
} else if (message.membersRemoved) {
// Say goodbye
var reply = new builder.Message()
.address(message.address)
.text("Goodbye.");
bot.send(reply);
}
});
/*---------------------
-- Utility functions --
---------------------*/
//function for attached images
var attach = function(p) {
if(typeof p != undefined && p != null) {
console.log("Found attachment: %s", p);
session.send({
attachments:[{
contentUrl: p,
contentType: "image/jpeg"
}]
})
}
}
var undoMutation = function(s) {
while(s.indexOf("ä") !== -1) {
s = s.replace("ä", "ae");
}
while(s.indexOf("ö") !== -1) {
s = s.replace("ö", "oe");
}
while(s.indexOf("ü") !== -1) {
s = s.replace("ü", "ue");
}
return s;
}
可能是嵌套字符串提示对话框的问题。目前我只找到一些解决方法来快速解决问题。
最快:扩大提示对话框的距离,如果Bot输入无效,会重新提示问题。
builder.Prompts.choice(session, args[1].text, args[1].answerValues, {
listStyle: builder.ListStyle.button,
maxRetries: 2
});
正如我所见,您会将 treeNote
传递给 select 对话框,因此您可以尝试使用 replaceDialog()
而不是 beginDialog()
来清除嵌套对话框堆栈。在 cancel
对话框中,也将 endDialog()
替换为 replaceDialog()
我目前正在使用带有 node.js 的 Microsoft Bot Framework 来编写一个通过 API 遍历决策树的机器人。我想允许用户在对话框中的任何时候取消树,这样他就不必遍历整个(可能是巨大的)树来退出。因为如果会话关闭,我需要向 API 发送消息,所以我使用 Dialog.beginDialogAction()
来启动 "cancel"-Dialog,而不是 Dialog.cancelAction()
,这样我可以提示用户确认以及关闭会话。
现在我已经准备好了,取消树就可以了,但是如果用户选择对确认提示说 "no" 并且机器人实际上应该重新提示最后一个问题,它有时使用 "no" 自动回答上一个问题(或抛出错误)。这仅在问题的 valueType 为 "string" 且显示 Prompts.choice
对话框时出现,对于 Prompts.number
和 Prompts.time
会产生预期的行为。
我搜索了所有我能找到的文档,但没有关于某些不支持 DialogActions 或类似内容的提示的信息。我只使用 session.beginDialog
、session.endDialog
、session.endConversation
和 builder.Prompts
来控制对话框堆栈。
代码如下所示:
//This dialog gets the next question node of the tree passed in args[1].
bot.dialog('select', [
function(session, args, next) {
//Depending on the value type of the question, different prompts are used.
switch (args[1].valueType) {
case "string":
builder.Prompts.choice(session, args[1].text, args[1].answerValues, {
listStyle: builder.ListStyle.button,
maxRetries: 0
});
break;
case "number":
builder.Prompts.number(session, args[1].text, {
integerOnly: true,
maxValue: 100,
minValue: 0
})
break;
case "datetime":
builder.Prompts.time(session, message + "\nPlease enter a date in the format 'yyyy-mm-dd'.");
break;
}
},
function(session, results) {
//Use the answer to proceed the tree.
//...
//With the new question node start over.
session.beginDialog('select', [sessionId, questionNode]);
}
]).beginDialogAction('cancelSelect', 'cancel', {
matches: /^stop$/i
});
//This dialog is used for cancelling.
bot.dialog('cancel', [
function(session, next) {
builder.Prompts.confirm(session, 'Do you really want to quit?');
},
function(session, results) {
if (results.response) {
finishSession();
session.endConversation('Session was closed.')
} else {
//Here the bot should stop this cancel-Dialog and reprompt the previous question
session.endDialog();
}
}
])
但机器人并没有重新提示,而是跳转到 'select'-Dialog 中的 function (session, results)
,在那里它尝试解析答案 "no",但显然失败了。
这里是我的 app.js 的完整副本。如果不模拟我们产品的 esc-API,您将无法 运行 它,但它表明我只使用 session.beginDialog
、session.endDialog
、session.endConversation
和 builder.Prompts
。我所做的唯一更改是删除私人信息并将消息翻译成英文。
/*---------
-- Setup --
---------*/
//esc and esc_auth are product specific, so obviously i cant share them. They handle the API of our product.
const esc = require("./esc");
const esc_auth = require("./esc_auth");
var restify = require("restify");
var builder = require("botbuilder");
var server = restify.createServer();
server.listen(process.env.PORT || process.env.port || 3978, function() {
console.log(`${server.name} listening to ${server.url}`);
});
var connector = new builder.ChatConnector({
//Cant share these as well
appId: "",
appPassword: ""
});
server.post("/api/messages", connector.listen());
var esc_header;
var esc_session;
var esc_attribs = {};
var treeNames = [];
/*---------
-- Start --
---------*/
//This function is called when no other dialog is currently running.
//It gets the authorization token from the API, reads concepts from the input and searches for matching decision trees.
//If not concepts or trees were found, a text search on the API is cone.
var bot = new builder.UniversalBot(connector, [
function(session) {
var esc_token;
esc_attribs = {};
console.log("Getting token...");
esc.escAccessToken(esc_auth.esc_system, esc_auth.esc_apiUser)
.then(function(result) {
esc_token = result;
esc_header = {
"Content-Type": "application/json",
"Authorization": "Bearer " + esc_token
};
console.log("Got token.");
//Look for concepts in the message.
esc.escAnnotateQuery(esc_header, session.message.text)
.then(function(result) {
for(i in result.concepts) {
for(j in result.concepts[i]) {
esc_attribs[i] = j;
}
}
//If concepts were found, look for trees and solutions with them
if(Object.keys(esc_attribs).length > 0) {
esc.escSearchIndexWithConcepts(esc_header, esc_attribs)
.then(function(result) {
var treeIds = [];
treeNames = [];
result = result;
result.records.forEach(function(entry) {
//Check which tree the found tree is or found solution is in.
if(entry.DecisionTree && !treeIds.includes(entry.DecisionTree)) {
treeIds.push(entry.DecisionTree);
}
})
if(treeIds.length != 0) {
esc.escSearchTrees(esc_header)
.then(function(result) {
console.log("Trees found.");
result.records.forEach(function(tree) {
if(treeIds.includes(tree.DecisionTree)) {
treeNames.push({id:tree.DecisionTree, name: tree.Label})
console.log("Tree: ", tree.DecisionTree, tree.Label);
}
})
session.beginDialog("tree", treeNames);
})
} else {
console.log("No tree found for " + session.message.text);
treeNames = [];
session.beginDialog("textSearch");
return;
}
})
} else {
console.log("No concepts found.");
session.beginDialog("textSearch");
return;
}
})
})
},
function(session, results) {
session.endConversation("You may now start a new search.");
}
]);
//Searches for trees by text.
bot.dialog("textSearch", [
function(session) {
session.send("No concepts were found in your input.");
builder.Prompts.confirm(session, "Start a text search instead?", {"listStyle": builder.ListStyle.button});
},
function(session, results) {
if(results.response) {
builder.Prompts.text(session, "Please enter your new search prompt in keywords.")
} else {
session.endDialog("Ok, back to concept search.")
}
},
function(session) {
//Search gives better results without mutated vowels
esc.escSearchIndex(esc_header, undoMutation(session.message.text))
.then(function(result) {
var treeIds = [];
treeNames = [];
result.records.forEach(function(entry) {
//Check which tree the found document is in.
if(entry.DecisionTree && !treeIds.includes(entry.DecisionTree)) {
treeIds.push(entry.DecisionTree);
}
})
if(treeIds.length != 0) {
esc.escSearchTrees(esc_header)
.then(function(result) {
console.log("Trees found.");
result.records.forEach(function(tree) {
if(treeIds.includes(tree.DecisionTree)) {
treeNames.push({id:tree.DecisionTree, name: tree.Label})
console.log("Tree: ", tree.DecisionTree, tree.Label);
}
})
session.beginDialog("tree", treeNames);
})
} else {
console.log("No tree found for " + session.message.text);
treeNames = [];
session.endConversation("No trees were found for this search.");
}
})
}
])
//The cancel dialog.
bot.dialog("cancel", [
function(session) {
builder.Prompts.confirm(session, "Do you really want to cancel?", {"listStyle": builder.ListStyle.button});
},
function(session, results) {
if(results.response) {
if(esc_session) {
esc.escFinishSession(esc_header, esc_session.sessionId)
.then(function(result) {
esc_session = undefined;
session.endConversation("Session was cancelled.")
})
} else {
session.endConversation("Session was cancelled.")
}
} else {
session.endDialog();
}
}
])
/*-------------------------
-- Decision tree dialogs --
-------------------------*/
//This dialog presents the found decision trees and lets the user select one.
bot.dialog("tree", [
function(session, treeArray) {
var opts = [];
treeArray.forEach(function(t) {
opts.push(t.name);
});
builder.Prompts.choice(session, "Following trees were found:", opts, {listStyle: builder.ListStyle.button})
},
function(session, results) {
let answer = results.response.entity;
console.log("Tree selected:", answer);
let id;
treeNames.forEach(function(t) {
if(t.name === answer && !id) {
id = t.id;
}
})
console.log("Starting session...");
esc.escStartSession(esc_header, id, esc_attribs)
.then(function(result) {
esc_session = result;
for(i in esc_session.concepts) {
for(j in esc_session.concepts[i]) {
esc_attribs[i] = j;
}
}
console.log("Started session.");
session.beginDialog(esc_session.questions[0].nodeType,[esc_session.sessionId, esc_session.questions[0]]);
})
.catch(function(err) {
console.log("Error starting ESC session.");
console.log(err);
})
}
]).beginDialogAction("cancelTree", "cancel", {matches: /^cancel$|^end$|^stop$|^halt/i});
//This dialog is for selection answers on a question node. It also saves recognized concepts within the answer.
bot.dialog("select", [
function(session, args) {
console.log("Select");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.userData = args;
var opts = new Array();
switch(args[1].valueType) {
case "string":
for(var i = 0; i < args[1].answerValues.length; i++) {
opts[i] = args[1].answerValues[i].value;
}
builder.Prompts.choice(session, message, opts, {listStyle: builder.ListStyle.button, maxRetries: 0});
break;
case "number":
for(var i = 0; i < args[1].answerIntervals.length; i++) {
opts[i] = args[1].answerIntervals[i].value;
}
builder.Prompts.number(session, message, {integerOnly: true, maxValue: 100, minValue: 0});
break;
case "datetime":
for(var i = 0; i < args[1].answerIntervals.length; i++) {
opts[i] = args[1].answerIntervals[i].value;
}
builder.Prompts.time(session, message + "\nPlease enter a date in format 'yyyy-mm-dd'.");
break;
}
},
function(session, results) {
let args = session.userData;
let answer;
//An answer was given.
if(results.response != null && results.response.entity != null) {
answer = results.response.entity;
} else if (results.response != null) {
answer = results.response;
} else {
//No answer (to a choice prompt) was given, check if concepts were recognized and try again.
}
esc.escAnnotateQuery(esc_header, session.message.text)
.then(function(result) {
for(i in result.concepts) {
for(j in result.concepts[i]) {
esc_attribs[i] = j;
}
}
console.log("Proceeding tree with answer %s", answer);
esc.escProceedTree(esc_header, args[0], args[1].nodeId, args[1].treeId, answer, esc_attribs)
.then(function(result) {
if(result.questions[0].nodeType === "error") {
//If no concept answers the question, ask again.
session.send("No answer was given.")
session.beginDialog("select", [esc_session.sessionId, esc_session.questions[0]])
} else {
esc_session = result;
console.log("Initiating new Dialog %s", esc_session.questions[0].nodeType);
//the nodeType is either "select", "info" or "solution"
session.beginDialog(esc_session.questions[0].nodeType, [esc_session.sessionId, esc_session.questions[0]])
}
})
.catch(function(err) {
console.log("Error proceeding tree.");
console.log(err);
});
})
}
]).beginDialogAction("cancelSelect", "cancel", {matches: /^abbrechen$|^beenden$|^stop$|^halt/i});
//This dialog is for showing hint nodes. It then automatically proceeds the tree.
bot.dialog("info", [
function(session, args) {
console.log("Info");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.send(message);
console.log("Proceeding tree without answer.");
esc.escProceedTree(esc_header, args[0], args[1].nodeId, args[1].treeId, "OK", esc_attribs)
.then(function(result) {
esc_session = result;
console.log("Initiating new Dialog %s", esc_session.questions[0].nodeType);
session.beginDialog(esc_session.questions[0].nodeType, [esc_session.sessionId, esc_session.questions[0]]);
})
.catch(function(err) {
console.log("Error proceeding tree.");
console.log(err);
});
}
])
//This dialog displays the reached solution. It then ends the dialog, erasing the concepts of this session.
bot.dialog("solution", [
function(session, args) {
console.log("Solution");
message = args[1].text;
attach(args[1].memo["Memo_URL"]);
session.send(message);
esc.escFinishSession(esc_header, args[0])
.then(function(result) {
console.log("Finished Session " + args[0]);
esc_session = undefined;
})
.catch(function(err) {
console.log("Error finishing session.");
console.log(err);
})
console.log("Ending dialog.");
session.endDialog("I hope i could help you.");
}
])
/*-----------
-- Manners --
-----------*/
// Greetings
bot.on("conversationUpdate", function (message) {
if (message.membersAdded && message.membersAdded.length > 0) {
// Don"t greet yourself
if(message.membersAdded[0].id !== message.address.bot.id) {
// Say hello
var reply = new builder.Message()
.address(message.address)
.text("Welcome to the Chatbot. Please enter your search.");
bot.send(reply);
}
} else if (message.membersRemoved) {
// Say goodbye
var reply = new builder.Message()
.address(message.address)
.text("Goodbye.");
bot.send(reply);
}
});
/*---------------------
-- Utility functions --
---------------------*/
//function for attached images
var attach = function(p) {
if(typeof p != undefined && p != null) {
console.log("Found attachment: %s", p);
session.send({
attachments:[{
contentUrl: p,
contentType: "image/jpeg"
}]
})
}
}
var undoMutation = function(s) {
while(s.indexOf("ä") !== -1) {
s = s.replace("ä", "ae");
}
while(s.indexOf("ö") !== -1) {
s = s.replace("ö", "oe");
}
while(s.indexOf("ü") !== -1) {
s = s.replace("ü", "ue");
}
return s;
}
可能是嵌套字符串提示对话框的问题。目前我只找到一些解决方法来快速解决问题。
最快:扩大提示对话框的距离,如果Bot输入无效,会重新提示问题。
builder.Prompts.choice(session, args[1].text, args[1].answerValues, { listStyle: builder.ListStyle.button, maxRetries: 2 });
正如我所见,您会将
treeNote
传递给 select 对话框,因此您可以尝试使用replaceDialog()
而不是beginDialog()
来清除嵌套对话框堆栈。在cancel
对话框中,也将endDialog()
替换为replaceDialog()