Есть ли способ захвата и сохранения сквозных данных разговора в хранилище больших двоичных объектов или в космическую БД в среде ботов с использованием SDK V4 Nodedjs - PullRequest
1 голос
/ 23 марта 2020

Я хочу сохранить данные разговора в учетной записи хранения или в космической БД. Попробовав 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

, я могу отправить журнал utterances в хранилище BLOB-объектов. Но я хочу сохранить сквозные данные разговора, которые включают в себя данные обоих пользователей, а также ответы ботов, используя javascript.

Я пытался использовать сохранение состояния пользователя и состояния разговора, но не достиг желаемого выход.

1 Ответ

1 голос
/ 23 марта 2020

Я создал собственный регистратор (на основе старого образца образцов botduilder, которого больше нет), который выполняет это с помощью TranscriptLoggerMiddleware. Я выбрал CosmosDB вместо Blob Storage, потому что чувствовал, что его проще хранить (и удалять) как документ JSON. Но вы можете настроить эту концепцию, чтобы использовать любую БД. Вот что я сделал.

Сначала создайте свой собственный код логгера. Как уже упоминалось, я использовал CosmosDB, поэтому вам, возможно, придется изменить некоторые вещи, если вы используете другую БД. Временами действий были проблемы с параллелизмом, поэтому вместо того, чтобы обойти это, я храню объект расшифровки локально и перезаписываю объект БД на каждом ходу. Может быть, не самый элегантный, но это работает. Кроме того, я обнаружил, что моя функция ожидания обязательна . В противном случае вы получите только одну сторону разговора. Мне сказали, что функция ожидания такого типа не является лучшей практикой, но ожидание обещания или других методов создания задержки не сработало для меня. Вот код:

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;

Теперь вам нужно присоединить это к адаптеру botframework в вашем файле индекса. js. Соответствующие фрагменты кода:

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);

Я предполагаю, что у вас уже есть индекс. js файл определен , но если вам нужна помощь в настройке и настройке регистратора стенограмм для работы с ним, просто дайте мне знать.

РЕДАКТИРОВАТЬ: По запросу, вот как выглядит объект в CosmosDB. Обычно я отображал «от имени», но из-за того, как я тестировал бота, он проходил через «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 передается в мою функцию и является идентификатором беседы):

    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]);
...