首页 > 解决方案 > 如何维护调度机器人和技能机器人之间的状态?

问题描述

我正在使用通过 Microsoft 的botframework-solutionsGithub 存储库提供的虚拟助手模板,并且在维护我们的主要入口点之间的活动对话时遇到了麻烦——开发的机器人实现了调度模型以确定发送用户话语以进行进一步处理的技能—— - 个人技能处理用户的输入。

我让我们的调度模型机器人收听localhost:3979/api/messages使用route方法 inmainDialog.ts确定将用户话语传递给的相关技能的 POST,该技能采用该话语并确定应该使用技能中的哪个对话来处理用户的话语。当我们开始一个实现多步骤瀑布对话的对话时,调度模型机器人不会跟踪技能机器人中活动的对话,因此技能机器人不知道如何将用户的话语路由到已经激活的对话框。当我们直接发布到技能机器人并在调度模型机器人之前,技能机器人能够跟踪活动对话,这让我相信我们没有正确管理调度机器人和技能机器人之间的状态.

我注意到我们从模板中使用的 bot 虚拟助手和技能模板botframework-solutions实例化了AutoSaveStateMiddleWare它们的新实例defaultAdapter.ts,因此看来对话和用户状态的读取和写入应该已经被自动管理。

调度机器人中的 mainDialog.ts,它将话语路由到适当的技能

protected async route(dc: DialogContext): Promise<void> {
        // Get cognitive models for locale
        const locale: string = i18next.language.substring(0, 2);
        const cognitiveModels: ICognitiveModelSet | undefined = this.services.cognitiveModelSets.get(locale);

        if (cognitiveModels === undefined) {
            throw new Error('There is no value in cognitiveModels');
        }
        // Check dispatch result
        const dispatchResult: RecognizerResult = await cognitiveModels.dispatchService.recognize(dc.context);
        const intent: string = LuisRecognizer.topIntent(dispatchResult);

        if (this.settings.skills === undefined) {
            throw new Error('There is no skills in settings value');
        }
        // Identify if the dispatch intent matches any Action within a Skill if so, we pass to the appropriate SkillDialog to hand-off
        const identifiedSkill: ISkillManifest | undefined = SkillRouter.isSkill(this.settings.skills, intent);
        if (identifiedSkill !== undefined) {
            // We have identified a skill so initialize the skill connection with the target skill
            await dc.beginDialog(identifiedSkill.id);

            // Pass the activity we have
            const result: DialogTurnResult = await dc.continueDialog();

            if (result.status === DialogTurnStatus.complete) {
                await this.complete(dc);
            }
        } else if (intent === 'l_NOVA_general') {
            // If dispatch result is general luis model
            const luisService: LuisRecognizerTelemetryClient | undefined = cognitiveModels.luisServices.get(this.luisServiceGeneral);
            if (luisService === undefined) {
                throw new Error('The specified LUIS Model could not be found in your Bot Services configuration.');
            } else {
                const result: RecognizerResult = await luisService.recognize(dc.context);
                if (result !== undefined) {
                    const generalIntent: string = LuisRecognizer.topIntent(result);

                    // switch on general intents
                    switch (generalIntent) {
                        case 'Escalate': {
                            // start escalate dialog
                            await dc.beginDialog(EscalateDialog.name);
                            break;
                        }
                        case 'None':
                        default: {
                            // No intent was identified, send confused message
                            await this.responder.replyWith(dc.context, MainResponses.responseIds.confused);
                        }
                    }
                }
            }
        } else {
            // If dispatch intent does not map to configured models, send 'confused' response.
            await this.responder.replyWith(dc.context, MainResponses.responseIds.confused);
        }
    }

以下来自技能机器人的代码,dialogBot.ts它监听所有turn事件

public async turn(turnContext: TurnContext, next: () => Promise<void>): Promise<any> {
        // Client notifying this bot took to long to respond (timed out)
        if (turnContext.activity.code === EndOfConversationCodes.BotTimedOut) {
            this.telemetryClient.trackTrace({
                message: `Timeout in ${ turnContext.activity.channelId } channel: Bot took too long to respond`,
                severityLevel: Severity.Information
            });

            return;
        }

        const dc: DialogContext = await this.dialogs.createContext(turnContext);

        if (dc.activeDialog !== undefined) {
            const result: DialogTurnResult = await dc.continueDialog();
        } else {
            await dc.beginDialog(this.rootDialogId);
        }

        await next();
    }

mainDialog.ts路由到claims_claimsStatus瀑布对话框的技能机器人内

protected async route(dc: DialogContext): Promise<void> {
        // get current activity locale
        const locale: string = i18next.language.substring(0, 2);
        const localeConfig: Partial<ICognitiveModelSet> | undefined = this.services.cognitiveModelSets.get(locale);

        // Populate state from SkillContext slots as required
        await this.populateStateFromSkillContext(dc.context);
        if (localeConfig === undefined) {
            throw new Error('There is no cognitiveModels for the locale');
        }
        // Get skill LUIS model from configuration
        if (localeConfig.luisServices !== undefined) {

            const luisService: LuisRecognizerTelemetryClient | undefined = localeConfig.luisServices.get(this.solutionName);

            if (luisService === undefined) {
                throw new Error('The specified LUIS Model could not be found in your Bot Services configuration.');
            } else {
                let turnResult: DialogTurnResult = Dialog.EndOfTurn;
                const result: RecognizerResult = await luisService.recognize(dc.context);
                const intent: string = LuisRecognizer.topIntent(result);

                switch (intent) {
                    case 'claims_claimStatus': {
                        turnResult = await dc.beginDialog(StatusDialog.name);
                        break;
                    }
.
.
.

预期结果:当使用调度机器人路由到技能机器人时,在对话中开始瀑布对话后claims_claimStatusdialogContext.activeDialog应该是statusDialog瀑布对话的进一步步骤

实际结果:当使用调度机器人路由到技能机器人时,在对话中开始瀑布对话后claims_claimStatusdialogContext.activeDialog应该是undefined瀑布对话的进一步步骤

标签: botframework

解决方案


推荐阅读