HomePage Forums General Forum News & Announcements Intent Parser

Viewing 1 post (of 1 total)
  • Author
  • #599

    I just uploaded a pull request containing the new TTI (Text To Intent) class. If anyone is willing to test this branch, you can clone it with the command:

    git clone -b intent_parsers https://github.com/aaronchantrill/Naomi.git

    This allows you to work with three different intent parsers. If you want to use the Adapt or Padatious plugins, you have to install the “adapt-parser” and “padatious” modules, either with pip3 or whatever your favorite method is for extending python3.

    Padatious also requires the FANN2 (Fast Artificial Neural Network) development library to be installed on your system. If you are using a debian derivative, you should use apt install python3-fann2 to install both the fann dev libraries and the python fann module and then use pip3 to install Padatious. If you try to just install the libfann-dev deb package, the python3 fann module won’t look in the right place for the sources by default, which can be frustrating.

    The Naomi intent parser is written in python. It may require you to install the jiwer module, which is used to calculate Levenshtein distances (number of changes required to transform one sequence to another) which is used as a measure of error to minimize when calculating which intent is closest to what the user just said.

    If you want to use the Adapt or Padatious intent parsers, you currently need to edit your profile.yml file and add a line like:

    tti_engine: Adapt TTI

    tti_engine: Padatious TTI

    The way all three of these work is you pass in a list of intents, then train the engine, then pass in a sentence and the intent parser tries to both figure out what plugin you are trying to activate, and do some pre-parsing to extract keywords.

    For instance, here is an example “Music” intent:

                'MusicIntent': {
                    'keywords': {
                        'ArtistKeyword': [
                            'third eye blind',
                            'the who',
                            'the clash'
                    'regex': {
                        'ArtistKeyword': [
                            "by (?P<ArtistKeyword>.*)$"
                    'templates': [
                        "play music by {ArtistKeyword}",
                        "play something by {ArtistKeyword}",
                        "play a song by {ArtistKeyword}",
                        "play music"
                    'action': self.handler

    This demonstrates all four major sections of an intent: “keywords”, “regex”, “templates” and “action”.

    Keywords are lists of words that Naomi should know, and which are passed to your STT dictionary if you are using pocketsphinx or julius. They should be all the same category. You can see that in the templates above, rather than make a separate template for each artist, they substitute the {ArtisKeyword} token which means any artist name can appear in that place.

    Artists other than ones you have thought of and added to Keywords can also be specified, although with local STT parsers like Pocketsphinx or Julius it can be difficult for Naomi to understand their names. But if you use Naomi with the –local flag, you could type in “play the dead” and the intent parser would probably extract “the dead” as the band name.

    Padatious and Naomi both use word analysis and sentence structure when figuring out an intent, but Adapt works pretty differently, only looking at the presence or absence of individual words when figuring out the intent. This makes it difficult to extract a word by position within the sentence. That is why Adapt also uses regex (we may also add the ability to use regex to the “Naomi TTI” parser at some point in the future). As you can see above, all of the templates that include an ArtistKeyword have it appear at the end of the phrase and after the word “by”. The intent author used this to create a regex that matches anything between the word “by” and the end of the phrase (“$”) and return it as ArtistKeyword.

    Finally, when an intent is selected as the most likely match for the input, the “action” is called with the intent result and “mic” so the handler can use the mic to “say” a response.

    Speaking of intent results, if we train Naomi with the intent above, and then say “Naomi, play the who” we could expect to get something like this back:

    {‘action’: at 0x7f3612b900d0>,
    ‘input’: ‘play the who’,
    ‘matches’: {‘ArtistKeyword’: [‘the who’]},
    ‘score’: 1.0}}`

    This is passed back to our plugin’s “handler” function as the first parameter. The handler function should always be declared as
    def handler(self, intent, mic):
    to be ready to be selected.

    The parts of the intent result are the Intent used to generate the result, in this case “MusicIntent”, the action method (which should be the method being executed), the list of matches (in this case Naomi has identified “the who” as the only member of the ArtistKeyword type) and a score (which shows how confident Naomi is about having selected the particular intent).

Viewing 1 post (of 1 total)

You must be logged in to reply to this topic.