Microsoft botframework V4,自定义技能。
打字稿
技能无法通过 SkillContext 接收到虚拟助手传递过来的信息
第 1 步:使用“ https://botbuilder.myget.org/feed/aitemplates/package/npm/botbuilder-solutions ”生成 VA
第 2 步:使用技能生成器命令生成技能
“ https://botbuilder.myget.org/feed/aitemplates/package/npm/botbuilder-skills ”
第 3 步:添加带有 slot 参数的技能清单文件
第 4 步:使用 slot 参数值设置 SkillContext。
第 5 步:尝试访问 Skill 处的 SkillContext 值。
如果“slot”属性匹配,则技能应该可以访问在 SkillContext 中设置的对象。
但是技能是无法获取到SkillContext的。
“SkillMiddleware”应该支持skillContextAccessor 并用slot 参数填充SkillContext。
在做了一些工作后发现 CustomSkillAdapter 填充了“skillContextAccessor”值。
当前代码:
导出类 CustomSkillAdapter 扩展 SkillHttpBotAdapter {
构造函数(
遥测客户端:遥测客户端,
对话状态:对话状态,
SkillContextAccessor:StatePropertyAccessor
dialogStateAccessor:StatePropertyAccessor
...
){
超级(遥测客户端);
[...]
this.use(new SkillMiddleware(conversationState, dialogStateAccessor));
[...]
}
}
根据此“ https://microsoft.github.io/botframework-solutions/howto/skills/skillenablingav4bot/ ”的预期代码
导出类 CustomSkillAdapter 扩展 SkillHttpBotAdapter {
构造函数(
遥测客户端:遥测客户端,
对话状态:对话状态,
SkillContextAccessor:StatePropertyAccessor
dialogStateAccessor:StatePropertyAccessor
...
){
超级(遥测客户端);
[...]
this.use(new SkillMiddleware(conversationState, SkillContextAccessor, dialogStateAccessor));
[...]
}
}
谢谢,
爱德华
嗨@Edwardfelix08 ,对于答案的延迟表示歉意。
我们查看了将 V4 Bot 作为技能启用的
按照您的重现步骤,我们了解到您有一些关于您的虚拟助手的信息,您将这些信息保存在虚拟助手的SkillContext
中,当技能收到消息时,您希望从SkillContext
。 这样对吗?
嗨@dfavretto。
是的,它是正确的。
嗨@Edwardfelix08 ,我们一直在测试这个场景,并创建了一个关于如何使这个工作的指南。 考虑到示例助手尚未准备好在这种情况下开箱即用,因此我们提供了三个步骤来完成此操作所需的一些小修改:
首先,您必须将所需信息保存在技能上下文中,以便以后检索。 这必须在将您的消息转发到技能
在mainDialog 中,您必须使用SkillContextAccessor来检索与您的上下文对应的SkillContext 。 这可以通过以下几行来完成:
const sc: SkillContext = await this.skillContextAccessor.get(dc.context, new SkillContext());
const skillContext: SkillContext = Object.assign(new SkillContext(), sc);
现在您已将SkillContext保存在变量中,您可以获取或设置任何值。 不要忘记SkillContext中的值是一个键值对,因此如果您不想覆盖您的值,请确保您的键是唯一的。 现在您可以保存任何内容,即位置值:
skillContext.setObj('location', locationObj);
最后,设置使用skillContextAccessor您SkillContext所以这个信息被保存在您的userState:
await this.skillContextAccessor.set(dc.context, skillContext);
保存在SkillContext的信息后,它的优良将消息转发到技能,但在此之前的消息到达技能,在SkillDialog里面botbuilder-skills
期间将处理SkillContext onBeginDialog方法,这是唯一的一次是当执行首次调用该技能。
该方法将自动执行以下步骤:
第三步也是最后一步是使用从虚拟助手发送的信息填充技能状态,步骤如下:
typescript
if (semanticAction !== undefined && Object.keys(semanticAction.entities)
.find((key: string) => key === "location"))
希望这些步骤有用😊
嘿@lauren-mills 你能检查一下这种方法是否正确吗? 😁
谢谢@dfavretto会尝试看看它是否有效。
嗨@dfavretto我已经尝试了上述解决方案,但没有奏效。 我仍然看到“CustomSkillAdapter”类中没有更新或代码更改
@ Edwardfelix08你能不能跟我们分享什么是你所面临的问题? 此外,这里有一些指导性问题,可以更好地确定我们如何为您提供帮助:
SkillContext
中?SkillManifest
更新了必要的插槽?SkillContext
的信息的键匹配?populateStateFromSemanticAction
是不是没有注释掉?此外,关于CustomSkillAdapter
,对于这种情况,无需更改该类。
嗨@dfavretto ,
下面是使用的代码
你能设法在你的虚拟助手的 SkillContext 中保存信息吗?
VA 主对话框。
const sk: SkillContext = await this.skillContextAccessor.get(dc.context, new SkillContext());
const SkillContext: SkillContext = Object.assign(new SkillContext(), sk);
SkillContext.setObj('userState', userProfile);
等待 this.skillContextAccessor.set(dc.context, SkillContext);
您的技能清单是否更新了必要的插槽?
VA 中的 Skill.json
“插槽”:[{
"name": "userState",
“类型”:[“IUserState”]
}],
技能清单
“插槽”:[{
"name": "userState",
“类型”:[“IUserState”]
}],
Slot 的键是否与用于在 SkillContext 中保存信息的键匹配?
populateStateFromSemanticAction 中的代码
if (skillContext.ContainsKey('userState')) {
......
......
}
您的 Skill 中的 populateStateFromSemanticAction 方法是否未注释?
是的,我在 botSkill 中取消了代码表 populateStateFromSemanticAction 方法的注释。
我们应该使用的机器人框架版本是什么?
我们正在使用以下软件包。
"botbuilder": "^4.5.3",
"botbuilder-ai": "^4.5.3",
"botbuilder-applicationinsights": "^4.5.3",
"botbuilder-azure": "^4.5.3",
"botbuilder-core": "^4.5.3",
"botbuilder-dialogs": "^4.5.3",
"botbuilder-skills": "^4.4.6",
"botbuilder-solutions": "^4.4.6",
"botframework-config": "^4.5.3",
"botframework-connector": "^4.5.3",
"botframework-schema": "^4.5.3",
@Edwardfelix08 ,我看到您正试图从skillContext
方法中的populateStateFromSemanticAction
获取值userState
populateStateFromSemanticAction
。 我想指出的是,您在Virtual Assistant 中填写的skillContext
不再是您在Skill 中填写的那个。
为了利用这种情况,来自虚拟助手的skillContext
被复制到活动的semanticAction
。 Activity 是从Virtual Assistant发送到Skill的唯一元素,然后可以对其进行评估以获取此信息。
以下是populateStateFromSemanticAction
的示例,它将从活动的semanticAction
获取您的userState
值:
protected async populateStateFromSemanticAction(context: TurnContext): Promise<void> {
// Example of populating local state with data passed through semanticAction out of Activity
const activity: Activity = context.activity;
const semanticAction: SemanticAction | undefined = activity.semanticAction;
if (semanticAction !== undefined && Object.keys(semanticAction.entities).find((key: string) => key === "userState")) {
const userState: any = semanticAction.entities["userState"];
const userStateObj = userState.properties["userState"];
const state: SkillState = await this.stateAccessor.get(context, new SkillState());
state.userState = userStateObj !== undefined ? userStateObj : userState;
await this.stateAccessor.set(context, state);
}
}
@dfavretto抱歉回复晚了。
我已经尝试过同样的方法,但仍然无法获得价值。
activity.semanticAction
值未定义。
嗨@Edwardfelix08 ,我们进行了一些验证,但无法重现您的场景,因为SemanticAction
始终默认为某个值,因此不应未定义它。
只是为了确认,在您的虚拟助手中,您是否按以下方式调用您的技能?
@darrenj - 我们是否应该添加支持团队,以便他们可以从另一个角度帮助解决这个问题? 由于它似乎与 TypeScript 实现本身没有任何关系,但它是在此处实现的特定场景。
嗨@dfavretto ,
抱歉回复晚了。 我们能够让这个工作,谢谢你。 我们指的是框架的旧版本,一旦更新并与您的代码交叉检查,并且“populateStateFromSemanticAction”存在差异,将代码更新为建议的代码,它开始像魅力一样工作。
感谢您在这方面帮助我们。
听到这个真棒! 很高兴能帮到你😊
最有用的评论
听到这个真棒! 很高兴能帮到你😊