Flutter: Adding an AI-Powered Voice Assistant to your application

Aurosmruti Das
Dec 13, 2020 · 11 min read

In this customer-centric era, user experience has become one of the topmost priority for customer based applications. That’s why developers are also focusing more on user interactions to make it as smooth as possible. When it comes to UX, AI( Artificial Intelligence ) has always been a good performer. Developers nowadays are using AI to enhance the UX of their applications. Voice-controlled interaction is one of them.

As a Flutter developer, I always had a curiosity of knowing how to implement a custom voice-enabled virtual assistant like google assistant, Siri, Alexa, etc to my own flutter application where I can program the behavior of that assistant. Then I got to know about Alan AI.

Alan AI is a complete voice AI platform that lets you embed a contextual voice assistant into your existing application. So if you want to add a voice assistant to your existing flutter application, then you are at the right place.

In this article I’ll walk you through the implementation of an AI-powered voice assistant in your existing flutter application and at the end of this article, you’ll be able to create your own voice assistant.

Creating a project on Alan Studio :

STEP-1

Sign up for Alan Studio if you don’t have an account.

STEP-2

the empty dashboard of Alan Studio

You will get an empty dashboard like this. ( If you haven’t created any projects yet ). Click on that “ Create voice assistant ” button.

STEP-3

project type dialogue

Then you’ll get the above dialogue. Click on that “ Empty project ” card. And then you’ll be asked for a project name, give a suitable name for your project. I’m naming it “ alan_demo ”.

STEP-4

basic default “hello world” voice script

After all of this stuff, finally, a script editor and real-time testing area will appear like this(in the above image). To test that basic “ hello world ” command, click on that mic button present in the “ debugging chat ” area at the right side of the window and say “ hello world ” in an audible voice. I hope you’ve got a reply from your pc saying “ hello ” or “ hi there ”. Isn’t it interesting?

STEP-5

get your Alan SDK key here

Click on the integration button present in the top bar of the script editor page. Then collect the SDK Key. You’ll need it later.

Finally, we successfully created a basic “ hello world ” script for our voice assistant. Ohhh yeahhhhh !!!

You may be thinking of the code that is written in that script editor. These are basically javascript codes, so feel free to do any Js stuff there. Don’t worry, we’ll discuss the code syntaxes once we connect this to our flutter application. So let’s do that first.

Connecting voice script to an existing flutter application :

If you haven’t created any flutter projects yet, then create a new flutter project now, and if you don’t know how to do that, then go for the following link.

STEP-1

Add the following dependency in your pubspec.yaml file. Also, make sure that you are using the latest version of it. You can get the latest version of it from here :

dependencies:
alan_voice: <latest version>

and then run $ flutter pub get

STEP-2

import ‘package:alan_voice/alan_voice.dart’;

Import the above package in your file.

STEP-3

String sdkKey = “ paste your sdk Key here ” ;@override
void initState() {
super.initState();
initAlan();
}
initAlan(){
AlanVoice.addButton(sdkKey);
}

Add this to your file. Here we are calling a function initAlan() inside the initState() of the stateful widget or a page in which you want to add that Alan button. Inside the initAlan(), we are adding the button with the help of the SDK key.

Now you can run your application and check the voice assistant by clicking that Alan button and saying “ hello world ”. Yeahhhhh !!

At this point, we have made a flutter application having a basic voice assistant. For more detailed stuff and improvements to the voice script, continue reading.

STEP-4

initAlan(){
AlanVoice.addButton(sdkKey);
AlanVoice.callbacks.add((command){});
}

Here we’ve added a callback listener in that initAlan(). It is called whenever some data or command is sent from the alan server ( obviously the commands to be sent are written on that voice script itself, we’ll discuss that later ) as a JSON object to client-side flutter code. It becomes handy when you try to do something in your flutter app as a response to your command.

STEP-5

initAlan(){
AlanVoice.addButton(sdkKey);
AlanVoice.callbacks.add((command)=> _handleCommand(command.data));
}
_handleCommand(Map<String, dynamic> response){
switch(response[“command”]){
case “command_1”:
//do something according to command_1
break;
case “command_2”:
//do something according to command_2
break;
default:
break;
}
}

Let's handle the command coming from that callback. As command data is a key-value map of type (string->dynamic), So the _handleCommand() will take a Map<String, dynamic> as its argument. That map will contain a key “command” whose value will give you the command that you wrote in that voice script for a particular task. Then according to that, you can perform those tasks in your flutter application. You can use the switch case to write separate task logics for each command.

Understanding the voice script syntax :

Intents

intent() is the basic commonly used function to describe a user given command. It has basically two parts, the first part is the pattern part and the second one is the action part. The action part will be executed when the pattern is matched. So Let’s start with a basic intent.

intent(‘hello world’, p=>{
p.play(‘(hello | hi there)’);
});

In the above example, if you say “ hello world ”, then you’ll get a reply “ hello ” or “ hi there ” from the assistant.

A project can have more than one intent and the intent can have more than one pattern. In the above example, “ hello world ” is the single pattern and present in the global context. Actually, the first pattern of intent is considered to be present in a global context. The global context is something that is given more priority while matching for patterns.

Play

play() is a predefined function that is used to respond to the user by sending a simple message or command in the form of a JSON object. If you don’t know about JSON, then google it.

intent(‘what is your name’, p=>{
p.play(‘I am alan’, ‘I am anon’);
});

play() can have more than one pattern ( i.e ‘ I am alan ’ and ‘ I am anon ’ in the above example ), then one of them will be picked randomly and played back to the user.

intent(‘go to bookings page’, p=>{
p.play({“command”: ”navigate”, “page”: “bookings” , “id”: 1});
});

In the above example, we are sending a JSON object instead of a simple string type pattern. Remember in flutter code we have declared a _handleCommand( Map<String, dynamic> response), we have to catch this JSON object there and handle it. Don’t worry, we are going to update that method soon.

Matching Principle

intent(‘what is your name’, p=>{
p.play(‘(I am alan)’);
});
intent(‘what is your name buddy’, p=>{
p.play(‘(I am anon)’);
});

In the above example, if the user asks for “what is your name” then the first intent will be matched over the second intent. Because some words are still missing from the user asked pattern but present in the second intent’s pattern. But if the user asks for “ what is your name buddy ”, then the second intent will be matched because of the more number of matched words in the pattern.

Pipes

intent(‘hello world (alan|)’, p=>{
p.play(‘(hello | hi there)’);
});

‘|’ is called a pipe which is used to make the pattern and response shorter.

In the above example, ‘|’ used in (alan|), implies that the user may or may not say the word “ alan ”, which means both “ hello world ” and “ hello world alan” will be matched. Simply we can consider it as an optional word in the pattern.

But when ‘|’ is used in between two words of the same pattern or response-pattern like in the above example, ‘|’, used in play(), i.e (hello | hi there). It implies “ hello ” OR “ hi there ”, which means between these two, only one will be picked as random and played back to the user.

Question, Reply and Follow

question() is a predefined function having the lowest priority to handle user commands.

question(‘hello world’, p=>{
p.play(‘(hello)’);
});
intent(‘hello world’, p=>{
p.play(‘(hi there)’);
});

If there is another intent() having the same pattern, then that will be activated instead of this. In this case, the user will get “hi there” playback.

reply() is used to give a response back to the user without having complex actions.

intent(‘hello world’,
reply(‘hi there’)
);

follow() is used in nested conversations and is activated only when the parent pattern is matched.

intent(‘How are you’,
reply(‘I am doing well. What about you ?’,
follow(‘(Not so good | bad | Terrible)’,
reply(‘sad to hear this’)),
follow(‘(good | I am also | ya doing well)’,
reply(‘I am happy to hear that’))
)
);

In the above example, we’re having a continuous conversation in which we can feel the importance of the follow and reply. If you want to send some command back, then you can’t just send those inside reply(), you have to take the help of play(). I have described those in the play section.

Slots

In case you need to use a word from the user given command and reply that word back as a playback to the user, then just have a look at the following example :

intent(‘you are $(word* (.*))’, p=>{
p.play(`yes, I am ${p.word.value}`);
});

In the above example, all words coming after ‘ are ’, in the user given command, will be copied into the variable ‘ word ’ and we can access those as p.word.value. Then using that, we can play the response back to the user using play(). Simply you can say, if a user has given a command ‘you are fantastic’, then a playback ‘ yes, I am fantastic ’ will be heard at the client-side.

intent(‘you are $(word good|better|best)’, p=>{
p.play(`yes, I am ${p.word.value}`);
}); // when you know all the possibilities of that word

Now you have got the power to make an amazing voice script.

Upgrading our old voice script :

Let’s make a small voice script to know how all previous things work.

updated voice script

You can run and test this script on the browser itself. Have a look at the rightmost section of the window.

Updating the _handleCommand() in flutter code :

_handleCommand(Map<String, dynamic> response) {    
switch (response["command"]) {
case "next_page":
Get.to(NewPage());
break;
case "prev_page":
Get.back();
break;
case "change_bg_color":
setState(() {
bgColor = Colors.yellow;
});
break;
case "disable":
AlanVoice.deactivate();
break;
default:
print("no match found");
break;
}
}

Full page code will look something like this :

You may be thinking of the Get, used in “ next_page ” or “ prev_page ” matches. Well, the Get is used here for contextless navigations. But Get is much more than that. You can visit the link to know more about it.

Few more customizations :

First, go to the Integrations page. Then switch to the Android tab there.

integrations page for more customizations

So many options here, you can customize your voice agent to some more extent and if you want to change the style of your Alan button, then click on that changing button in the above image, then a menu will appear where you can choose your button style.

available button styles

Possible errors and their solutions :

  • In Android When you add the dependency alan_voice to your pubspec.yaml and then after pub get when you try to run the application if some error occurs like “Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared in library [:alan_voice]”, then you have to go to the android/app/build.gradle file, then search for “ minSdkVersion ” and then update its value to 21. Then again run it. I hope your problem will be fixed.
  • In ios, if some error occurs related to permission, then check for Info.plist file. Don’t forget to add NSMicrophoneUsageDescription there with a string value explaining to the user how the app uses this data. For more google it.
  • If some error related to SDK files download occurs, then check for the internet connection of your device and pc as well.

Getting free interactions for your projects :

Initially, you get 50 interactions from Alan AI which is very less I think. So what you have to do is, there are so many YouTubers providing their promo codes in the description of their videos related to voice assistants. I am giving some links just go for it. Per promo code, you’re gonna get 2500 interactions which are enough for your projects.
1. Javascript Mastery
2. MTechViral
3. Web Dev Simplified

For further reading :

Github repository of this project: https://github.com/anon-000/alan_demo

Here I am attaching some Github repos where you can get some more interesting implementation of this alan ai.

Now it’s time to end our article here. I’ll thank Alan AI for making all these things this much easier with its user-friendly GUI. It also has an analytics page where you can get a detailed view of your interactions. Amazing thing is that anyone can learn and implement it on any platform. List of all platforms that are supported are listed on its official website, you can go and check there.

Not only Alan but also Google also has developed a suite named Dialogflow CX for these kinds of AI-related things like chatbots, voice bots, and IVR bots. They are building the future.

So it is just an easy example of the implementation of a voice assistant in a flutter application. As all of you know, “ SKY’S THE LIMIT ”. You can do anything with it, that totally depends upon you. Much more interesting stuff can be done by training your voice assistant to its full extent. I hope you guys will implement this and try to make something more amazing.

You can reach me on LinkedIn and Twitter. Also, don’t forget to check out our Website. And thank you for reading till the end. It’s my first article, so if you have any kind of suggestions for me, then don’t forget to respond. If this article has added some value to your knowledge, then show some love by hitting that clap (👏 ) button.

Happy Coding

Aurosmruti Das

Smartters’ Studio

A group of tech enthusiastic people spreading their…