arrow-left

All pages
gitbookPowered by GitBook
1 of 1

Loading...

4.2. Advanced Interaction

hashtag
Built-in Macros

Besides #ONT for checking an ontology, STDM provides several macros useful for dialogue design.

hashtag
#LEM

The following example shows a use case of the macro #LEM that uses the to match lemmas of "raining tacos":

  • #5: maches the input with the lemma of "rain" or "rainy", then the lemma of "taco".

hashtag
#UNX

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.

triangle-exclamation

Seldomly, #UNKgets 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 to the #UNK state to ensure it gets the lowest priority among other branches.

hashtag
#SET & #IF

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.

circle-info

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

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:

  • #3: the method in returns the value corresponding to the key, RAINING_TACOS if exists; otherwise, False.

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.

hashtag
Music

It is possible to make our system actually sings instead of prompting the lyric. Let us first install the package:

Then, import the package and update the MacroPlayRainingTacos macro to play the MP3 file, :

  • #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.

hashtag
Time

The transitions in prompt the same time (3PM) upon every request. Let us create a new macro that checks the current (system) time:

  • #1: imports the package.

  • #5: retrieves the current time in the specified format using the method.

  • #6

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.

hashtag
Weather

The transitions in prompt the same weather (sunny) upon every request. Let us retrieve the latitude and the longitude of the system using :

Then, use a web API provided by the to retrieve the grid correlates to the coordinate:

  • Look for the forecast field under properties:

Write a macro that retrieves the current weather for the grid using another web API:

  • #1: imports the package.

  • #2: imports the package.

  • #6

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.

circle-info

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.

: checks if the argument is a proper boolean value.
  • #14: stores the boolean value to the variable.

  • : returns the current time using the
    method.
    : 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.

  • S: What can I do for you?
    U: Play raining tacos
    S: It's raining tacos. From out of the sky ... What can I do for you?
    U: Play raining taco
    S: It's raining tacos. From out of the sky ... What can I do for you?
    U: Play rain taco
    S: It's raining tacos. From out of the sky ... What can I do for you?
    U: Play rainy taco
    S: It's raining tacos. From out of the sky ... What can I do for you?
    U: Bye
    S: Sorry, I didn't understand you.
    NLTK Lemmatizerarrow-up-right
    score
    get()arrow-up-right
    dictarrow-up-right
    VLCarrow-up-right
    resources/raining_tacos.mp3arrow-up-right
    Section 4.1
    timearrow-up-right
    strftimearrow-up-right
    Section 4.1
    Google Mapsarrow-up-right
    National Weather Servicearrow-up-right
    https://api.weather.gov/points/33.7904,-84.3266arrow-up-right
    https://api.weather.gov/gridpoints/FFC/52,88/forecastarrow-up-right
    jsonarrow-up-right
    requestsarrow-up-right
    Mathematics and Science Center at Emory University (400 Dowman Dr, Atlanta, GA, 30322)
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '`It\'s raining tacos. From out of the sky ...`': 'start'
            },
            'error': {
                '`Sorry, I didn\'t understand you.`': 'end'
            },
        }
    }
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '`It\'s raining tacos. From out of the sky ...`': 'start'
            },
            '#UNX': {
                '`Thanks for sharing.`': 'end'
            },
        }
    }
    S: What can I do for you?
    U: My name is Jinho
    S: Right. Thanks for sharing. What can I do for you?
    U: I am a professor
    S: Yeah. Thanks for sharing. What can I do for you?
    U: Hello world
    S:  Thanks for sharing. What can I do for you?
    U: Play raining tacos
    S: It's raining tacos. From out of the sky ...
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '#IF($RAINING_TACOS=True) `Don\'t make me sing this again!`': 'start',
                '`It\'s raining tacos. From out of the sky ...` #SET($RAINING_TACOS=True)': 'start',
            },
            '#UNX': {
                '`Thanks for sharing.`': 'start'
            },
        }
    }
    S: What can I do for you?
    U: Play raining tacos
    S: It's raining tacos. From out of the sky ...   What can I do for you?
    U: Play raining tacos
    S:  Don't make me sing this again! What can I do for you?
    ...
    class MacroSetBool(Macro):
        def run(self, ngrams: Ngrams, vars: Dict[str, Any], args: List[str]):
            if len(args) != 2:
                return False
    
            variable = args[0]
            if variable[0] == '$':
                variable = variable[1:]
    
            boolean = args[1].lower()
            if boolean not in {'true', 'false'}:
                return False
    
            vars[variable] = bool(boolean)
            return True
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '#IF($RAINING_TACOS) `Don\'t make me sing this again!`': 'start',
                '`It\'s raining tacos. From out of the sky ...` #SETBOOL(RAINING_TACOS, True)': 'start',
            },
            '#UNX': {
                '`Thanks for sharing.`': 'start'
            },
        }
    }
    
    macros = {
        'SETBOOL': MacroSetBool()
    }
    class MacroPlayRainingTacos(Macro):
        def run(self, ngrams: Ngrams, vars: Dict[str, Any], args: List[str]):
            return not vars.get('RAINING_TACOS', False)
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '#IF($RAINING_TACOS) `Don\'t make me sing this again!`': 'start',
                '#IF(#PLAY_RAINING_TACOS) `It\'s raining tacos. From out of the sky ...` #SETBOOL(RAINING_TACOS, True)': 'start',
            },
            '#UNX': {
                '`Thanks for sharing.`': 'start'
            },
        }
    }
    
    macros = {
        'SETBOOL': MacroSetBool(),
        'PLAY_RAINING_TACOS': MacroPlayRainingTacos()
    }
    
    df = DialogueFlow('start', end_state='end')
    df.load_transitions(transitions)
    df.add_macros(macros)
    df.run()
    S: What can I do for you?
    U: Play raining tacos
    S:  It's raining tacos. From out of the sky ...    What can I do for you?
    U: Play raining tacos
    S:  Don't make me sing this again! What can I do for you?
    U: Play raining tacos
    S:  Don't make me sing this again! What can I do for you?
    ...
    pip install python-vlc
    import vlc
    
    class MacroPlayRainingTacos(Macro):
        def run(self, ngrams: Ngrams, vars: Dict[str, Any], args: List[str]):
            if not vars.get('RAINING_TACOS', False):
                vlc.MediaPlayer("resources/raining_tacos.mp3").play()
                return True
            return False
    import time
    
    class MacroTime(Macro):
        def run(self, ngrams: Ngrams, vars: Dict[str, Any], args: List[str]):
            current_time = time.strftime("%H:%M")
            return "It's currently {}.".format(current_time)
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '#IF($RAINING_TACOS) `Don\'t make me sing this again!`': 'start',
                '#IF(#PLAY_RAINING_TACOS) `It\'s raining tacos. From out of the sky ...` #SETBOOL(RAINING_TACOS, True)': 'start',
            },
            '[{time, clock}]': {
                'state': 'time',
                '#TIME': 'end'
            },
            '#UNX': {
                '`Thanks for sharing.`': 'start'
            },
        }
    }
    
    macros = {
        'SETBOOL': MacroSetBool(),
        'PLAY_RAINING_TACOS': MacroPlayRainingTacos(),
        'TIME': MacroTime()
    }
    S: What can I do for you?
    U: What time is it now?
    S: It's currently 05:27.
    {
        ...,
        "properties": {
            "@id": "https://api.weather.gov/points/33.7904,-84.3266",
            ...,
            "forecast": "https://api.weather.gov/gridpoints/FFC/52,88/forecast",
            ...
        }
    }
    import json
    import requests
    
    class MacroWeather(Macro):
        def run(self, ngrams: Ngrams, vars: Dict[str, Any], args: List[Any]):
            url = 'https://api.weather.gov/gridpoints/FFC/52,88/forecast'
            r = requests.get(url)
            d = json.loads(r.text)
            periods = d['properties']['periods']
            today = periods[0]
            return today['detailedForecast']
    transitions = {
        'state': 'start',
        '`What can I do for you?`': {
            '[play, [!{#LEM(rain), rainy}, #LEM(taco)]]': {
                'state': 'play_raining_tacos',
                '#IF($RAINING_TACOS) `Don\'t make me sing this again!`': 'start',
                '#IF(#PLAY_RAINING_TACOS) `It\'s raining tacos. From out of the sky ...` #SETBOOL(RAINING_TACOS, True)': 'start',
            },
            '[{time, clock}]': {
                'state': 'time',
                '#TIME': 'end'
            },
            '[{weather, forecast}]': {
                'state': 'weather',
                '#WEATHER': 'end'
            },
            '#UNX': {
                '`Thanks for sharing.`': 'start'
            },
        }
    }
    
    macros = {
        'SETBOOL': MacroSetBool(),
        'PLAY_RAINING_TACOS': MacroPlayRainingTacos(),
        'TIME': MacroTime(),
        'WEATHER': MacroWeather()
    }
    S: What can I do for you?
    U: How is the weather today?
    S: A chance of rain showers. Cloudy, with a high near 68. South wind 0 to 5 mph. Chance of precipitation is 30%.
    str.formatarrow-up-right