Annotate user inputs

If you want to match on dynamic details in the user input that would be hard to maintain in a language object, you might want to use annotations.

Annotations in Teneo can be considered 'labels' that are attached to inputs. Some annotations are created automatically by Teneo, but you can also dynamically add them using scripts.

As an example, on this page we will use annotations to 'label' promotion codes in a user input. These promotion codes are stored in a global variable and we are going to assume this variable is dynamically populated through an API or something similar.

The following 2 steps are needed to annotate the user input with the promotion codes:

  1. Create a global variable and populate it with a list of promotion codes
  2. Create a global listener that will listen for all user inputs and a script that inspects each word in the user input. If the word is in the list of promotion codes, it should add the annotation VALID_PROMO_CODE

Add a global variable

First, we need to create a global variable that we will assume has been populated dynamically with promotion codes for Longberry baristas:

  1. Go to the solutions backstage by clicking on 'Solution' in the top right.
  2. Click on 'Globals' in the panel to the left.
  3. Go to 'Variables'.
  4. Add a new variable and give it the name validPromoCodes.
  5. Then give it this value:

    ["mvkn","vuyo","2ppu","lqgp","ym5b","634q","g2gl"]

  6. Hit 'Save'.

Add the annotation script to a global listener

Next, we need to set up a global pre listener so that we can annotate the user input before it is tested against flow triggers and transitions.

  1. Click on the 'Solution' tab in the top left.
  2. Click on 'Globals'.
  3. Select 'Listeners'.
  4. Go to the green 'Add' icon, open the drop-down menu and select 'Pre listener' to add a new pre-listener.
  5. Name it Find valid promotion codes. Then click the left arrow at the top.
  6. Paste the kleene star * into the condition field. This will match on everything since we want to inspect every input for valid promotion codes.
  7. Add the following script in the 'Execute this script' field. (Details on the script can be found below):
    def n = _.sentenceCount  // get the number of sentences
    // iterate through the sentences
    for (int si = 0; si < n; si++) {
        // iterate through each word in the sentence
        _.sentences[si].words.eachWithIndex { word, wordIndex ->
            if (validPromoCodes.contains(word.getOriginal().toString())) {
                // if lookup value is true then we annotate the 'range' that matched the list.
                _.inputAnnotations.add(_.createInputAnnotation("VALID_PROMO_CODE", si, [wordIndex] as HashSet, ["Promo code": word.getOriginal().toString()]))
            }
        }
    }
  8. Save using the 'Save' button in the top left of the editing window.
  9. Go back to the main solution window and reload the engine in try out.

Give it a try and inspect the annotations

We are now annotating promotion codes using a global pre listener, which means language conditions can now use the custom annotation %$VALID_PROMO_CODE to check if a user input contains a valid promotion code.

We can also inspect the annotation in the 'Response Info' panel:

  1. In the main solution window, open the 'Response Info' panel on the right hand side.
  2. Type mvkn into Try out. This is a valid promo code and will be annotated accordingly.
  3. In the 'Response Info' panel under 'Input Summary' you can see what Teneo annotated, including your customized annotation %$VALID_PROMO_CODE.

If you hover over an annotation, you will get extra information (if there is any) from the annotation variables.

Explanation of the script

Let's have a detailed look at the script that we used:

def n = _.sentenceCount  // get the number of sentences
// iterate through the sentences
for (int si = 0; si < n; si++) {
    // iterate through each word in the sentence
    _.sentences[si].words.eachWithIndex { word, wordIndex ->
        if (validPromoCodes.contains(word.getOriginal().toString())) {
            // if lookup value is true then we annotate the 'range' that matched the list.
            _.inputAnnotations.add(_.createInputAnnotation("VALID_PROMO_CODE", si, [wordIndex] as HashSet, ["Promo code": word.getOriginal().toString()]))
        }
    }
}

Here is what the script does:

  1. First, we get the number of sentences in the input and iterate through the sentences. We do this because we need to provide the sentence number when we add an annotation.
  2. For each sentence, we iterate through its words. We get the word and the words' index. This is done via the eachWithIndex iterator.
  3. Next we check if the word exists in the global list. If so, we annotate the word in the sentence at wordIndex and create a annotation variable Promo code with the found promo code as a annotation value to Promo code, like so:

Image of the input annotation annotated image

The script uses a number of Engine scripting API methods:

Engine scripting api (Java) Engine scripting api (Groovy) Description
_.getSentenceCount() _.sentenceCount Returns the number of sentences in the user input.
_.getSentences() _.sentences Returns an unmodifiable view of the sentences and their words, generated from the user input text.
getWords() words Returns the words of this sentence
_.getInputAnnotations().add(...) _.inputAnnotations.add(...) Adds the given annotation to the annotations data
_.createInputAnnotation(...) _.createInputAnnotation(...) Creates a user input Annotation object with the given data.

Was this page helpful?