How-Tos¶
Here you can find answers to the most common questions that you may have when building an AI agent with Alan AI.
Dialog script¶
How to capture the entire user input¶
How to capture the entire user input
If you need to capture the entire user input, you can use the p.inputText object in the fallback()
function.
Assume you need to get the user feedback and play it back to the user. You can add the following code to the dialog script:
intent("I want to give feedback", async p => {
p.play("Please start talking");
p.userData.feedback = [];
await p.then(captureFeedback);
let feedback = p.userData.feedback.join(`\n`);
p.play(`Here is your feedback: ` + feedback);
});
let captureFeedback = context(() => {
intent(`No, thank you`, p => {
p.play(`OK, saving`);
p.resolve();
});
fallback(p => {
console.log(`input text: "${p.inputText}"`);
p.play(`Would you like to add anything else?`);
p.userData.feedback.push(p.inputText);
});
});
When the user says: I want to give feedback
, the AI agent prompts them to share their feedback, activates the captureFeedback
context and pauses the script until the feedback is received. The user input is stored in the p.inputText
object, which is added to the fallback within the context. Once the user finishes sharing their thoughts, Alan AI exits the context and repeats the feedback to the user.
How to run a query with words from the user input¶
How to run a query with words from the user input
If you need to run a query with user’s words, you can add a slot to the command pattern to capture the user’s input.
In the example below, when the user asks to translate a word or phrase, Alan AI captures this word or phrase, makes an API call to an external translation service and plays the result with the Italian accent.
intent('How would you say $(PHRASE: free form text...)?', async p => {
translate(p, p.PHRASE.value);
})
async function translate(p, text) {
try {
const response = await api.axios.post('https://studio.alan.app/api_playground/translate', {
text: text,
srcLang: 'en',
dstLang: 'it'
}, {
timeout: 3000
});
const responseData = response.data;
p.play(voice('it'), responseData.translated);
} catch (error) {
console.error('Error occurred:', error);
p.play('Sorry, something went wrong with the server');
}
}
How to get the right answer from the user¶
How to get the right answer from the user
In some cases, the user’s answer may be not precise. As a result, you will not be able to get from the user input the data you need for the subsequent dialog flow. To get the necessary information, you can use an async context in the dialog script.
Consider the following example: you need to get the coffee type from the user input, but instead the user just says: I want a coffee
. You can add the following command to the dialog script:
intent("I want a coffee", async p => {
p.play("What coffee do you prefer?");
const coffee = await p.then(whatCoffee);
p.play(`Your ${coffee} coffee will be ready in a moment`);
});
const whatCoffee = context(() => {
intent("$(COFFEE: black, americano, latte, cappuccino, expresso)", p => p.resolve(p.COFFEE));
})
Here, once you receive an answer that should be more specific, the AI agent plays: What coffee do you prefer?
, activates the whatCoffee
context and stops the script execution until the user gives the necessary answer. If the user answer matches one of the values listed in the COFFEE
slot, Alan AI exits the context, and the coffee type is returned. The AI agent then plays: Your ${coffee} coffee will be ready in a moment
with the coffee type obtained.
How to handle unexpected user commands¶
How to handle unexpected user commands
The user may give an answer of the type inappropriate for you. In this case, you can lock the user in the context with the fallback() function until the necessary user input is received.
Consider the following example: a dialog script for a simple math checker offers the user to add two random numbers.
intent("Check my math", async p => {
const a = Math.floor(Math.random()*10);
const b = Math.floor(Math.random()*10);
p.play(`How much ${a} plus ${b}?`);
const sum = await p.then(getNumber);
p.play(`Your answer ${sum} is ${a+b==sum? 'correct': 'incorrect'}`);
});
const getNumber = context(() => {
intent("It is $(RESULT: 1, 2, 3...)", p => {
console.log(p.RESULT.value);
p.resolve(p.RESULT.value);
});
fallback("You have to say a number");
});
Here, after the AI agent asks a question, it activates the getNumber
context and stops the script execution until the answer of the appropriate type is received. The answer must be captured by the RESULT slot: in this case, the AI agent exits it the context, and the user answer is returned. If the answer is of any other type, the user remains in the context. To instruct the user on the rules, the AI agent plays: You have to say a number
.
How to iterate over a list of objects (back and forward)¶
How to iterate over a list of objects (back and forward)
You may need to add a command that will allow the user to iterate over a list of objects. This can be the case, for example, if you are building an AI agent for a shopping or ordering app and want the user to pick something from the products list.
Consider the following example: you want your AI agent to name all available fruits, allow the user to pick some and save them to the user’s favorites list.
let fruits = ["apple", "orange", "lemon", "mango", "banana", "avocado", "kiwi"]
intent("I want to select fruits", async p => {
p.play("Iterate over the list of fruits and select your favorite one. To select fruit say 'select', say 'forward' or 'back' to traverse over the list");
p.play("Say 'finish' to complete your choice")
p.userData.favorite = []
p.play(`We have ${fruits.length} fruit in our list. First is ${fruits[0]}`)
await p.then(selectFruits, {state: { index : 0}})
if (p.userData.favorite.length > 0) {
p.play(`Your favorite fruits are: ${p.userData.favorite.join(", ")}`)
} else {
p.play(`You have not chosen any fruit`)
}
});
const selectFruits = context(() => {
intent("Select it", p => {
let selected = false
if(!p.userData.favorite.includes(fruits[p.state.index])) {
p.userData.favorite.push(fruits[p.state.index])
}
p.play(fruits[p.state.index] + " is selected")
p.play(p.userData.favorite)
})
intent("Say again", p => playFruit(p, p.state.index))
intent("Next", p => {
if(p.state.index < fruits.length-1) {
p.state.index++;
playFruit(p, p.state.index)
}
else {
p.play("It's the last fruit in the list")
}
})
intent("Go back", p => {
if(p.state.index > 0) {
p.state.index--;
playFruit(p, p.state.index)
}
else {
p.play("It's the first fruit in the list")
}
})
intent("That's it", p => p.resolve())
fallback("Say select to choose fruit, say forward or back to navigate through the list or say 'finish' to return")
})
const playFruit = (p, index) => {
p.play(`Fruit number ${p.state.index+1} is ${fruits[p.state.index]}`)
}
Here, the list of fruits is first saved to the fruits
array. When the user says: I want fruits
, the AI agent gives some instructions on how to pick fruits, names the first fruit in the list and activates the selectFruit
context. The dialog script execution stops until the user makes his or her choice and exits the selectFruit
context by saying: That's it
.
In the selectFruit
context, the user can select the named fruit, go forward or back with commands and tell the AI agent to stop iterating over the list. In the latter case, Alan AI exits the context, and we get back to executing the script in the initial command.
The context also has the fallback() function to lock the user if the necessary answer is not given.
To iterate over the list of fruits, the following Alan AI objects and variables are added to the script:
userData: this variable can be used to store data that can be accessed between contexts. In this example, the user choice is saved to the
p.userData.favorites
array in theselectFruit
context. The resulting list is played to the user after the user exits the context.state: this is a special object that сan be used as a ‘dictionary’. In this example, the
state
object stores the index of the current element in the fruits array. When the context is activated, the index is set to 0, and thestate
object is passed to the context. With each new step forward or backward in the context, the index is incremented or decremented.
How to sort items by price, name or category¶
How to sort items by price, name or category
If you are working with the item list, it is always a good idea provide the user with the ability to sort items by price, name or category. You can do it in the following way:
const menuItems = [
{name: "Cheese Burger", price: 8.99, category: 'burger'},
{name: "Double Cheese Burger", price: 12.00, category: 'burger'},
{name: "Bacon Burger", price: 11.50, category: 'burger'},
{name: "Hawaian Burger", price: 9.99, category: 'burger'},
{name: "Mexican Spicy Burger", price: 12.50, category: 'burger'},
{name: "Ceaser Salad", price: 12.50, category: 'salad'},
{name: "Garden Salad", price: 9.99, category: 'salad'}
];
intent(
'Sort by $(ORDER_BY: name, price, category...)',
p => {
const orderBy = p.ORDER_BY.value;
let orderedMenuItems = menuItems;
switch(orderBy){
case 'name':
orderedMenuItems = menuItems.sort((p1, p2) => p1.name.localeCompare(p2.name));
break;
case 'price':
orderedMenuItems = menuItems.sort((p1, p2) => p1.price - p2.price);
break;
case 'category':
orderedMenuItems = menuItems.sort((p1, p2) => p1.category.localeCompare(p2.category));
break;
}
p.play({command: 'getMenu', data: orderedMenuItems});
p.play(`Here are the items ordered by ${orderBy}`);
console.log(orderedMenuItems);
}
);
How to pass information to the context¶
How to pass information to the context
If you need to pass some information to the context, you can use the state object. state
is a kind of ‘dictionary’ where you can store any data you want.
intent("I have friends", async p => {
p.play("How many friends do you have?");
let number = await p.then(numberContext)
p.play("What is your friend's name number one?");
let index = 0, friends = [];
let list = await p.then(friendsContext, {state: {number, index, friends}})
p.play({command: "friends", list})
})
const friendsContext = context(() => {
intent("$(NAME: John, Mike, Jane, Mary...)", p => {
let {number, friends} = p.state;
friends[p.state.index++] = p.NAME;
if (p.state.index == number) {
p.resolve(friends)
}else {
p.play(`What is your friend's name number ${p.state.index+1}?`);
}
})
})
const numberContext = context(() => {
intent("$(FRIENDS_NUMBER: 1, 2. 3...)", p => {
if (p.FRIENDS_NUMBER.number > 0) {
p.resolve(p.FRIENDS_NUMBER.number)
} else {
p.play("The number of friends must be one or more")
}
})
})
In the example above, the AI agent gets the number of friends the user has and the friends’ names. Here we have a command: I have friends
, and two contexts that are activated from it:
numberContext
to get the number of friends from the user inputfriendsContext
to create a list of friends the user has
When we activate the friendsContext
, we are passing the following state
object to it: {state: {number, index, friends}}
.
number
stands for the number of friends retrieved from the user input, index
is used for iterating over the friends’ array and friends
contains the list of friends. Once the number of friends in the array is equal to the number of friends defined in the user input, Alan AI exits the context, and a command with the list of friends is sent to the app.
How to indicate meaningful words, terms and names¶
How to indicate meaningful words, terms and names
In patterns, you may have key words, terms and names to which the AI agent must pay a special attention. To increase the significance of these words and the chances that Alan AI matches the user’s input, instead of regular words or phrases, you can use slots in patterns.
In the example below, there are plumber terms that are key in the sentence. Instead of using regular alternatives, we can turn the terms to a slot and add this slot to the pattern. Although the slot values will not be used anywhere further in the script, this will increase the terms recognition.
intent('What is $(TERM: j-bend, return bend, p-trap, u-bend, s-trap...)?', p => {
p.play('It is the curved pipe under a sink that keeps sewer gases from entering the home.');
});
Client app¶
How to send commands to the app¶
How to send commands to the app
To trigger activities in the app with a voice or text command, you need to send commands from the dialog script to the app. Do the following:
Use the play() function in the dialog script to send a command to the app.
In the app, add the onCommand handler and define what actions must be taken when the command is received.
Let’s assume we want to open the cart when the user says: Go to the cart
. To do this, in the dialog script we will add the play()
function with the command object:
intent('Open the cart', p => {
p.play({command: 'showCart'});
p.play('Opening the cart');
});
In the app, we will use the onCommand handler
and define the logic for the showCart command in it:
var alanBtnInstance = alanBtn({
key: "YOUR_KEY_FROM_ALAN_STUDIO_HERE",
onCommand: function (commandData) {
if (commandData.command === "showCart") {
// go to the cart here
}
},
rootEl: document.getElementById("alan-btn"),
});
self.button.onCommand = ^(NSDictionary *command) {
NSString* commandName = [command objectForKey:@"command"];
NSLog(@"%@", commandName);
// if the command is showCart, go the cart here
};
self.button.onCommand = { command in
guard let commandName = command?["command"] as? String else {
return
}
print(commandName)
// if the command is showCart, go the cart here
}
val alanCallback: AlanCallback = object : AlanCallback() {
override fun onCommand(eventCommand: EventCommand) {
try {
val command = eventCommand.data
val commandName = command.getJSONObject("data").getString("command")
Log.d("AlanButton", "onCommand: commandName: $commandName")
// if the command is showCart, go the cart here
} catch (e: JSONException) {
Log.e("AlanButton", e.message)
}
}
};
AlanCallback alanCallback = new AlanCallback() {
@Override
public void onCommand(final EventCommand eventCommand) {
try {
JSONObject command = eventCommand.getData();
String commandName = command.getJSONObject("data").getString("command");
Log.d("AlanButton", "onCommand: commandName: " + commandName);
// if the command is showCart, go the cart here
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
}
};
_MyHomePageState() {
AlanVoice.onCommand.add((command) => _handleCommand(command.data));
}
void _handleCommand(Map command) {
switch (command["command"]) {
case "showCart":
// go to the cart here
break;
default:
debugPrint("Unknown command: ${command}");
}
}
this.alanBtnComponent.nativeElement.addEventListener('command', (data) => {
const commandData = (data).detail;
if (commandData.command === 'showCart') {
// go to the cart here
}
});
import { AlanView } from '@alan-ai/alan-sdk-react-native';
import { NativeEventEmitter, NativeModules } from 'react-native';
const {AlanManager, AlanEventEmitter} = NativeModules;
const alanEventEmitter = new NativeEventEmitter(AlanEventEmitter);
componentDidMount() {
/// Handle commands from Alan AI Studio
alanEventEmitter.addListener('onCommand', (data) => {
console.log(`onCommand: ${JSON.stringify(data)}`);
// if the command is showCart, go the cart here
});
}
componentWillUnmount() {
alanEventEmitter.removeAllListeners('onCommand');
}
How to send data from the dialog script to the app¶
How to send data from the dialog script to the app
To pass data from the dialog script to the app, in the play() function, define a JSON object of the command with all the data to be sent.
In this example, together with the navigate command, we are sending the route to the page that must be opened when the command is received. The logic for command handling is defined in the onCommand handler as described in the how-to above.
intent('Open the cart', p => {
p.play({command: 'navigate', route: 'home'});
p.play('Opening the cart');
});
How to send data from the app to the dialog script¶
How to send data from the app to the dialog script
To pass data from the app to the dialog script, you can use the project API functionality. Do the following:
Define a project API method in your dialog script.
Call the defined method from your app using Alan AI’s
callProjectApi()
. When calling the project API method, provide the method name and a JSON object with the data you want to send.
Let’s assume we want to pass the user’s name to the dialog script and greet the user when the user logs in to the system. To do this, we will define the greetUser()
project API method in the dialog script:
projectAPI.greetUser = function(p, param, callback) {
if (param) {
p.play(`Nice to see you again, ${param.user}`);
} else {
p.play('Welcome to our app');
}
callback();
};
In the app, we will call the greetUser()
method when the Log in
button is clicked and send the user’s name with it. Now, when the user logs in to the system, the Alan AI button will be activated automatically; Alan AI will send the user’s name to the dialog script and play: Nice to see you again, John Smith
or Welcome to our app
, if no name is provided.
// Calling the project API method on button click
function sendData() {
alanBtnInstance.activate();
alanBtnInstance.callProjectApi("greetUser", {
user: 'John Smith'
}, function(error, result) {});
};
// Calling the project API method on button click
- (void)callProjectApi {
[self.button callProjectApi:@"script::greetUser" withData:@{@"user":@"John Smith"} callback:nil];
}
// Calling the project API method on button click
func callProjectApi() {
self.button.callProjectApi("script::greetUser", withData: ["user":"John Smith"], callback: nil)
}
// Calling the project API method on button click
fun callProjectApi() {
val params = JSONObject()
try {
params.put("user", "John Smith")
} catch (e: JSONException) {
Log.e("AlanButton", e.message)
}
alanButton?.callProjectApi("script::greetUser", params.toString())
}
// Calling the project API method on button click
void callProjectApi() {
JSONObject params = new JSONObject();
try {
params.put("user","John Smith");
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
alanButton.callProjectApi("script::greetUser", params.toString());
}
_MyHomePageState() {
// Calling the project API method on button click
void _callProjectApi() {
var params = jsonEncode({"user":"John Smith"});
AlanVoice.callProjectApi("script::greetUser", params);
}
}
var myAlanBtn = document.getElementById('myAlanBtn');
myAlanBtn.componentOnReady().then(function () {
// Calling the project API method on button click
myAlanBtn.callProjectApi("greetUser", {user: "John Smith"}, function (error, result) {
console.log("project API function has been called", error, result);
});
});
import { AlanView } from '@alan-ai/alan-sdk-react-native';
import { NativeEventEmitter, NativeModules } from 'react-native';
const {AlanManager, AlanEventEmitter} = NativeModules;
export default class MyApp extends Component {
// Calling the project API method on button click
onPress = {() =>
AlanManager.activate();
AlanManager.callProjectApi(
'greetUser',
{user: 'John Smith'},
(error, result) => {
if (error) {
console.error(error);
} else {
console.log(result);
}
},
)
}
How to call a function in the dialog script from the app¶
How to call a function in the dialog script from the app
If you need to call a function from the app and perform some activities in the dialog script, you can use the project API functionality. Do the following:
Define a project API method in your dialog script.
Call the defined method from your app using Alan AI’s
callProjectApi()
.
Let’s assume we want the AI agent to inform users about the closest stores available when they select a location in the app. To do this, we will define the getStores()
method in the dialog script:
projectAPI.getStores = function(p, param, callback) {
p.userData.stores = param.stores;
if (param && param.length) {
p.play('We found several stores close to you...');
} else {
p.play('There are no stores at the moment, please choose another location');
}
callback();
};
In the app, we will call the getStores()
method when a location is selected. The Alan AI button will be activated automatically; Alan AI will send the stores list to the dialog script, save it to the userData variable and play: We found several stores close to you… or There are no stores at the moment, please choose another location.
// Calling the project API method on choosing a location
function sendData() {
alanBtnInstance.activate();
alanBtnInstance.callProjectApi("getStores", {
stores: storesList
}, function(error, result) {});
};
// Calling the project API method on choosing a location
- (void)callProjectApi {
[self.button callProjectApi:@"script::getStores" withData:@{@"stores":@"storesList"} callback:nil];
}
// Calling the project API method on choosing a location
func callProjectApi() {
self.button.callProjectApi("script::getStores", withData: ["stores":"storesList"], callback: nil)
}
// Calling the project API method on choosing a location
fun callProjectApi() {
val params = JSONObject()
try {
params.put("stores", "storesList")
} catch (e: JSONException) {
Log.e("AlanButton", e.message)
}
alanButton?.callProjectApi("script::getStores", params.toString())
}
// Calling the project API method on choosing a location
void callProjectApi() {
JSONObject params = new JSONObject();
try {
params.put("stores","storesList");
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
alanButton.callProjectApi("script::getStores", params.toString());
}
_MyHomePageState() {
// Calling the project API method on choosing a location
void _callProjectApi() {
var params = jsonEncode({"stores":"storesList"});
AlanVoice.callProjectApi("script::getStores", params);
}
}
var myAlanBtn = document.getElementById('myAlanBtn');
myAlanBtn.componentOnReady().then(function () {
// Calling the project API method on choosing a location
myAlanBtn.callProjectApi("getStores", {stores: storesList}, function (error, result) {
console.log("project API function has been called", error, result);
});
});
import { AlanView } from '@alan-ai/alan-sdk-react-native';
import { NativeEventEmitter, NativeModules } from 'react-native';
const {AlanManager, AlanEventEmitter} = NativeModules;
export default class MyApp extends Component {
// Calling the project API method on choosing a location
onPress = {() =>
AlanManager.activate();
AlanManager.callProjectApi(
'getStores',
{stores: storesList},
(error, result) => {
if (error) {
console.error(error);
} else {
console.log(result);
}
},
)
}
}
How to send information about the app visual context to the dialog script¶
How to send information about the app visual context to the dialog script
To build a contextual AI agent, you should be able to provide Alan AI with information about the app’s visual context: what screen is currently open, what options are enabled at the moment and so on. To do this, you can use the visual state functionality. Do the following:
Use the setVisualState() method in the app to send the information about the current visual context to the dialog script.
In the dialog script, differentiate responses using the visual object.
Let’s assume we want to provide users with a possibility to ask about available functions and want the AI agent to respond differently depending on the screen open. To do this, we need to send the visual state from the app like this:
alanBtnInstance.setVisualState({screen:"main"});
- (void)setVisualState {
[self.button setVisualState:@{@"screen":@"main"}];
}
func setVisualState() {
self.button.setVisualState(["screen":"main"])
}
fun setVisualState() {
val params = JSONObject()
try {
params.put("screen", "main")
} catch (e: JSONException) {
e.message?.let { Log.e("AlanButton", it) }
}
alanButton?.setVisualState(params.toString())
}
void setVisualState() {
JSONObject params = new JSONObject();
try {
params.put("screen","main");
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
alanButton.setVisualState(params.toString());
}
_MyHomePageState() {
void _setVisualState() {
var visualState = jsonEncode({"screen":"main"});
AlanVoice.setVisualState(visualState);
}
}
var myAlanBtn = document.getElementById('myAlanBtn');
myAlanBtn.componentOnReady().then(function () {
myAlanBtn.setVisualState({screen: 'main'});
});
setVisualState() {
AlanManager.setVisualState({screen:"main"});
}
In the dialog script, you can differentiate responses by accessing the p.visual
runtime variable:
intent("What can I do here?", p => {
let screen = p.visual.screen;
switch (screen) {
case "main":
p.play("You can browse our catalog and choose products");
break;
case "checkout":
p.play("Click Proceed to check out or Back to continue shopping");
break;
default:
p.play("Sorry, I have no information about it");
}
});
How to filter commands in the script¶
How to filter commands in the script
If some of the voice and text commands should work only in specific circumstances: when a screen is open or options are enabled, you can send the visual state from the app to Alan AI as described in the how-to above and filter commands in the dialog script like this:
const vCheckoutScreen = visual({"screen": "checkout"});
intent(vCheckoutScreen, 'How do I check out?', p => {
p.play('Check the products added to the cart and click Proceed');
});
How to activate the Alan AI button programmatically and play a greeting¶
How to activate the Alan AI button programmatically and play a greeting
You can activate the Alan AI button programmatically, for example, if you want to greet the user or let the AI agent start the dialog. To do this, use the onButtonState handler to check the Alan AI button state and the activate() and playText() client API methods.
In the example below, when the Alan AI button state is ONLINE (the connection to the Alan AI Studio project is established but the Alan AI button is not yet activated), the Alan AI button is activated programmatically and the agent greets the user.
var greetingWasSaid = false;
var alanBtnInstance = alanBtn({
...
onButtonState: async function(status) {
if (status === 'ONLINE') {
if (!this.greetingWasSaid) {
await alanBtnInstance.activate();
alanBtnInstance.playText("Hello! I'm Alan. How can I help you?");
this.greetingWasSaid = true
}
}
},
rootEl: document.getElementById("alan-btn"),
});
class _MyHomePageState extends State {
bool _greetingIsPlayed = false;
_MyHomePageState() {
AlanVoice.addButton("ec973ec04ff2bac6faceb579449bc5142e956eca572e1d8b807a3e2338fdd0dc/stage");
AlanVoice.onButtonState.add((state) {
if (state.name == "ONLINE" && !_greetingIsPlayed) {
_greetingIsPlayed = true;
AlanVoice.activate();
AlanVoice.playText("Hello! I'm Alan. How can I help you?");
}
});
}
}
private greetingWasSaid: boolean = false;
export class AppComponent {
ngAfterViewInit() {
this.alanBtnComponent.nativeElement.addEventListener('buttonState', (data) => {
const buttonState = (<CustomEvent>data).detail;
if (buttonState === 'ONLINE') {
if (!this.greetingWasSaid) {
this.greetUserForFirstTime();
this.greetingWasSaid = true
}
}
});
}
async greetUserForFirstTime() {
this.alanBtnComponent.nativeElement.componentOnReady().then(async () => {
try {
await this.alanBtnComponent.nativeElement.activate();
this.alanBtnComponent.nativeElement.playText("Hello! I'm Alan. How can I help you?");
} catch(e) {
console.info('DEBUG', e);
}
});
}
}
How to capture user utterances as text¶
How to capture user utterances as text
To capture what the user has said as a text message, use Alan AI’s onEvent handler.
In the example below, different types of events are handled to write text messages of the user’s input and Alan AI’s response to the app logs:
recognized
event to log interim results for the user’s utteranceparsed
event to log the final variant of the user’s utterance, as Alan AI has parsed ittext
event to log the AI agent response
var alanBtnInstance = alanBtn({
// Handling events
onEvent: function (e) {
switch (e.name) {
case "recognized":
console.info('Interim results:', e.text);
break;
case "parsed":
console.info('Final result:', e.text);
break;
case "text":
console.info('Alan AI reponse:', e.text);
break;
default:
console.info('Unknown event');
}
},
});
val alanCallback: AlanCallback = object : AlanCallback() {
/// Handling events
override fun onEvent(payload: String) {
try {
val eventName = JSONObject(payload).getString("name")
val eventText = JSONObject(payload).getString("text")
when (eventName) {
"recognized" -> {
Log.d("AlanButton", "Interim results: $eventText")
}
"parsed" -> {
Log.d("AlanButton", "Final result: $eventText")
}
"text" -> {
Log.d("AlanButton", "Alan AI response: $eventText")
}
}
} catch (e: JSONException) {
e.message?.let { Log.e("AlanButton", it) }
}
}
};
/// Registering callback
alanButton?.registerCallback(alanCallback);
AlanCallback alanCallback = new AlanCallback() {
/// Handling events
@Override
public void onEvent(String payload) {
try {
JSONObject eventDict = new JSONObject(payload);
String eventName = eventDict.getString("name");
String eventText = eventDict.getString("text");
switch (eventName) {
case "recognized":
Log.d("AlanButton", "Interim results: " + eventText);
break;
case "parsed":
Log.d("AlanButton", "Final result: " + eventText);
break;
case "text":
Log.d("AlanButton", "Alan AI's response: " + eventText);
break;
default:
Log.d("AlanButton", "Unknown event");
}
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
}
};
/// Registering callbacks
alanButton.registerCallback(alanCallback);
_MyHomePageState() {
/// Registering the event listener
AlanVoice.onEvent.add((event) => _handleEvent(event.data));
/// Handling events
void _handleEvent(Map<String, dynamic> event) {
switch (event["name"]) {
case "recognized":
debugPrint("Interim results: ${event["text"]}");
break;
case "parsed":
debugPrint("Final result: ${event["text"]}");
break;
case "text":
debugPrint("Alan AI's response: ${event["text"]}");
break;
default:
debugPrint("Unknown event");
}
}
}
ngAfterViewInit() {
/// Registering the event listener
this.alanBtnComponent.nativeElement.addEventListener('event', (data) => {
const event = (<CustomEvent>data).detail;
/// Handling events
switch (event.name) {
case "recognized":
console.info('Interim results:', event.text);
break;
case "parsed":
console.info('Final result:', event.text);
break;
case "text":
console.info('Alan AI's reponse:', event.text);
break;
default:
console.info('Unknown event');
}
});
}
alanEventEmitter.addListener('onEvent', (payload) => {
let eventObj = JSON.parse(payload);
switch (eventObj.name) {
case "recognized":
console.info('Interim results:', eventObj.text);
break;
case "parsed":
console.info('Final result:', eventObj.text);
break;
case "text":
console.info('Alan AI's reponse:', eventObj.text);
break;
default:
console.info('Unknown event');
}
});
How to send text messages to Alan AI¶
How to send text messages to Alan AI
To send the user’s request to Alan AI as a text message, use the sendText() method. To capture the AI agent response to the sent message, use the onEvent handler and the text
event.
In the example below, when a button is clicked, the How can you help me?
text message is sent to Alan AI. The agent replies with the response defined in the dialog script. The user’s input and the AI agent response are captured with the help of parsed
and``text`` events in the onEvent
handler and logged to the console.
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
<div class="alan-btn"></div>
<button type="button" onclick="sendText()">Send text</button>
<script>
var alanBtnInstance = alanBtn({
key: "YOUR_KEY_FROM_ALAN_STUDIO_HERE",
onEvent: function (e) {
if (e.name === "parsed") {
console.info('Sent msg:', e.text);
}
else if (e.name === "text") {
console.info('Received msg:', e.text);
}
},
rootEl: document.getElementById("alan-btn"),
});
function sendText() {
alanBtnInstance.sendText('How can you help me?');
}
</script>
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
- (void)sendText {
[self.button sendText:@"How can you help me?"];
}
self.button.onEvent = ^(NSString *payload) {
NSData* eventData = [payload dataUsingEncoding:NSUTF8StringEncoding];
NSError* error = nil;
NSDictionary* eventDict = [NSJSONSerialization JSONObjectWithData:eventData options:0 error:&error];
if (error != nil) {
return;
}
NSLog(@"%@", eventDict);
};
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
func sendText() {
self.button.sendText("How can you help me?")
}
self.button.onEvent = { event in
guard let eventData = event?.data(using: .utf8, allowLossyConversion: false),
let eventDict = try? JSONSerialization.jsonObject(with: eventData, options: .mutableContainers)
else {
return
}
print(eventDict)
}
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
fun sendText() {
alanButton?.sendText("How can you help me?")
}
val alanCallback: AlanCallback = object : AlanCallback() {
override fun onEvent(payload: String) {
try {
val eventName = JSONObject(payload).getString("name")
val eventText = JSONObject(payload).getString("text")
when (eventName) {
"parsed" -> {
Log.d("AlanButton", "Sent msg: $eventText")
}
"text" -> {
Log.d("AlanButton", "Received msg: $eventText")
}
}
} catch (e: JSONException) {
e.message?.let { Log.e("AlanButton", it) }
}
}
}
alanButton?.registerCallback(alanCallback);
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
void sendText() {
alanButton.sendText("How can you help me?");
}
AlanCallback alanCallback = new AlanCallback() {
@Override
public void onEvent(String payload) {
try {
JSONObject eventDict = new JSONObject(payload);
String eventName = eventDict.getString("name");
String eventText = eventDict.getString("text");
switch (eventName) {
case "parsed":
Log.d("AlanButton", "Sent msg: " + eventText);
break;
case "text":
Log.d("AlanButton", "Received msg: " + eventText);
break;
default:
Log.d("AlanButton", "Unknown event");
}
} catch (JSONException e) {
Log.e("AlanButton", e.getMessage());
}
}
};
alanButton.registerCallback(alanCallback);
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
_MyHomePageState() {
void _sendText() {
AlanVoice.sendText("How can you help me?");
}
AlanVoice.onEvent.add((event) => _handleEvent(event.data));
void _handleEvent(Map<String, dynamic> event) {
switch (event["name"]) {
case "parsed":
debugPrint("Sent msg: ${event["text"]}");
break;
case "text":
debugPrint("Received msg: ${event["text"]}");
break;
default:
debugPrint("Unknown event");
}
}
}
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
var myAlanBtn = document.getElementById('myAlanBtn');
myAlanBtn.componentOnReady().then(function () {
myAlanBtn.sendText("How can you help me?");
});
ngAfterViewInit() {
this.alanBtnComponent.nativeElement.addEventListener('event', (data) => {
const event = (<CustomEvent>data).detail;
switch (event.name) {
case "parsed":
console.info('Sent msg:', event.text);
break;
case "text":
console.info('Received msg:', event.text);
break;
default:
console.info('Unknown event');
}
});
}
intent('How can you help me?', p => {
p.play('I can do virtually anything. Ask me a question or say what to do');
});
sendText() {
AlanManager.sendText("How can you help me?");
}
componentDidMount() {
alanEventEmitter.addListener('onEvent', (payload) => {
let eventObj = JSON.parse(payload);
switch (eventObj.name) {
case "parsed":
console.info('Sent msg:', eventObj.text);
break;
case "text":
console.info('Received msg:', eventObj.text);
break;
default:
console.info('Unknown event');
}
});
}
componentWillUnmount() {
alanEventEmitter.removeAllListeners('onEvent');
}