有没有什么方法可以使用 SDK V4 Nodedjs 在 bot 框架中捕获端到端对话数据并将其保存到 blob 存储或 cosmos DB 中

Is there any way to capture and save end-to-end conversation data into blob storage or cosmos DB in bot framework using SDK V4 Nodedjs

我想将对话数据存储到存储账户或cosmos DB。通过尝试这个 https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-storage?view=azure-bot-service-4.0&tabs=javascript#using-blob-storage

我能够将话语日志发送到 blob 存储中。但是我想存储端到端的对话数据,其中包括两个用户的数据以及使用 javascript.

的机器人响应

我尝试使用保存用户状态和对话状态,但没有达到预期的输出。

我创建了一个自定义记录器(基于不再存在的旧 botduilder-samples 示例),它使用 TranscriptLoggerMiddleware 完成此操作。我选择 CosmosDB 而不是 Blob 存储,因为我觉得它更容易存储(和检索)为 JSON 文档。但是您可以调整这个概念以使用任何数据库。这是我所做的。

首先,创建您的自定义记录器代码。如前所述,我使用的是 CosmosDB,因此如果您使用的是不同的数据库,则可能需要更改一些内容。这些活动的时间安排造成了并发问题,因此我没有解决这个问题,而是在本地存储转录对象,并在每个回合 覆盖 DB 对象。也许不是最优雅的,但它确实有效。此外,我发现我的等待函数是 必需的 。否则你只能站在谈话的一边。我被告知这种类型的等待功能不是最佳实践,但等待承诺或其他创建延迟的方法对我不起作用。这是代码:

customerLogger.js

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const { CosmosDbStorage } = require('botbuilder-azure');
const path = require('path');

/**
 * CustomLogger, takes in an activity and saves it for the duration of the conversation, writing to an emulator compatible transcript file in the transcriptsPath folder.
 */
class CustomLogger {
    /**
     * Log an activity to the log file.
     * @param activity Activity being logged.
     */

    // Set up Cosmos Storage
    constructor(appInsightsClient) {
        this.transcriptStorage = new CosmosDbStorage({
            serviceEndpoint: process.env.COSMOS_SERVICE_ENDPOINT,
            authKey: process.env.COSMOS_AUTH_KEY,
            databaseId: process.env.DATABASE,
            collectionId: 'bot-transcripts'
        });

        this.conversationLogger = {};

        this.appInsightsClient = appInsightsClient;

        this.msDelay = 250;
    }


    async logActivity(activity) {

        if (!activity) {
            throw new Error('Activity is required.');
        }

        // Log only if this is type message
        if (activity.type === 'message') {

            if (activity.attachments) {
                var logTextDb = `${activity.from.name}: ${activity.attachments[0].content.text}`;
            } else {
                var logTextDb = `${activity.from.name}: ${activity.text}`;
            }

            if (activity.conversation) {
                var id = activity.conversation.id;
                if (id.indexOf('|') !== -1) {
                    id = activity.conversation.id.replace(/\|.*/, '');
                }

                // Get today's date for datestamp
                var currentDate = new Date();
                var day = currentDate.getDate();
                var month = currentDate.getMonth()+1;
                var year = currentDate.getFullYear();
                var datestamp = year + '-' + month + '-' + day;
                var fileName = `${datestamp}_${id}`;

                var timestamp = Math.floor(Date.now()/1);

                // CosmosDB logging (JK)
                if (!(fileName in this.conversationLogger)) {
                    this.conversationLogger[fileName] = {};
                    this.conversationLogger[fileName]['botName'] = process.env.BOTNAME;
                }

                this.conversationLogger[fileName][timestamp] = logTextDb;

                let updateObj = {

                    [fileName]:{
                        ...this.conversationLogger[fileName]
                    }

                }

                // Add delay to ensure messages logged sequentially
                await this.wait(this.msDelay);

                try {
                    let result = await this.transcriptStorage.write(updateObj);
                } catch(err) {
                    this.appInsightsClient.trackTrace({message: `Logger ${err.name} - ${path.basename(__filename)}`,severity: 3,properties: {'botName': process.env.BOTNAME, 'error':err.message,'callStack':err.stack}});
                }
            }
        }
    }
    async wait(milliseconds) {
        var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > milliseconds) {
                break;
            }
        }
    }
}
exports.CustomLogger = CustomLogger;

现在您需要将其附加到 index.js 文件中的 botframework 适配器。相关代码为:

index.js

const { TranscriptLoggerMiddleware } = require('botbuilder');
const { CustomLogger } = require('./helpers/CustomLogger');

//
//Your code to create your adapter, etc.
//

const transcriptLogger = new TranscriptLoggerMiddleware(new CustomLogger(appInsightsClient));
adapter.use(transcriptLogger);

我在这里假设您已经弄清楚了 index.js 文件,但是如果您需要任何帮助来设置它并让转录记录器使用它,请告诉我。

编辑:根据要求,这是对象在 CosmosDB 中的样子。通常我会显示 "from name",但由于我测试机器人的方式,它通过 "undefined".

{
    "id": "2020-3-21_IfHK46rZV42KH5g3dIUgKu-j",
    "realId": "2020-3-21_IfHK46rZV42KH5g3dIUgKu-j",
    "document": {
        "botName": "itInnovationBot",
        "1584797671549": "Innovation Bot: Hi! I'm the IT Innovation Bot. I can answer questions about the innovation team and capture your innovation ideas. Let me know how I can help!",
        "1584797692355": "undefined: Hello",
        "1584797692623": "Innovation Bot: Hello.",
        "1584797725223": "undefined: Tell me about my team",
        "1584797725490": "Innovation Bot: The innovation team is responsible for investigating, incubating, and launching new technologies and applications. The innovation focus areas are:\n\n* Chatbots\n\n* Augmented Reality/Virtual Reality\n\n* Blockchain\n\n* Robotic Process Automation\n\n* AI & Machine Learning\n\nLet me know if you want to learn more about any of these technologies!",
        "1584797746279": "undefined: Thanks",
        "1584797746531": "Innovation Bot: You're welcome."
    },
    "_rid": "OsYpALLrTn2TAwAAAAAAAA==",
    "_self": "dbs/OsYpAA==/colls/OsYpALLrTn0=/docs/OsYpALLrTn2TAwAAAAAAAA==/",
    "_etag": "\"a4008d12-0000-0300-0000-5e7618330000\"",
    "_attachments": "attachments/",
    "_ts": 1584797747
}

要回读对话(即使仍在对话中间),您只需在机器人中创建一个连接器,重新创建密钥,然后读取文件下面(在这种情况下,id 被传递到我的函数中,并且是对话 id):

    const transcriptStorage = new CosmosDbStorage({
        serviceEndpoint: process.env.COSMOS_SERVICE_ENDPOINT,
        authKey: process.env.COSMOS_AUTH_KEY,
        databaseId: process.env.DATABASE,
        collectionId: 'bot-transcripts',
        partitionKey: process.env.BOTNAME
    });

    // Get today's date for datestamp
    var currentDate = new Date();
    var day = currentDate.getDate();
    var month = currentDate.getMonth()+1;
    var year = currentDate.getFullYear();
    var datestamp = year + '-' + month + '-' + day;
    var filename = `${datestamp}_${id}`;

    var transcript = await transcriptStorage.read([filename]);