我用MS Botframework v4实现了一个聊天机器人。我使用UserState和ConversationState,而我的MemoryStorage是来自Azure的BlobDB。
运行机器人时,我得到了两个UserState数据集,而只有一个ConversationState数据集。
在我的对话框中的某个时刻,Bot似乎“切换”到另一个UserState数据集,并且以前保存在旧集中的所有内容都不再可用。
这是在谈话的早期发生的。
这是我的onTurn。在这里,我是第一次访问UserState和ConversationState:
async onTurn(turnContext) {
const dc = await this.dialogSet.createContext(turnContext);
//await logMessageText(this.memoryStorage, turnContext, this.userState);
// See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types.
if (turnContext.activity.type === ActivityTypes.value){
console.log(turnContext.activity.type.value);
}
if (turnContext.activity.type === ActivityTypes.Message) {
// Continue ongoing dialog
await dc.continueDialog();
} else if (turnContext.activity.type === ActivityTypes.ConversationUpdate) {
// Do we have any new members added to the conversation?
if (turnContext.activity.membersAdded.length !== 0) {
// Iterate over all new members added to the conversation
for (var idx in turnContext.activity.membersAdded) {
// Greet anyone that was not the target (recipient) of this message.
// Since the bot is the recipient for events from the channel,
// context.activity.membersAdded === context.activity.recipient.Id indicates the
// bot was added to the conversation, and the opposite indicates this is a user.
if (turnContext.activity.membersAdded[idx].id !== turnContext.activity.recipient.id) {
// Funktionierender Code, wenn WebChat gefixt
console.log("User added");
// Read ConversationData from State
const conversationData = await this.conversationDataAccessor.get(turnContext, {});
const user = await this.userDataAccessor.get(turnContext, {});
// Get userID which is either IDA for advisory or IDR for result
conversationData.URLparam = turnContext.activity.membersAdded[idx].id;
// Manually set userId for Emulator use
conversationData.URLparam = "1234A";
// Set userID
if (!conversationData.userID) {
console.log("UserID wird eingetragen");
conversationData.userID = conversationData.URLparam.substring(0, conversationData.URLparam.length-1);
console.log("Eingetragene user ID:" + conversationData.userID);
}
// Get last character which determines mode
conversationData.mode = conversationData.URLparam.substring(conversationData.URLparam.length-1, conversationData.URLparam.length);
// Write user and conversationdata to State
await this.conversationDataAccessor.set(turnContext, conversationData);
await this.userDataAccessor.set(turnContext, user);
// Route to correct dialog depending on treatment and bot type
if (treatment.initiation == true && conversationData.mode.localeCompare("A") == 0) {
console.log("Advisory Modus");
await dc.beginDialog('welcome', conversationData.userID);
} else if (treatment.initiation == false) {
await dc.beginDialog('startBot', conversationData.userID);
} else if (treatment.initiation == true && conversationData.mode.localeCompare("R") == 0) {
console.log("Result Modus");
await dc.beginDialog('investmentResult', conversationData.userID)
}
}
if (turnContext.activity.membersAdded[idx].id === turnContext.activity.recipient.id) {
// Start the dialog.
console.log("Bot joined");
}
}
}
}
首先调用我的对话框“ welcome”,然后调用“ promptForName”。在下一个代码段中一切正常:
// Function for welcoming user
async welcomeUser (step) {
console.log("Welcome User Dialog");
// Get userId from onTurn()
const userID = step.options;
// Get conversation- and userData from bot state
const conversationData = await this.conversationDataAccessor.get(step.context, {});
const user = await this.userDataAccessor.get(step.context, {});
console.log("User in welcome dialog");
console.log(util.inspect(user, false, null, false ));
console.log("conversationData from Middleware");
console.log(util.inspect(conversationData, false, null, false ));
// Write user and conversationdata to state
await this.userDataAccessor.set(step.context, user);
await this.conversationDataAccessor.set(step.context, conversationData);
// Welcome the user
if (treatment.introduction == true && treatment.rememberName == true && treatment.gender == true) {
await sendWithDelay("Hallo und herzlich willkommen, ich bin **Charles**, dein persönlicher **Investmentberater**. Ich begleite dich durch den Beratungsprozess.", step);
} else if (treatment.introduction == true && treatment.gender == false) {
var msg = "Hallo und herzlich willkommen, ich bin ein **Robo-Advisor**. Ich begleite dich durch den Beratungsprozess.";
await sendWithDelay(msg, step);
} else if (treatment.introduction == false && treatment.selfReference == false && treatment.rememberName == false) {
var msg = "Du wirst nun durch den Beratungsprozess begleitet.";
await sendWithDelay(msg, step);
}
// Check if bot in testmode and route to dialogs
if (testing == true) {
// Start main dialog
return await step.beginDialog('mainMenu', userID);
} else {
// Start Profilecreation
return await step.beginDialog('createProfile', userID);
}
}
// Functions for creating UserProfile
async promptForName (step) {
console.log("Name Prompt");
// Get userID from prior step and clear changes
const userID = step.options;
// Read UserData from State
const user = await this.userDataAccessor.get(step.context, {});
const conversationData = await this.conversationDataAccessor.get(step.context, {});
// Save User- and Conversationdata to State
await this.userDataAccessor.set(step.context, user);
await this.conversationDataAccessor.set(step.context, conversationData);
// Before prompting, check if value already exists
if(!user.name){
if (user.deleted == true) {
if (treatment.selfReference == true) {
var msg = "Ich stelle dir nun die gleichen Fragen erneut.";
await sendWithDelay(msg, step);
} else {
var msg = "Im folgenden nochmal die gleichen Fragen.";
await sendWithDelay(msg, step);
}
} else {
if (treatment.selfReference == true) {
var msg = "Ich stelle dir nun ein paar Fragen, um deine wichtigsten Daten zu erfassen.";
await sendWithDelay(msg, step);
} else {
var msg = "Im folgenden ein paar Fragen, um deine wichtigsten Daten zu erfassen.";
await sendWithDelay(msg, step);
}
}
// Username doesn't exist --> Prompt
await delay(userData.name.prompt, step).then(async function() {
return await step.prompt(NAME_PROMPT, userData.name.prompt);
});
} else {
return await step.next();
}
}
在下一个将用户的回复写入userData的代码段中,突然创建了一个新的dataSet。
async promptForAge (step) {
console.log("Age Prompt");
// Get userID from prior step and clear changes
var userID = step.options;
// Get UserData from State
const user = await this.userDataAccessor.get(step.context, {});
console.log("User in age dialog");
console.log(util.inspect(user, false, null, false ));
// Before saving entry, check if it already exists
if(!user.name) {
user.name = step.result;
// Write userData to State
await this.userDataAccessor.set(step.context, user);
// Notify user about his name being remembered
if (treatment.rememberName == true) {
var msg = `Hallo **${user.name}**! Danke, dass du mir deinen Namen verraten hast. Ich werde ihn mir ab jetzt merken.`;
await sendWithDelay(msg, step);
}
}
// Before prompting, check if value already exists
if(!user.age) {
await delay(userData.age.prompt, step).then(async function() {
return await step.prompt(AGE_PROMPT, userData.age.prompt);
});
} else {
return await step.next();
}
}
这是数据库中数据集的外观:
这是两个用户数据集的内容:
正在创建的第一个
{"id":"emulator%2Fusers%2Fdeb871a4-cbb9-4e3c-9fff-e9ed88f597f5","realId":"emulator/users/deb871a4-cbb9-4e3c-9fff-e9ed88f597f5/","document":{"userData":{},"eTag":"*"}}
将step.result一次创建的内容写入user.name:
{"id":"emulator%2Fusers%2Fr_72zsnsmmnp","realId":"emulator/users/r_72zsnsmmnp/","document":{"userData":{"name":"John Doe"},"eTag":"*"}}