简体   繁体   中英

Alexa ask a question and get response from external API

I have set up a simple intent

 { "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": [] } } } 

But when I ask a question it gives me a generic error response like this:

Me: alexa ask viva bank when is the late fee charged

Alexa: Sorry, I don't know that.

Here is my lambda code, but I don't think it is getting that far.

 '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(); }; 

I'm really just looking to create a very simple pass through, where a question is asked to Alexa, and then I pipe that to an external API and have Alexa read the response.

You can make the question slot value as required if it is mandatory for the intent and you need to include the intent name. You can use async/await to handle the 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");
      });
  });
};

In AskIntentHandler you should set your "canHandle" to the name of the intent like so in addition to checking the question slot.

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
  }
}

Also if "question" is always required to run the intent, you can set up a dialog so Alexa will ask the user for "question" if she doesn't recognize one.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM