alexa / alexa-skills-kit-sdk-for-nodejs

The Alexa Skills Kit SDK for Node.js helps you get a skill up and running quickly, letting you focus on skill logic instead of boilerplate code.
Apache License 2.0
3.12k stars 736 forks source link

Possible to access slots after emitWithState-ing from one intent to another? #250

Closed bdelee-zz closed 6 years ago

bdelee-zz commented 6 years ago

I am developing a relatively complex skill, and one piece of functionality that would make my life a lot easier would be the ability to use the Dialog.Directives after calling a different state with emitWithState. Currently, when I am in one intent, and plan on moving over to another intent in a different state to continue the flow of logic, the requesting intent doesn't get updated to the new intent, and so it doesn't think that the slots I am eliciting exist.

For example, say I am in intentOne inside stateOne, and at the end of it, I change state to stateTwo and emitWithState to intentTwo, which is handled inside of stateTwo. I then try to emit(':elicitSlot', 'num', ...) to fill in the value for slot "num." However, looking at the logged requests and responses, the skill still seems to think that I am back inside intentOne/stateOne, which doesn't have a slot called "num" and therefore tells me:

"error": { "type": "INVALID_RESPONSE", "message": "A valid slot of the intent being processed should be specified for slotToElicit in \"Dialog.ElicitSlot\" directive" }

And if I log the this.event.request.intent object after emitWithState-ing, the intent still reads as intentOne.

As far as I know, this is happening because when an intent is emitted from the code rather than by voice, it there isn't an update called from the interaction model. I may be way off on that though. Is there a way to 'refresh' the request to include the information(slots to be filled, specifically) for the current intent from the interaction model without having to call an actual emit?

bdelee-zz commented 6 years ago

Here is a feature request from the ASK forums that matches what I am saying

I'm surprised there aren't more people asking for this or calling it an issue.

tianrenz commented 6 years ago

Hi @bdelee,

Intent forwarding or emitWithState is a SDK feature that's intended to allow developers handle the same request with different handler functions. By design, it is not supposed to change any thing in the incoming request event. The reason behind is simple: from SDK perspective, any request send from Alexa service is immutable. The only way user interact with Alexa service is through response.

Regards, Tianren

bdelee-zz commented 6 years ago

Thanks for the reply, @Amazon-tianrenz

Is there any possibility/plan to create a way to "refresh" the request/response based on the new intent and therefore have access to the slots associated with it? I understand that this would take a change on both the SDK and the Alexa service side. I am imagining a function that has a sort of call and response without actually emitting any speech or taking input from a user.

For example, say IntentOne has SlotOne and SlotTwo and IntentTwo has SlotThree, and we emit('IntentTwo'). If we try to do anything related to SlotThree, the skill will fail, because it is not included in the request. Ideally, we'd have a way to refresh the request based on a new intent, something like emit(':updateIntent', 'IntentTwo') which would give us a new request with IntentTwo, and more importantly, SlotThree visible to the lambda code, while also calling an emit on the IntentTwo itself. Sort of like an emit or emitWithState, but there is a call and response with the Alexa service as well that happens without the knowledge of the user.

tianrenz commented 6 years ago

Hi @bdelee,

Maybe the skill messaging service API could help here.

bdelee-zz commented 6 years ago

I think I am missing something, but I'm not sure how the skill messaging API gets me what I need. I think I could pull down the entire interaction model, and see what slots are in each intent, but trying to :elicitSlot will still fail unless the request itself is updated with the newer intent

tianrenz commented 6 years ago

@bdelee,

Currently there's no way of receiving a new intent without user initiated request. To update the skill service to send intent request without user initiating is not the desired behavior can could lead to potential problems

Regards

bdelee-zz commented 6 years ago

I guess there is nothing that can be done currently, but if Amazon really wants some interesting and complex skills to be built for their Alexa platform, I think they need to consider including programatic switching of states/intents where the lambda can ping the Alexa service to get an updated request/response for the current intent in the code without user input. I have my hands in a lot of complex skills, and it would be extremely valuable to be able to do this when considering the current limitations of using the Dialog model.

tobias74 commented 6 years ago

Basically this limitation prevents returning to a Multi-Turn-Dialog after the user said "Help".

In case you need to elicit several slots to complete an intent, there has to be a way to return to this Dialog after the user activated the HelpIntent.

User: "I want to order a Pizza" Alexa: "Which Pizza do you want?" User: "Salami" Alexa: "Where do you want this Pizza to be delivered?" User: "1 Somestreet in Sometown" Alexa: "How do you want to pay?" User: "Help"

at this point you can respond with the correct help-text, listing all the available payment-options (it is possible to determine the state of the dialog by using session-attributes) but you cannot re-elicit the paymentSlot

Alexa: "You can pay with Mastercard, Visa, Bitcoin, Ethereum or Paypal. Which Payment-Method do you want?" ^^^^ <<<<--- sadly this cannot be done with :elicitSlot. It has to be a normal response. Now the Users says: "Ethereum" and Alexa does not know which Intent to activate, since Ethereum could be a Payment-Method or the Name of a Pizza.

I definetly must be missing something here. How do people implement multi-turn-dialogs with simple one-word-responses without having to fear the HelpIntent?

bdelee-zz commented 6 years ago

@tobias74

This is a great example of what I am talking about. Another example that I am encountering is how the limitation makes it very difficult to "chunk" information. Let's say there is an API call that returns a list of theaters to see a movie, but we want to piece them out as three theaters at a time. We are elicitSlot-ing the theater name, or the user can say next/previous/start over/repeat using the AMAZON default intents. Once the user says one of those defaults, we drop out of the initial intent for chunking the theater list and can no longer elicitSlot to try to get their result.

If we could emitWithState back into the original intent with access to the requires slots, this process would be very simple. Yet, because of this limitation, it is difficult to use the Dialog.Model while also chunking information. Chunking is extremely important for presenting information over voice services to keep available choices manageable.

tianrenz commented 6 years ago

Hi all,

Thanks for your support for the SDK. We've released ASK SDK v2 for Node.js yesterday, which aims to address many of the issues here. We encourage you to check out our wiki here.

bdelee-zz commented 6 years ago

Thanks for the update, I really appreciate the hard work you've put into it. I've looked through the wiki and nothing jumps out at me as something that solves this issue. I may be missing something. Can you give me a little more direction? Thank you.

tianrenz commented 6 years ago

Hi @bdelee,

This issue seems to be a request for feature that's not currently supported. I checked out the links to the ASK forums. And it seems to be a good place to voice feature requests. From SDK perspective, mutating an intent or switching to a different intent in the middle of dialog management is not supported for now.

Regards