从不同的机器人访问CosmosDB

问题描述 投票:1回答:2

我正在尝试使用两个不同的机器人(js,v4,ms botframework)从/向Azure Cosmos DB读取和写入。

Chatbot 1: - 与用户聊天,保存用户数据并在以后使用

Chatbot 2: - 读取并显示一些用户数据

我使用以下客户端:https://github.com/Microsoft/BotFramework-WebChat

场景:

  1. 我将我的userID固定在客户端(它有一个指向机器人1的直接线),让我们说“123”
  2. 我使用Bot 1并在对话框中输入我的用户名(由bot提示)
  3. 我使用相同的ID“123”刷新运行Bot 1的网站
  4. 我看到机器人仍然存储了我的数据
  5. 我将客户端的ID更改为“124”
  6. 我使用Bot 1并看到没有存储的数据(由于ID“124”从未与Bot 1聊过,因此预计会这样做)
  7. 我将ID更改回“123”
  8. 我使用bot 1,看到第2步中的数据仍然存在
  9. 我使用id为“123”的bot 2
  10. 我看到没有数据(“未定义”)
  11. 我再次使用ID为“123”的机器人
  12. 我看到第2步的数据消失了

这意味着每当我使用我的第二个机器人访问数据库时,似乎数据被清除/删除。

这是我在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: {}
              }

有任何想法吗?提前致谢

javascript database azure botframework access
2个回答
1
投票

由于存储ID(参见图像)是根据用户ID(也可能是自动创建并因频道而异)和频道ID自动创建的,因此这很难做到。它可以使持久的用户和会话数据变得非常困难,特别是在机器人和频道上。

示例ID:

enter image description here

Here's more on how IDs work

就个人而言,我会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':

enter image description here

阅读:

const userDataFromStorage = await this.memoryStorage.read(['UserId']);

userDataFromStorage将如下所示:

{ UserId:
   { name: 'myName',
     eTag: '"0000c700-0000-0000-0000-5c7879d30000"' } }

您必须自己管理userIds,但这将确保可以跨机器人,渠道和用户读取数据。


0
投票

编辑:通过在每次“用户”调用后添加“[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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.