Я делаю навык на основе Навыка дерева решений от разработчиков Amazon. В большинстве случаев это просто изменение карты и массива параметров slotsToOptions, речевого вывода и изменение диалоговой модели Alexa в соответствии с его требованиями, но неожиданно конечное состояние не достигается после заполнения моего последнего обязательного слота намерения. Мои входные данные соответствуют целевым слотам, как и предполагалось, и dialogState достигает завершенного.
Я попытался изменить количество необходимых слотов намерений, чтобы увидеть, заканчивается ли диалог одним слотом, но получаю ту же строку «Извините, я не понимаю».
Входной JSON:
{
},
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.dee28b7f-fa01-4603-924e-0a718e92a1a7",
"timestamp": "2019-06-18T19:51:56Z",
"locale": "en-US",
"intent": {
"name": "RecommendationIntent",
"confirmationStatus": "NONE",
"slots": {
"Design": {
"name": "Design",
"value": "led",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.04a2dc83-565b-418a-bca8-50366ef9b69c.designType",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "LED",
"id": "53e0dbc06e48e3d381ac224fa8bae3df"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
},
"ContributingFactor": {
"name": "ContributingFactor",
"value": "cost",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.04a2dc83-565b-418a-bca8-50366ef9b69c.ContributingFactorType",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "Cost",
"id": "20b4f77bd00b4f63a49ec8e08f3bf6a6"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
}
},
"dialogState": "COMPLETED"
}
}
фрагменты index.js в Lambda (карты и обработчики РекомендацииИнтента)
const InProgressRecommendationIntent = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'RecommendationIntent'
&& request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
const currentIntent = handlerInput.requestEnvelope.request.intent;
let prompt = '';
for (const slotName of Object.keys(handlerInput.requestEnvelope.request.intent.slots)) {
const currentSlot = currentIntent.slots[slotName];
if (currentSlot.confirmationStatus !== 'CONFIRMED'
&& currentSlot.resolutions
&& currentSlot.resolutions.resolutionsPerAuthority[0]) {
if (currentSlot.resolutions.resolutionsPerAuthority[0].status.code === 'ER_SUCCESS_MATCH') {
if (currentSlot.resolutions.resolutionsPerAuthority[0].values.length > 1) {
prompt = 'Which would you like';
const size = currentSlot.resolutions.resolutionsPerAuthority[0].values.length;
currentSlot.resolutions.resolutionsPerAuthority[0].values
.forEach((element, index) => {
prompt += ` ${(index === size - 1) ? ' or' : ' '} ${element.value.name}`;
});
prompt += '?';
return handlerInput.responseBuilder
.speak(prompt)
.reprompt(prompt)
.addElicitSlotDirective(currentSlot.name)
.getResponse();
}
} else if (currentSlot.resolutions.resolutionsPerAuthority[0].status.code === 'ER_SUCCESS_NO_MATCH') {
if (requiredSlots.indexOf(currentSlot.name) > -1) {
prompt = `What ${currentSlot.name} are you looking for`;
return handlerInput.responseBuilder
.speak(prompt)
.reprompt(prompt)
.addElicitSlotDirective(currentSlot.name)
.getResponse();
}
}
}
}
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
},
};
const CompletedRecommendationIntent = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'RecommendationIntent'
&& request.dialogState === 'COMPLETED';
},
handle(handlerInput) {
const filledSlots = handlerInput.requestEnvelope.request.intent.slots;
const slotValues = getSlotValues(filledSlots);
const key = `${slotValues.Design.resolved}-${slotValues.contributingFactor.resolved}`;
const material = options[slotsToOptionsMap[key]];
const speechOutput =
`You want a/an ${slotValues.Design.resolved} circuit and your contributing factor is ${slotValues.contributingFactor.resolved}. You should consider using ${material.name} as your material`;
return handlerInput.responseBuilder
.speak(speechOutput)
.getResponse();
},
};
const slotsToOptionsMap = {
'RF-Performance': 0,
'LED-Performance': 1,
'Digital-Performance': 2,
'Hybrid-Performance': 3,
'RF-Cost': 4,
'LED-Cost': 5,
'Digital-Cost': 6,
'Hybrid-Cost': 7
};
const options = [
{ name: 'rp', description: ''},
{ name: 'lp', description: ''},
{ name: 'dp', description: ''},
{ name: 'hp', description: ''},
{ name: 'rc', description: ''},
{ name: 'lc', description: ''},
{ name: 'dc', description: ''},
{ name: 'hc', description: ''}
];
Я получаю эту строку в журнале, когда запускаю console.log (error.trace) в обработчике ошибок:
2019-06-18T19:51:56.339Z 5b28750f-6084-4fb7-ac04-9b6a892e5ab6 Error handled: Cannot read property 'resolved' of undefined
Я ожидаю, что в результате Alexa выведет материал из сопоставления. Никакие реальные материалы не отображаются, но в нем должно быть сказано: «Если вы хотите использовать [тип] схему, а [производительность или стоимость] является вашим фактором, вы должны использовать [материал]». Если я скажу RF и Cost как мой тип и способствующий фактор, я должен получить «rc» в качестве материала. Вместо этого единственное сообщение после заполнения последнего слота: «Извините, я не понимаю команду». Нужно ли добавлять код для управления значением shouldEndSession или чем-то другим? Оригинальный код выполнил все правильные запросы. В выводе JSON при достижении «Извините, я не понимаю», следует, если значение EndSession равно false, как и следовало ожидать.