๋ง์ดํฌ๋ก์ํํธ ๋ดํ๋ ์์ํฌ V4, ์ปค์คํ ์คํฌ.
ํ์ดํ์คํฌ๋ฆฝํธ
Skill์ด SkillContext๋ฅผ ํตํด Virtual Assistant์์ ์ ๋ฌ๋ ์ ๋ณด๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
1๋จ๊ณ: " https://botbuilder.myget.org/feed/aitemplates/package/npm/botbuilder-solutions "๋ฅผ ์ฌ์ฉํ์ฌ VA ์์ฑ
2๋จ๊ณ: ์คํฌ ์์ฑ๊ธฐ ๋ช
๋ น์ ์ฌ์ฉํ์ฌ ์คํฌ ์์ฑ
" https://botbuilder.myget.org/feed/aitemplates/package/npm/botbuilder-skills "
3๋จ๊ณ: ์ฌ๋กฏ ๋งค๊ฐ๋ณ์๊ฐ ์๋ ์คํฌ ๋งค๋ํ์คํธ ํ์ผ ์ถ๊ฐ
4๋จ๊ณ: ์ฌ๋กฏ ๋งค๊ฐ๋ณ์ ๊ฐ์ผ๋ก SkillContext๋ฅผ ์ค์ ํฉ๋๋ค.
5๋จ๊ณ: Skill์์ SkillContext ๊ฐ์ ์ก์ธ์ค๋ฅผ ์๋ํฉ๋๋ค.
SkillContext์ ์ค์ ๋ ๊ฐ์ฒด๋ "slot" ์์ฑ์ด ์ผ์นํ๋ ๊ฒฝ์ฐ ๊ธฐ์ ์์ ์ก์ธ์คํ ์ ์์ด์ผ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ์คํฌ์ SkillContext๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
"SkillMiddleware"๋ SkillContextAccessor๋ฅผ ์ง์ํ๊ณ 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(์๋ก์ด SkillMiddleware(conversationState, SkillContextAccessor, dialogStateAccessor));
[...]
}
}
๊ฐ์ฌ ํด์,
์๋์๋
@Edwardfelix08๋ , ๋ต๋ณ์ด ๋ฆ์ด ์ฃ์กํฉ๋๋ค.
V4 Bot์ ๊ธฐ์ ๋ก ํ์ฑํํ๊ธฐ ์ํ ๋ฌธ์๋ฅผ ๊ฒํ ํ์ผ๋ฉฐ(๋ฌธ์ ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋จ, ์ด์ ๋งํฌ์์ 404๋ฅผ ๋ฐํํจ) ์ฝ๋์ ์ผ๋ถ ๋ณ๊ฒฝ ์ฌํญ์ ๋ฐ๋ผ ์ฌ๋ฐ๋ฅด๊ฒ ์
๋ฐ์ดํธ๋์ง ์์์์ ๊นจ๋ฌ์์ผ๋ฏ๋ก ํด๋น ๋ฌธ์๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
์ฌํ ๋จ๊ณ์ ๋ฐ๋ผ ๊ฐ์ ๋์ฐ๋ฏธ์ ๋ํ ์ผ๋ถ ์ ๋ณด๊ฐ ์๊ณ ์ด ์ ๋ณด๋ฅผ ๊ฐ์ ๋์ฐ๋ฏธ์ SkillContext
์ ์ ์ฅํ๊ณ Skill์ด ๋ฉ์์ง๋ฅผ ์์ ํ ๋ ์ด ์ ๋ณด๋ฅผ ๊ฒ์ํ๊ธฐ๋ฅผ ์ํ๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค. SkillContext
. ์ด ์ฌ๋ฐ๋ฅธ์ง?
์๋
ํ์ธ์ @dfavretto์
๋๋ค.
๋ค ๋ง์ต๋๋ค.
@Edwardfelix08๋ , ์๋ ํ์ธ์, ์ฐ๋ฆฌ๋ ์ด ์๋๋ฆฌ์ค๋ฅผ ํ ์คํธํ์ผ๋ฉฐ ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๊ฐ์ด๋๋ฅผ ๋ง๋ค์์ต๋๋ค. ๊ฒ์ ๊ณ ๋ ค ์ํ ๋น์๊ฐ ์ฐ๋ฆฌ๊ฐ ์ด๋ฌํ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๊ธฐ ์ํด ํ์ํ ๋ช ๊ฐ์ง ์ฌ์ํ ์์ ์ผ๋ก ์ธ ๋จ๊ณ๋ฅผ ์ ๊ณตํ๊ณ , ๊ทธ๋์ ์ค๋น๊ฐ ์์ - ์ค๋ธ - ๋ฐ์ค ์ฌ์ฉ์์ด ์๋๋ฆฌ์ค๊ฐ๋์ง ์์ต๋๋ค :
๋จผ์ ์ํ๋ ์ ๋ณด๋ฅผ ๋์ค์ ๊ฒ์ํ๊ธฐ ์ํด ์ ์ฅ ํด์ผ ํฉ๋๋ค. ๋ฉ์์ง๋ฅผ Skill์ ์ ๋ฌ ํ๊ธฐ ์ ์ ์ด ์์ ์ ์ํํด์ผ ํฉ๋๋ค. ๋ฐ๋ก ์ง์ ์ ํ ํ์๋ ์์ต๋๋ค. ์ด ์ ๋ณด๋ ๋ค๋ฅธ ๋จ๊ณ์์ ์ ์ฅ๋ ์ ์์ต๋๋ค.
๋ด๋ถ 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);
์ด ์ ๋ณด๊ฐ userState์ ์ ์ฅ๋๋๋ก ๋ง์ง๋ง์ผ๋ก, skillContextAccessor๋ฅผ ์ฌ์ฉํ์ฌ SkillContext์ ์ค์ ํฉ๋๋ค :
awaitย this.skillContextAccessor.set(dc.context,ย skillContext);
SkillContext์ ์ ๋ณด๋ฅผ ์ ์ฅ ํ ํ, ๊ทธ๊ฒ์ ๋ฒ๊ธ ์คํฌ์ ๋ฉ์์ง๋ฅผ ์ ๋ฌ ๋งํ๋ ๋ฉ์์ง๋ ์คํฌ์์ ๋๋ฌํ๊ธฐ ์ ์ SkillDialog ๋ด๋ถ botbuilder-skills
๋์ SkillContext์ ์ฒ๋ฆฌ ํ onBeginDialog ๋ฐฉ๋ฒ ์๋ง ํ ๋ฒ ์คํ๋ฉ๋๋ค, ์คํฌ์ด ์ฒ์์ผ๋ก ํธ์ถ๋ฉ๋๋ค.
์ด ๋ฐฉ๋ฒ์ ์๋์ผ๋ก ๋ค์ ๋จ๊ณ๋ฅผ ์ํํฉ๋๋ค.
์ธ ๋ฒ์งธ์ด์ ๋ง์ง๋ง ๋จ๊ณ๋ ๋ค์ ๋จ๊ณ์ ๋ฐ๋ผ ๊ฐ์ ๋์ฐ๋ฏธ์์ ๋ณด๋ธ ์ ๋ณด๋ก SkillState ๋ฅผ ์ฑ์ฐ๋ ๊ฒ์ ๋๋ค.
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 ,
์๋๋ ์ฌ์ฉํ ์ฝ๋
Virtual Assistant์ SkillContext์ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์์ต๋๊น?
VA ๋ฉ์ธ ๋ค์ด์ผ๋ก๊ทธ.
const sk: SkillContext = this.skillContextAccessor.get(dc.context, new SkillContext())์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
const ๊ธฐ์ ์ปจํ
์คํธ: SkillContext = Object.assign(new SkillContext(), sk);
SkillContext.setObj('userState', userProfile);
this.skillContextAccessor.set(dc.context, SkillContext)๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
SkillManifest๊ฐ ํ์ํ ์ฌ๋กฏ์ผ๋ก ์
๋ฐ์ดํธ๋์์ต๋๊น?
๋ฒ์ง๋์์ Skill.json
"์ฌ๋กฏ": [{
"์ด๋ฆ": "์ฌ์ฉ์ ์ํ",
"์ ํ": ["IUserState"]
}],
์คํฌ๋งค๋ํ์คํธ
"์ฌ๋กฏ": [{
"์ด๋ฆ": "์ฌ์ฉ์ ์ํ",
"์ ํ": ["IUserState"]
}],
์ฌ๋กฏ์ ํค๊ฐ 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 , populateStateFromSemanticAction
๋ฉ์๋์ skillContext
์์ userState
๊ฐ์ ์ป์ผ๋ ค๊ณ ํฉ๋๋ค. Virtual Assistant์ ๊ธฐ์
ํ skillContext
๋ ๋ ์ด์ Skill ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ง ์์ต๋๋ค.
์ด ์ํฉ์ ํ์ฉํ๊ธฐ ์ํด Virtual Assistant์ skillContext
๊ฐ ํ๋์ semanticAction
๋ณต์ฌ๋ฉ๋๋ค. Activity๋ Virtual Assistant ์์ Skill๋ก ์ ์ก๋๋ ์ ์ผํ ์์์ด๋ฉฐ ์ด ์ ๋ณด๋ฅผ ์ป๊ธฐ ์ํด ํ๊ฐํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์์
๋๋ค populateStateFromSemanticAction
๋น์ ์ป์ ๊ฒ์ด๋ค userState
ํ๋์์์ ๊ฐ semanticAction
:
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"์ ์ฐจ์ด๊ฐ ์์๊ณ ์ ์๋ ์ฝ๋๋ก ์ฝ๋๋ฅผ ์
๋ฐ์ดํธํ๊ณ ๋งค๋ ฅ์ฒ๋ผ ์๋ํ๊ธฐ ์์ํ์ต๋๋ค.
๋์์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
๊ทธ ๋ง์ ๋ค์ผ๋ ๋๋จํด! ๋์์ด ๋ ์ ์์ด์ ๊ธฐ์ฉ๋๋ค ๐
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ทธ ๋ง์ ๋ค์ผ๋ ๋๋จํด! ๋์์ด ๋ ์ ์์ด์ ๊ธฐ์ฉ๋๋ค ๐