Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Let us create transitions for a virtual agent that handles time, weather, and playing music:
#5
: shows the current time (although it is correct only twice a day at the moment).
#8
: informs the current weather in Sunnyville.
#11
: plays the song "Raining Tacos".
#14
: print the error message and references to the start
state.
Notice that when the user input does not match any of the conditions, it prints the error message and loops back to the start
state.
It is possible to name any transition you create as a state:
#6
: names the state as time
.
#9
: names the state as weather
.
#13
: names the state as play_raining_tacos
.
#17
: references to the play_raining_tacos
state.
State referencing can be abused to create transitions that never end (infinite loop). It is important to design an exit state so you can terminate the conversation without throwing errors:
#6,10,14,17
: loops back to the start
state.
#19-21
: creates an exit state to terminate the dialogue.
What is the main difference between an error
transition and an exit
state?
An error transition defines a default action for uninterpretable user input, whereas an exit state terminates the current session of the dialogue.
Let us create a simple transition that counts how many times the user visits:
#4
: calls the macro #VISITS
defined in #7
.
MacroVisits
can be defined as follow:
#10-13
: uses the match statements to return the appropriate literal.
The challenge is that we must save the number of visits to make this macro effective (and correct). This can be achieved by saving the variable dictionary into a binary file using the built-in Python object serialization called pickle:
#1
: takes a dialogue flow df
and a file path varfile
for saving the variable dictionary to.
#3
: creates a dictionary by copying only user-generated variables.
#4
: opens a writable (w
) and binary (b
) file and dumps the dictionry object into the file.
After running this code, you will see the visits.pkl
file saved under the resources
directory.
The following code shows how to load the saved dictionary to a new dialogue flow:
#1
: takes a dialogue flow df
and a file path varfile
for loading the variable dictionary from.
#2
: opens a readable (r
) and binary (b
) file and loads the object as a dictionary.
#3
: adds all variables in the loaded dictioinary to the variable dictionary of df
.
#5
: saves the new variable dictionary to the same file.
You aim to create a chatbot that makes a movie or a song recommendation. Your system should conduct dialogue including the following aspects:
Greet with respect to the current time and/or weather.
Ask about the user's name (with a different way of asking each time the user logins).
If it is the first time the system sees the name, then prompt the first-time greeting. Otherwise, greet by asking about its previous recommendation.
Recommend a movie or a song, depending on the user's request. Do not make the same recommendation more than once for each genre.
If the user requests a different recommendation, make another suggestion.
Provide more information about the recommendation upon request.
Here is an example dialogue for a user talking to this chatbot for the first time:
Here is an example dialogue for a user coming back for the second time:
Your chatbot should give an appropriate response to every user response.
Update it to design a dialogue flow for the chatbot.
Create a PDF file quiz4.pdf
that describes the following:
Sample dialogues that your chatbot can conduct.
Explanations of your approach.
Commit and push quiz4.py
to your GitHub repository.
Submit quiz4.pdf
to Canvas.
Draw a diagram describing the following dialogue flow.
What is the role of MacroWhatElse
?
It is often the case that the user says something out of the topic that the system expects. One way of handling such occasions is by using global transitions that anticipate common cases:
#1-8
: creates global transitions.
#10
: adds the global transitions to the dialogue flow.
Notice that after prompting an output in the global transitions, it will direct to the good
state defined in the regular transitions.
The global transitions are fired whenever the user content matches their conditions, which can cause multiple matching conditions as follow:
#5
: matches the condition in the movie
state.
#5
: matches the condition in the global transition.
Thus, it is recommended to put lower scores on the conditions in global transitions such that local transitions are prioritized over them:
Besides #ONT
for checking an ontology, STDM provides several macros useful for dialogue design.
The following example shows a use case of the macro #LEM
that uses the NLTK Lemmatizer to match lemmas of "raining tacos":
#5
: maches the input with the lemma of "rain" or "rainy", then the lemma of "taco".
The #UNX
macro can be used as an alternative to the 'error'
transition, which prepends a short acknowledgment phrase (e.g., "yeah", "sure") to the error statement:
#8
: prepends an acknowledgment phrase to the error statement, "Thanks for sharing" in #8
.
#3,5
: add acknowledgment phrases given the user inputs.
#7
: does not add an acknowledgment phrase when the user input is short.
When the user input contains fewer than three tokens, #UNK
does not add any acknowledgment.
Seldomly, #UNK
gets selected even when conditions in other transitions match the input (due to an STDM bug). If you notice this during testing, assign a very slow score to the #UNK
state to ensure it gets the lowest priority among other branches.
Let us update the above transitions so that it sometimes refuses to sing the same song:
#6
: can be picked if the variable $RAINING_TACOS
equals to the string 'True'
.
#7
: sets $RAINING_TACOS
to 'True'
after prompting the system output.
Once $RAINING_TACOS
is set to 'True'
, STDM randomly picks a statement in #6
or #7
as the system output.
Notice that the #SET
macro only assigns a string value to the variable. It is possible to write a macro to set any variable to an actual boolean value (e.g., True
, False
):
#3-4
: checks if there are two arguments.
#6-8
: retrieves the variable name.
#10-12
: checks if the argument is a proper boolean value.
#14
: stores the boolean value to the variable.
Given MacroSetBool
, the above transitions can be updated as follow:
#6
: is selected if $RAINING_TACOS
is True
.
#0
: sets the variable $RAINING_TACOS
to the boolean value True
.
Currently, STDM randomly chooses the statements in #6
and #7
once $RAINING_TACOS
becomes True
. We can write another macro that prompts #7
only for the first time:
Given MacroPlayRainingTacos
, the transitions can be updated as follow:
#7
: is selected if the macro #PLAY_RAINING_TACOS
returns True
.
#17
: adds #PLAY_RAINING_TACOS
to the macro dictionary.
It is possible to make our system actually sings instead of prompting the lyric. Let us first install the VLC package:
Then, import the package and update the MacroPlayRainingTacos
macro to play the MP3 file, resources/raining_tacos.mp3:
#1
: imports the VLC package.
#6
: creates a VLC media player and plays the specified MP3 file.
When you run the above dialogue flow, it now plays the MP3 file and prompts the lyric.
The transitions in Section 4.1 prompt the same time (3PM) upon every request. Let us create a new macro that checks the current (system) time:
#1
: imports the time package.
#5
: retrieves the current time in the specified format using the strftime
method.
#6
: returns the current time using the str.format
method.
The macro MacroTime
can be called to generate the system output:
#11
: calls the TIME
macro to generate the system output displaying the current time.
#22
: adds #TIME
to the macro dictionary.
The transitions in Section 4.1 prompt the same weather (sunny) upon every request. Let us retrieve the latitude and the longitude of the system using Google Maps:
Then, use a web API provided by the National Weather Service to retrieve the grid correlates to the coordinate: https://api.weather.gov/points/33.7904,-84.3266
Look for the forecast
field under properties
: https://api.weather.gov/gridpoints/FFC/52,88/forecast
Write a macro that retrieves the current weather for the grid using another web API:
#1
: imports the json package.
#2
: imports the requests package.
#6
: specifies the forecast URL.
#7
: retrieves the content from the URL in JSON.
#8
: saves the JSON content to a dictionary.
#9
: retrieves forecasts for all supported periods.
#10
: retrieves the forecast for today.
#11
: returns today's forecast.
Finally, update the transitions with the weather macro:
#15
: calls the WEATHER
macro to generate the system output displaying today's weather.
#22
: adds #WEATHER
to the macro dictionary.
The time and the weather retrieved by the above macros are oriented to the system, not the user. It is possible to anticipate the users' location if one's IP address is provided; however, this is not possible unless the user uses a specific device (e.g., Amazon Echo, smartphone) and agrees to send one's private information to our system.
A dialogue flow can be complex when you start adding multiple topics. In this case, you can create a separate transition dictionary for each topic.
Let us create transitions talking about music and movies:
#3
: directs to the music
state.
#4
: directs to the movie
state.
The music
and movie
states can be defined in separate transition dictionaries:
#5
: directs to the start
state.
#8
: directs to the movie
state.
#5
: directs to the start
state.
#8
: directs to the music
state.
Finally, all three transition dictionaries can be loaded to the same dialogue flow:
When the dialogue flow runs, it randomly selects one of the 3 states, music
, movie
, and end
:
#1
: randomly selects the music
state.
#3
: switches to the movie
state when it does not understand the user input.
#5
: switches to the music
state when it does not understand the user input.
#7
: goes back to the start
state when it understands the user input, and randomly selects the movie
state.
#9
: goes back to the start
state when it understands the user input, and randomly selects the music
state.
#11
: goes back to the start
state when it understands the user input, and randomly selects the end
state.
#1
: randomly selects the end
state and terminates the dialogue.
The randomness in the above transitions can be quite annoying because it may end the dialogue immediately after it runs or repeats the same topic over and over. This can be alleviated by using the #GATE
built-in macro:
#3
: puts the music topic to an open gate.
#4
: puts the movie topic to an open gate.
#4
: has no gate to open (so it can be selected at any time).
Once an output is selected, #GATE
closes the door for that output such that it will never be selected again.
It is important to have at least one output with no gate; otherwise, the system will crash unless one of the outputs leads to the end state.
The gating prevents the system from repeating the same topic, but the end
state can still be selected at any time without consuming all the other topics. To ensure that the end
state gets selected last, we use scoring:
#6
: indicates that this is the end
state.
#7
: assigns the score of this state to 0.1
.
By default, all states receive a score of 1; thus, assigning a score below 1 would make that state not selected at all unless there are dynamic scoring changes through macros such as #GATE
.