我正在尝试使用两个不同的机器人(js,v4,ms botframework)从/向Azure Cosmos DB读取和写入。
Chatbot 1: - 与用户聊天,保存用户数据并在以后使用
Chatbot 2: - 读取并显示一些用户数据
我使用以下客户端:https://github.com/Microsoft/BotFramework-WebChat
场景:
这意味着每当我使用我的第二个机器人访问数据库时,似乎数据被清除/删除。
这是我在index.js中访问数据库的方法:
//Add CosmosDB (info in .env file)
const memoryStorage = new CosmosDbStorage({
serviceEndpoint: process.env.ACTUAL_SERVICE_ENDPOINT,
authKey: process.env.ACTUAL_AUTH_KEY,
databaseId: process.env.DATABASE,
collectionId: process.env.COLLECTION
})
// ConversationState and UserState
const conversationState = new ConversationState(memoryStorage);
const userState = new UserState(memoryStorage);
// Use middleware to write/read from DB
adapter.use(new AutoSaveStateMiddleware(conversationState));
adapter.use(new AutoSaveStateMiddleware(userState));
这就是我在bot.js中使用DB的方式:
constructor(conversationState, userState, dialogSet, memoryStorage) {
// Creates a new state accessor property.
// See https://aka.ms/about-bot-state-accessors to learn more about the bot state and state accessors
this.conversationState = conversationState;
this.userState = userState;
// Memory storage
this.memoryStorage = memoryStorage;
// Conversation Data Property for ConversationState
this.conversationData = conversationState.createProperty(CONVERSATION_DATA_PROPERTY);
// Properties for UserState
this.userData = userState.createProperty(USER_DATA_PROPERTY);
this.investmentData = userState.createProperty(INVESTMENT_DATA_PROPERTY);
}
async displayPayout (step) {
console.log("Display Payout");
// Retrieve user object from UserState storage
const userInvestData = await this.investmentData.get(step.context, {});
const user = await this.userData.get(step.context, {});
await step.context.sendActivity(`Hallo ${user.name}. Am Ausgang kannst du dir deine Bezahlung von ${userInvestData.payout} abholen.` );
}
代码片段来自bot 2. Bot 1以相同的方式保存数据。你可以在这里找到回购:
机器人1:https://github.com/FRANZKAFKA13/roboadvisoryBot
机器人2:https://github.com/FRANZKAFKA13/displayBot
Bot 1的客户:https://github.com/FRANZKAFKA13/ra-bot-website-c
Bot 2的客户:https://github.com/FRANZKAFKA13/ra-bot-website-display
我还尝试在bot 2中使用CosmosDB中的“readOnly”键,这会引发错误:
[onTurnError]: [object Object]
(node:1640) UnhandledPromiseRejectionWarning: TypeError: Cannot perform 'set' on a proxy that has been revoked
at adapter.sendActivities.then (C:\Users\X\Implementierung\display_bot\node_modules\botbuilder-core\lib\turnContext.js:175:36)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
(node:1640) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
我注意到的另一个行为:当我通过我的客户端使用redux存储触发“加入事件”时,也不会保存用户数据(每次刷新页面时,数据都会消失,尽管使用相同的ID“123 “ 每时每刻)
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
// Event starting bot's conversation
name: 'webchat/join',
value: {}
}
有任何想法吗?提前致谢
由于存储ID(参见图像)是根据用户ID(也可能是自动创建并因频道而异)和频道ID自动创建的,因此这很难做到。它可以使持久的用户和会话数据变得非常困难,特别是在机器人和频道上。
示例ID:
就个人而言,我会write my own, custom storage,而不是(或除了)用UserState
保存它。
要编写数据,请执行以下操作:
const changes = {};
const userDataToWrite = {
name: step.result,
eTag: '*',
}
// Replace 'UserId' with however you want to set the UserId
changes['UserId'] = userDataToWrite;
this.memoryStorage.write(changes);
这将存储一个看起来像这样的文档(我将'UserId'设置为'user123':
阅读:
const userDataFromStorage = await this.memoryStorage.read(['UserId']);
userDataFromStorage
将如下所示:
{ UserId:
{ name: 'myName',
eTag: '"0000c700-0000-0000-0000-5c7879d30000"' } }
您必须自己管理userIds,但这将确保可以跨机器人,渠道和用户读取数据。
编辑:通过在每次“用户”调用后添加“[this.userID]”解决它。
我尝试了你的方法,每当我写入数据时,都会创建一个新的eTag,导致对象被拆分:
"document": {
"25781dc4-805d-4e69-bf89-da1f4d72e7cb": {
"25781dc4-805d-4e69-bf89-da1f4d72e7cb": {
"25781dc4-805d-4e69-bf89-da1f4d72e7cb": {
"25781dc4-805d-4e69-bf89-da1f4d72e7cb": {
"25781dc4-805d-4e69-bf89-da1f4d72e7cb": {
"name": "",
"age": "",
"gender": "",
"education": "",
"major": "",
"eTag": "\"00003998-0000-0000-0000-5c797fff0000\""
},
"name": "Jane Doe",
"eTag": "\"00003e98-0000-0000-0000-5c7980080000\""
},
"age": 22,
"eTag": "\"00004898-0000-0000-0000-5c7980150000\""
},
"gender": "female",
"eTag": "\"00004d98-0000-0000-0000-5c79801b0000\""
},
"education": "Bachelor",
"eTag": "\"00005498-0000-0000-0000-5c7980200000\""
},
"major": "Business Administration",
"complete": true
我怎么能阻止这个?
我的代码:
在构造函数中:
this.changes = {};
this.userID = "";
this.userDatax = {
name: "",
age: "",
gender: "",
education: "",
major: "",
eTag: '*',
}
在对话框中:
async welcomeUser (step) {
console.log("Welcome User Dialog");
//step.context.sendActivity({ type: ActivityTypes.Typing});
// Initialize UserData Object and save it to DB
this.changes[this.userID] = this.userDatax;
await this.memoryStorage.write(this.changes);
}
async promptForAge (step) {
console.log("Age Prompt");
// Read UserData from DB
var user = await this.memoryStorage.read([this.userID]);
console.log(user);
// Before saving entry, check if it already exists
if(!user.name) {
user.name = step.result;
user.eTag = '*';
// Write userData to DB
this.changes[this.userID] = user;
await this.memoryStorage.write(this.changes);
}
}