我有2个与虚拟助手相关的技能,并且我正在尝试从技能A调用技能B(在技能A的末尾,并且用户没有进一步的操作)。我知道我必须为此通过虚拟助手。我要处理两个问题:
对于第二个问题,使用带有插槽的SkillContext似乎是the way,但是我似乎找不到第一个问题的解决方案,因为当技能返回到VA时,它全部返回是一个布尔值,指示它是否已完成https://github.com/microsoft/botframework-solutions/blob/853a7ccb940ec2c4d59433b6f2ca2cfa8d5264b4/lib/typescript/botbuilder-skills/src/skillDialog.ts#L229。
我试图做的是将我的数据保存在Skill A的SkillContext中,然后在VA中获取该数据并将其传递给SkillB。但是,这只有在Skill A和VA都向相同的Cosmos DB,这并不理想。
有没有更好的解决方案?
答案 0 :(得分:0)
可以不使用对话框将数据从技能传递到父机器人吗?
我正在使用以下代码片段来调用根机器人的技能
var response = await _skillClient.PostActivityAsync(_botId, targetSkill, _skillsConfig.SkillHostEndpoint, turnContext.Activity, cancellationToken);
我正在使用以下代码段结束技能机器人中的对话
var endOfConversation = Activity.CreateEndOfConversationActivity();
endOfConversation.Code = EndOfConversationCodes.CompletedSuccessfully;
答案 1 :(得分:0)
就我而言,我使用的是 Bot Composer 而不是 PVA。我希望语法是相似的,并且这将同样适用于具有自定义创建技能的 PVA。
我一直在寻求做类似的事情,并且能够使用以下语法获得可行的解决方案。
在我的示例中,我有一个包含 2 个步骤的瀑布式对话框。第一步显示带有几个选项的提示。最后一步检索所选值并结束对话和对话。就我而言,我希望将所选值作为技能的输出返回,以便我可以将其保存到作曲家中的变量中,并在稍后的对话中使用。
我的对话代码是:
public class ActiveFuelCardDialog : ComponentDialog
{
public ActiveFuelCardDialog() : base(nameof(ActiveFuelCardDialog))
{
InitializeWaterfallDialog();
}
public WaterfallStepContext StepContext { get; private set; }
private void InitializeWaterfallDialog()
{
var waterFallSteps = new WaterfallStep[]
{
CardSelectionStepAsync,
FinalStepAsync
};
AddDialog(new WaterfallDialog($"{nameof(ActiveFuelCardDialog)}.mainFlow", waterFallSteps));
AddDialog(new ChoicePrompt($"{nameof(ActiveFuelCardDialog)}.cardSelection"));
InitialDialogId = $"{nameof(ActiveFuelCardDialog)}.mainFlow";
}
private async Task<DialogTurnResult> CardSelectionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
StepContext = stepContext;
//then return back a list of 2 cards
//in the format: CardType
List<ActiveFuelCardsOutput> activeFuelCardsOutputs = new List<ActiveFuelCardsOutput>();
activeFuelCardsOutputs.Add(new ActiveFuelCardsOutput()
{
CardNo = "1234567890123456",
CardType = "WM",
ExpiryDate = DateTime.Now.AddMonths(8)
});
activeFuelCardsOutputs.Add(new ActiveFuelCardsOutput()
{
CardNo = "2345678901234657",
CardType = "WM",
ExpiryDate = DateTime.Now.AddMonths(6)
});
activeFuelCardsOutputs.Add(new ActiveFuelCardsOutput()
{
CardNo = "3456789012345678",
CardType = "WM",
ExpiryDate = DateTime.Now.AddMonths(12)
});
return await stepContext.PromptAsync($"{nameof(ActiveFuelCardDialog)}.cardSelection",
new PromptOptions
{
Prompt = MessageFactory.Text("Please select a card"),
Choices = ChoiceFactory.ToChoices(activeFuelCardsOutputs.Select(x => x.CardNo).ToArray())
}, cancellationToken);
}
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
StepContext = stepContext;
string selectedCard = ((FoundChoice)stepContext.Result).Value;
//https://techcommunity.microsoft.com/t5/teams-developer/skill-dialog-enddialog-does-not-work/m-p/1476612
await stepContext.Context.SendActivityAsync(new Activity()
{
Type = ActivityTypes.EndOfConversation,
Code = EndOfConversationCodes.CompletedSuccessfully,
Value = selectedCard
});
return await stepContext.EndDialogAsync();
}
}
导致此功能对我有用的部分是在 FinalStepAsync 方法中
await stepContext.Context.SendActivityAsync(new Activity()
{
Type = ActivityTypes.EndOfConversation,
Code = EndOfConversationCodes.CompletedSuccessfully,
Value = selectedCard
});
return await stepContext.EndDialogAsync();
这似乎结束了对话并返回了值。
然后我可以通过将技能的“属性”设置为某个变量(例如 dialog.selectedCard)在 Bot Composer 中使用它。然后使用像“${dialog.selectedCard}”这样的值。
这篇文章让我找到了这个答案。 Helpful Post