Alexa Decision Tree Skill не достигает ответа в тестовом окружении.после заполнения всех необходимых слотов намерений, несмотря на то, что dialogState достигнет ЗАВЕРШЕНО - PullRequest
0 голосов
/ 18 июня 2019

Я делаю навык на основе Навыка дерева решений от разработчиков 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, как и следовало ожидать.

...