Skip to content

Instantly share code, notes, and snippets.

@germanviscuso
Last active October 17, 2018 12:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save germanviscuso/f73099b99021299aceafd2756688db0b to your computer and use it in GitHub Desktop.
Save germanviscuso/f73099b99021299aceafd2756688db0b to your computer and use it in GitHub Desktop.
Alexa Skills Basics: Recommendation Intent
{
"interactionModel": {
"languageModel": {
"invocationName": "busca camisetas",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "RecommendationIntent",
"slots": [
{
"name": "color",
"type": "tipoColor",
"samples": [
"{quiero} color {color}",
"color {color}",
"{quiero} {color}",
"{color}"
]
},
{
"name": "talla",
"type": "tipoTalla",
"samples": [
"{quiero} talla {talla}",
"{quiero} tamaño {talla}",
"{quiero} {talla}",
"{talla}",
"talla {talla}",
"tamaño {talla}",
"{talla}",
"de talla {talla}",
"de tamaño {talla}"
]
},
{
"name": "marca",
"type": "tipoMarca"
},
{
"name": "precio",
"type": "tipoPrecio"
},
{
"name": "quiero",
"type": "tipoQuiero"
},
{
"name": "camiseta",
"type": "tipoCamiseta"
},
{
"name": "un",
"type": "tipoArticulo"
},
{
"name": "conector",
"type": "tipoConector"
}
],
"samples": [
"{un} {camiseta}",
"{quiero} {un} {camiseta} {color}",
"{quiero} {un} {camiseta} {precio}",
"{quiero} {un} {camiseta} marca {marca}",
"{quiero} {un} {camiseta}",
"{quiero} {un} {camiseta} {color} de talla {talla}",
"{quiero} {camiseta} {color}",
"{quiero} {camiseta} {precio}",
"{quiero} {camiseta} marca {marca}",
"{quiero} marca {marca}",
"{quiero} {un} {marca}",
"{quiero} {camiseta}",
"{quiero} {camiseta} {color} de talla {talla}",
"{quiero} {color} de talla {talla}",
"{quiero} {color} y talla {talla}",
"{quiero} {un} {camiseta} {talla} de color {color}",
"{quiero} {talla} de color {color}",
"{quiero} {un} {camiseta} {color} de talla {talla} y {precio}",
"{quiero} talla {talla} marca {marca} color {color}",
"{quiero} talla {talla}",
"talla {talla}",
"talla {talla} color {color}",
"color {color}",
"color {color} talla {talla}",
"{quiero} {un} {color}",
"{quiero} {talla}",
"{quiero} {color}",
"{quiero} {color} {talla} {precio} marca {marca}",
"{color} {talla} {precio} marca {marca}",
"{quiero} {talla} {color} {precio} marca {marca}",
"{talla} {color} {precio} marca {marca}",
"{quiero} {precio} {talla} {color} marca {marca}",
"{precio} {talla} {color} marca {marca}",
"{quiero} {color} {talla} {precio} {conector} marca {marca}",
"{color} {talla} {precio} {conector} marca {marca}",
"{quiero} {talla} {color} {precio} {conector} marca {marca}",
"{talla} {color} {precio} {conector} marca {marca}",
"{quiero} {precio} {talla} {color} {conector} marca {marca}",
"{precio} {talla} {color} {conector} marca {marca}",
"{color} {talla} {precio} {conector} marca {marca}",
"{talla} {color} {precio} {conector} marca {marca}",
"{quiero} {precio} {talla} {color} {conector} marca {marca}",
"{precio} {talla} {color} {conector} marca {marca}",
"{quiero} {un} color {color} talla {talla} marca {marca} {conector} precio {precio}",
"{quiero} {un} talla {talla} color {color} marca {marca} {conector} precio {precio}",
"{quiero} {un} marca {marca} color {color} talla {talla} {conector} precio {precio}"
]
}
],
"types": [
{
"name": "tipoPrecio",
"values": [
{
"name": {
"value": "caro",
"synonyms": [
"de lujo",
"caras",
"costosas",
"cara"
]
}
},
{
"name": {
"value": "intermedio",
"synonyms": [
"promedio",
"termino medio",
"de precio normal"
]
}
},
{
"name": {
"value": "barato",
"synonyms": [
"asequibles",
"baratas",
"barata"
]
}
}
]
},
{
"name": "tipoMarca",
"values": [
{
"name": {
"value": "adidas"
}
},
{
"name": {
"value": "puma"
}
},
{
"name": {
"value": "ralph lauren"
}
},
{
"name": {
"value": "tommy hilfiger"
}
},
{
"name": {
"value": "gap"
}
},
{
"name": {
"value": "lacoste"
}
}
]
},
{
"name": "tipoTalla",
"values": [
{
"name": {
"value": "xxl",
"synonyms": [
"gigante",
"super grande"
]
}
},
{
"name": {
"value": "xl",
"synonyms": [
"amplia",
"extra grande"
]
}
},
{
"name": {
"value": "l",
"synonyms": [
"grande"
]
}
},
{
"name": {
"value": "m",
"synonyms": [
"intermedia",
"mediano",
"mediana",
"medio",
"media"
]
}
},
{
"name": {
"value": "s",
"synonyms": [
"pequeño",
"pequeña"
]
}
},
{
"name": {
"value": "xs",
"synonyms": [
"muy pequeño",
"muy pequeña",
"pequeñita",
"diminuta"
]
}
}
]
},
{
"name": "tipoQuiero",
"values": [
{
"name": {
"value": "recomiéndame"
}
},
{
"name": {
"value": "busco"
}
},
{
"name": {
"value": "quisiera"
}
},
{
"name": {
"value": "búscame"
}
},
{
"name": {
"value": "busca"
}
},
{
"name": {
"value": "queremos"
}
},
{
"name": {
"value": "me gusta"
}
},
{
"name": {
"value": "me gustaría"
}
},
{
"name": {
"value": "quisiera"
}
},
{
"name": {
"value": "quiero"
}
},
{
"name": {
"value": "me va"
}
},
{
"name": {
"value": "me vale"
}
}
]
},
{
"name": "tipoCamiseta",
"values": [
{
"name": {
"value": "camisa"
}
},
{
"name": {
"value": "camiseta"
}
},
{
"name": {
"value": "camisetas"
}
}
]
},
{
"name": "tipoArticulo",
"values": [
{
"name": {
"value": "los"
}
},
{
"name": {
"value": "el"
}
},
{
"name": {
"value": "las"
}
},
{
"name": {
"value": "la"
}
},
{
"name": {
"value": "unas"
}
},
{
"name": {
"value": "unos"
}
},
{
"name": {
"value": "una"
}
},
{
"name": {
"value": "un"
}
}
]
},
{
"name": "tipoColor",
"values": [
{
"name": {
"value": "rosa",
"synonyms": [
"rosadas",
"rosados",
"rosada",
"rosado",
"rosas"
]
}
},
{
"name": {
"value": "marrón",
"synonyms": [
"marrones"
]
}
},
{
"name": {
"value": "blanco",
"synonyms": [
"blancas",
"blanca"
]
}
},
{
"name": {
"value": "negro",
"synonyms": [
"negras",
"negra"
]
}
},
{
"name": {
"value": "verde"
}
},
{
"name": {
"value": "amarillo",
"synonyms": [
"amarillas",
"amarilla"
]
}
},
{
"name": {
"value": "azul",
"synonyms": [
"azules",
"azulada"
]
}
},
{
"name": {
"value": "rojo",
"synonyms": [
"rojas",
"colorada",
"roja"
]
}
}
]
},
{
"name": "tipoConector",
"values": [
{
"name": {
"value": "y de"
}
},
{
"name": {
"value": "y"
}
}
]
}
]
},
"dialog": {
"intents": [
{
"name": "RecommendationIntent",
"confirmationRequired": true,
"prompts": {
"confirmation": "Confirm.Intent.181259956199"
},
"slots": [
{
"name": "color",
"type": "tipoColor",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.1292632413709.1011723684445"
}
},
{
"name": "talla",
"type": "tipoTalla",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.1292632413709.537210718424"
}
},
{
"name": "marca",
"type": "tipoMarca",
"confirmationRequired": false,
"elicitationRequired": false,
"prompts": {}
},
{
"name": "precio",
"type": "tipoPrecio",
"confirmationRequired": false,
"elicitationRequired": false,
"prompts": {}
},
{
"name": "quiero",
"type": "tipoQuiero",
"confirmationRequired": false,
"elicitationRequired": false,
"prompts": {}
},
{
"name": "camiseta",
"type": "tipoCamiseta",
"confirmationRequired": false,
"elicitationRequired": false,
"prompts": {}
},
{
"name": "un",
"type": "tipoArticulo",
"confirmationRequired": false,
"elicitationRequired": false,
"prompts": {}
}
]
}
]
},
"prompts": [
{
"id": "Confirm.Intent.181259956199",
"variations": [
{
"type": "PlainText",
"value": "¿Entonces buscamos color {color} , talla {talla} , precio {precio} y marca {marca} ?"
},
{
"type": "PlainText",
"value": "¿Entonces buscamos color {color} , talla {talla} y marca {marca} ?"
},
{
"type": "PlainText",
"value": "¿Entonces buscamos color {color} , talla {talla} y precio {precio} ?"
},
{
"type": "PlainText",
"value": "¿Entonces buscamos color {color} y talla {talla} ?"
},
{
"type": "PlainText",
"value": "¿Estás seguro?"
}
]
},
{
"id": "Elicit.Slot.1292632413709.537210718424",
"variations": [
{
"type": "PlainText",
"value": "Vale. color {color} , pero porfi dime la talla"
},
{
"type": "PlainText",
"value": "Debes indicarme una talla para continuar"
}
]
},
{
"id": "Elicit.Slot.1292632413709.1011723684445",
"variations": [
{
"type": "PlainText",
"value": "Dime ahora de que color la prefieres"
},
{
"type": "PlainText",
"value": "Vale. talla {talla}, pero porfi dime el color"
}
]
}
]
}
}
// Lambda Function code for Alexa.
// Paste this into your index.js file.
const Alexa = require("ask-sdk");
const LaunchRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest';
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let speechOutput = '¡Hola y bienvenido a busca camisetas! Puedo recomendarte camisetas en base a una talla y color. Por ejemplo, puedes pedirme que te recomiende una camiseta roja de talla grande';
return responseBuilder
.speak(speechOutput)
.reprompt('prueba otra vez, ' + speechOutput)
.getResponse();
},
};
const CancelStopIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
(request.intent.name === 'AMAZON.CancelIntent'|| request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let speechOutput = 'Vale. ¡Hasta luego! ';
return responseBuilder
.speak(speechOutput)
.withShouldEndSession(true)
.getResponse();
},
};
const HelpIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.HelpIntent' ;
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let speechOutput = 'Puedo recomendarte camisetas en base a una talla y color. Por ejemplo, puedes pedirme que te recomiende una camiseta roja de talla grande';
return responseBuilder
.speak(speechOutput)
.reprompt('preuba otra vez, ' + speechOutput)
.getResponse();
},
};
const NavigateHomeIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.NavigateHomeIntent' ;
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let speechOutput = 'Navegar a caso no está implementado. ';
return responseBuilder
.speak(speechOutput)
.reprompt('prueba otra vez, ' + speechOutput)
.getResponse();
},
};
const InProgressRecommendationIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'RecommendationIntent'
&& request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
const intent = request.intent;
return responseBuilder
.addDelegateDirective(intent)
.getResponse();
},
};
const CompletedRecommendationIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'RecommendationIntent';
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
const intent = request.intent;
let speechOutput = 'I didn\'t catch your confirmation';
if(intent.confirmationStatus === 'DENIED') {
speechOutput = 'Vale. ¡Cancelamos y volvemos a empezar!';
return responseBuilder
.speak(speechOutput)
.reprompt('¿Qué tipo de camiseta quieres?')
.getResponse();
}
speechOutput = 'Buscando... ';
let data = [
{ id: 1, producto: 'camiseta de elastano para corredores', marca: 'puma', precio: 'intermedio', color: ['negro', 'blanco', 'rojo'], talla: ['xs', 's', 'm', 'l'] },
{ id: 2, producto: 'camiseta casual urbana', marca: 'adidas', precio: 'barato', color: ['verde', 'azul'], talla: ['m', 'l', 'xl', 'xxl'] }
];
let slotValues = getSlotValues(request.intent.slots);
// getSlotValues returns .heardAs, .resolved, and .isValidated for each slot, according to request slot status codes ER_SUCCESS_MATCH, ER_SUCCESS_NO_MATCH, or traditional simple request slot without resolutions
let color = slotValues.color.resolved;
let talla = slotValues.talla.resolved;
let precio = slotValues.precio.resolved;
let marca = slotValues.marca.resolved;
var filteredArray = data.filter(el=> {
let condition = el.color.some(e => {
return color == e;
});
condition = condition && el.talla.some(e => {
return talla == e;
});
if(precio)
condition = condition && el.precio == precio;
if(marca)
condition = condition && el.marca == marca;
return condition
});
if(filteredArray.length == 0)
speechOutput += '¡Vaya! No he encontrado ninguna camiseta con esas características. Por favor realiza otra búsqueda';
else {
speechOutput += '!He encontrado lo que buscabas! '
+ filteredArray[0].producto + ' de marca ' + filteredArray[0].marca + ' con un precio ' + filteredArray[0].precio
+ ', disponible en tallas ' + filteredArray[0].talla + ' y colores ' + filteredArray[0].color;
speechOutput += ' . Puedes realizar otra búsqueda o terminar diciendo para'
}
return responseBuilder
.speak(speechOutput)
.reprompt('prueba otra vez, ' + speechOutput)
.getResponse();
}
};
const SessionEndedHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);
return handlerInput.responseBuilder.getResponse();
}
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
const request = handlerInput.requestEnvelope.request;
console.log(`Error handled: ${error.message}`);
// console.log(`Original Request was: ${JSON.stringify(request, null, 2)}`);
return handlerInput.responseBuilder
.speak(`Perdona. Ha ocurrido un error. ${error.message} `)
.reprompt(`Perdona. Ha ocurrido un error. ${error.message} `)
.getResponse();
}
};
function randomElement(myArray) {
return(myArray[Math.floor(Math.random() * myArray.length)]);
}
function getSlotValues(filledSlots) {
const slotValues = {};
Object.keys(filledSlots).forEach((item) => {
const name = filledSlots[item].name;
if (filledSlots[item] &&
filledSlots[item].resolutions &&
filledSlots[item].resolutions.resolutionsPerAuthority[0] &&
filledSlots[item].resolutions.resolutionsPerAuthority[0].status &&
filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code) {
switch (filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code) {
case 'ER_SUCCESS_MATCH':
slotValues[name] = {
heardAs: filledSlots[item].value,
resolved: filledSlots[item].resolutions.resolutionsPerAuthority[0].values[0].value.name,
ERstatus: 'ER_SUCCESS_MATCH'
};
break;
case 'ER_SUCCESS_NO_MATCH':
slotValues[name] = {
heardAs: filledSlots[item].value,
resolved: '',
ERstatus: 'ER_SUCCESS_NO_MATCH'
};
break;
default:
break;
}
} else {
slotValues[name] = {
heardAs: filledSlots[item].value || '', // may be null
resolved: '',
ERstatus: ''
};
}
}, this);
return slotValues;
}
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
CancelStopIntentHandler,
HelpIntentHandler,
NavigateHomeIntentHandler,
InProgressRecommendationIntentHandler,
CompletedRecommendationIntentHandler,
LaunchRequestHandler,
SessionEndedHandler
)
.addErrorHandlers(ErrorHandler)
.lambda();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment