Alexa задает вопрос и получает ответ от внешнего API - PullRequest
11 голосов
/ 26 апреля 2019

Я настроил простое намерение

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "viva bank",
      "intents": [
        ...builtin intents...{
          "name": "ask",
          "slots": [{
            "name": "question",
            "type": "AMAZON.SearchQuery"
          }],
          "samples": [
            "when {question}",
            "how to {question}",
            "what {question}"
          ]
        }
      ],
      "types": []
    }
  }
}

Но когда я задаю вопрос, он дает мне общий ответ об ошибке, подобный этому:

Я: Алекса, спрашивай у вива банка, когда взимается штраф за просрочку

Алекса: Извините, я этого не знаю.

Вот мой лямбда-код, но я не думаю, что он зашёл так далеко.

'use strict';

const Alexa = require('ask-sdk-core');
var https = require('https');
var querystring = require('querystring');


const APP_ID = 'amzn1.ask.skill.1234';

const AskIntentHandler = {
  canHandle(handlerInput) {
    return !!handlerInput.requestEnvelope.request.intent.slots['question'].value;
  },
  handle(handlerInput) {
    var question = handlerInput.requestEnvelope.request.intent.slots['question'].value;
    console.log('mydata:', question);
    var responseString = '';
    const subscription_key = 'XXXX';

    var data = {
      simplequery: question,
      channel: 'Alexa'
    };
    var get_options = {
      headers: {
        'Subscription-Key': subscription_key
      }
    };

    https.get('https://fakeapi.com/' + querystring.stringify(data), get_options, (res) => {
      console.log('statusCode:', res.statusCode);
      console.log('headers:', res.headers);

      res.on('data', (d) => {
        responseString += d;
      });

      res.on('end', function(res) {
        var json_hash = JSON.parse(responseString);
        // grab the first answer returned as text and have Alexa read it
        const speechOutput = json_hash['results'][0]['content']['text'];
        console.log('==> Answering: ', speechOutput);
        // speak the output
        return handlerInput.responseBuilder.speak(speechOutput).getResponse();
      });
    }).on('error', (e) => {
      console.error(e);
      return handlerInput.responseBuilder.speak("I'm sorry I ran into an error").getResponse();
    });
  }

};

exports.handler = (event, context) => {
  const alexa = Alexa.handler(event, context);
  alexa.APP_ID = APP_ID;
  alexa.registerHandlers(AskIntentHandler);
  alexa.execute();
};

Я просто хочу создать очень простой проход, в котором Алексе задают вопрос, а затем я передаю его на внешний API, и Алекса читает ответ.

Ответы [ 2 ]

0 голосов
/ 01 июня 2019

Вы можете указать значение слота вопроса, если это необходимо для намерения, и вам необходимо указать имя намерения.Вы можете использовать async / await для обработки API.

const Alexa = require('ask-sdk-core');
const https = require('https');
const querystring = require('querystring');
const { getSlotValue } = Alexa;

const APP_ID = 'amzn1.ask.skill.1234';

const AskIntentHandler = {
  canHandle(handlerInput) {
    return (
      handlerInput.requestEnvelope.request.type === "IntentRequest" &&
      handlerInput.requestEnvelope.request.intent.name === "AskIntent"
    );
  },
  async handle(handlerInput) {
    const question = getSlotValue(handlerInput.requestEnvelope, "question");
    console.log("question ", question);
    const data = await getAnswer(question);
    const speechText = data;
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(speechText)
      .getResponse();
  }
};

const getAnswer = question => {
  const subscription_key = "XXXX";
  let data = {
    simplequery: question,
    channel: "Alexa"
  };
  let get_options = {
    headers: {
      "Subscription-Key": subscription_key
    }
  };
  return new Promise((resolve, reject) => {
    https
      .get(
        "https://fakeapi.com/" + querystring.stringify(data),
        get_options,
        res => {
          console.log("statusCode:", res.statusCode);
          console.log("headers:", res.headers);
          res.on("data", d => {
            responseString += d;
          });

          res.on("end", function(res) {
            var json_hash = JSON.parse(responseString);
            // grab the first answer returned as text and have Alexa read it
            const speechOutput = json_hash["results"][0]["content"]["text"];
            console.log("==> Answering: ", speechOutput);
            resolve(speechOutput);
          });
        }
      )
      .on("error", e => {
        console.error(e);
        resolve("I'm sorry I ran into an error");
      });
  });
};
0 голосов
/ 06 мая 2019

В AskIntentHandler вы должны установить свой «canHandle» на имя намерения, например, в дополнение к проверке слота вопроса.

const AskIntentHandler = {
  canHandle (handlerInput) {
  return handlerInput.requestEnvelope.request.type === 'IntentRequest' &&
      handlerInput.requestEnvelope.request.intent.name === 'AskIntent' &&
      !!handlerInput.requestEnvelope.request.intent.slots['question'].value
  },
  handle (handlerInput) {
     // API Request Here
  }
}

Также, если «вопрос» всегда требуется для запуска намерения,Вы можете настроить диалог, чтобы Alexa спросила пользователя о «вопросе», если он его не распознает.

https://developer.amazon.com/docs/custom-skills/delegate-dialog-to-alexa.html

...