How many times do you want to find the perfect tool to keep track of the movies you've watched? The search ends now. Introducing Alexa Movie History, the server stands by your side and keeps all your movie watch histories.
Simply ask Alexa to start the Movie History, tell it the movie you just watched and the date, you are all set! Check back the total times you watch movies, or the date when you watched one particular movie by simply talking to it.
System ArchitectureIn my design the Alexa skill works as a front-end server, taking user commands, doing NLP stuff, and resolving into corresponding intents.
Then the Alexa trigger one of the lambda function to take action, this is done by setting the Alexa Skill Kit as the trigger of the lambda function. So whenever an intent is resolved by Alexa, it will know where to find the code to take actions.
In Movie History skill I want to store the movie watch history for each user from different Alexa device (Amazon Echo, Echo dot, Echo show, or even home made Raspberry Pi based Alexa device), and later be able to retrieve them back after days, months or even years after they told the Alexa when and what they have watched. This will require the data being persisted across sessions. So as part of Amazon package deal, Dynamo DB would be the most convenient persistence solution.
Finally, because the whole thing runs on cloud, you lose a lot of the abilities to test and debug your application like you do for desktop/web applications, I need to find a way to diagnose how my application works. Luckily I found out that if you use Node.js to write the lambda function, any console.log will be redirect to AWS CloudWatch automatically. So log anything you want like you do in everyday Javascript code, and they will be properly stored and presented to you in the CloudWatch dashboard.
VUI DesignAfter decided the high level system design, now it's time to design the Voice User Interface (VUI).
Amazon has provided a lot of really helpful resource for reference, here is the Amazon VUI design guide site. Definitely worth checking out:
https://developer.amazon.com/designing-for-voice/
Here is my design for Movie history:
Main Menu
As you can tell from the graph, the whole VUI is consisted of two parts: the input part and query part. So the first thing you hear from Movie History will be a main menu prompting for two choices: add new movie watch record or review the watch history.
Add New
After chose to add new one, the user would be prompted to provide the movie watch information. Here I decided to only accept two information, the title and watch time. Too many information would make the user interaction way too complex and hence hard to use. So let's KISS (keep it simple and stupid).
Since both parameter are required, I decided to use dialog based interaction so user can choose to provide everything in one shot, or just tell the name, and let the application tell them what else are needed.
Review
If the user choose to review, there would be two way of review his/her past watch history, either get an overall idea of how many movies he/she has watched, or ask for the exact date when one particular movie was watched.
This time I decided to just tell the user about the choices and let user say whatever they want to do. So no more menus, if the user says he want the total number, he will have it; if the user says he want to know the date for one movie, we will find it.
Database SchemaDynamoDB is a NoSQL schemaless database so technically there is no schema, but for convenience I'll define the schema I'm using right now.
In DynamoDB the only thing you need to pay attention is the primary key. The primary key for a DynamoDB table can be a single partition key, or a partition key with a sort key. Depends on the use case you can leverage the primary key to make your queries super fast.
In Movie History, I want the data records to store the movie title and watched date obviously. In addition to that I also need to be able to easily query all the entries for one movie title (you may watch movie multiple times and we can keep all of them), and query all the records for one user. So I choose to use a partition key and a sort key.
The partition key is the user ID Alexa generated for each user per skill, so that all the data for one user is stored in one partition guarantees the query performance.
The sort key is a combination of movie title and watch date as string, so that two watch date will stored in two rows. And because title is the first part of the sort key, records for same movie will be stored in sequence sort by watch date, therefore we can quickly find all the watch dates for one movie.
With this schema, to query all data for one user, here is the query:
{
TableName: 'WatchedMovies',
KeyConditionExpression: 'UserId = :pkey',
ExpressionAttributeValues: {
':pkey': { S: userId.toString() },
}
And here is the query to find all watch dates for one movie:
{
TableName: 'WatchedMovies',
KeyConditionExpression: 'UserId = :pkey and begins_with(TitleWithDate, :skeyPrefix)',
ExpressionAttributeValues: {
':pkey': { S: userId.toString() },
':skeyPrefix': { S: title }
}
Further Improvements- Validate the movie name.
- Provide a search functionality to make it easier to provide the correct movie name.
- Support card in Alexa app.
- Support display the information on Echo show.
- I published my Alexa skill once and got some certification feedback for further modification. I'll update once I've done that and successfully published the skill.
This is my very first effort to create an Alexa skill. Thanks to this opportunity and the information/tools provided in this contest I would able to finish an end-to-end Alexa skill experience. This was a few joyful days with challenges and achievements. I enjoy the tool chain Alexa provides and feel very rewarding for the end result. I created this skill to solve my real problem to find a perfect tool to save all the movies I have watched, but I hope this would be as useful to you as well.
Thanks for your support!
Comments