我正在使用通过Microsoft的botframework-solutions
Github存储库提供的虚拟助手模板,并且在维护我们的主要入口点之间的活动对话框时遇到了麻烦-这是一个开发出的机器人,该机器人实现了调度模型以确定要使用的技能发送用户的话语以进行进一步处理-个性化技能会处理用户的输入。
我让我们的调度模型机器人侦听使用localhost:3979/api/messages
中的route
方法对mainDialog.ts
进行的POST,以确定将用户的话语传递给的相关技能,这将使该话语成为可能并确定应使用技能中的哪个对话框来处理用户的话语。当我们开始实现多步瀑布对话框的对话框时,调度模型bot不会跟踪技能bot中活动的对话框,因此技能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_claimStatus
对话框中开始瀑布对话框之后,dialogContext.activeDialog
应该为statusDialog
,以进行进一步的操作瀑布对话框
实际结果:在使用分派机器人将其路由到技能机器人时,在claims_claimStatus
对话框中开始瀑布对话框之后,dialogContext.activeDialog
应该为undefined
,以进行进一步的操作瀑布对话框