Finding Assigned Intents / Parsing Annotations

It is sometimes useful within a solution to extract information which is stored in annotations - for example to find the top intent or list all matched intents.

In these examples we will show code snippets which extract information about matched classes - however the same approach would apply for any annotations, just requiring a change of filter text / method.

These snippets should be added to either

  • Global Pre-Listener - if they should only be optionally executed, depending on input
  • Pre-Matching script - if they should always be executed for every input

Basic Information: All Matched Class Names

If we are only interested in the names of the annotations - then we can use the names property and filter for the subset we require:

_.inputAnnotations.names.findAll { it.endsWith('.INTENT') }

This will return the names of all the intent annotations:

[TDR_MY_NAME_IS_ANNA.INTENT, FLIGHT_BOOKING.INTENT, WEATHER_FORECAST.INTENT]

Additional Known Information: All Intents w/ Confidence

If we know that the annotation contains additional useful information in it’s variables - then we can take a slightly different approach and iterate the annotation objects themselves (using the getAll method) - filtering on name as before. Then we can call any method of the annotation object directly, for example to get the sentence index and value of the confidence variable as well:

def intents_with_confidence = _.inputAnnotations
    .all
    .findAll { it.name.endsWith('.INTENT') }
    .collect { [name: it.name, sentence: it.sentenceIndex, confidence: it.variables['confidence']] }

[[name:TDR_MY_NAME_IS_ANNA.INTENT, sentence:0, confidence:0.2317, order:0], [name:FLIGHT_BOOKING.INTENT, sentence:0, confidence:0.1355, order:1], [name:WEATHER_FORECAST.INTENT, sentence:0, confidence:0.1345, order:2]]

Single Annotation: Top Intent

In case where we know there is only 1 match it would make sense to use find instead of findAll as this returns an object (the first match) instead of a collection (of all matches):

def top_intent_annotation = _.inputAnnotations.all.find { it.name.endsWith('.TOP_INTENT') }
def top_intent = [name: top_intent_annotation.name, confidence: top_intent_annotation.variables['confidence']]

[name:TDR_MY_NAME_IS_ANNA.INTENT, confidence:0.2317]

All Known Information: All Intents w/ All variables

In some cases - especially during development when the final data formats are not fully realised it can be useful to extract all the information associated with an annotation for outputting to tryout or for further processing.

This can be done with a bit of extra processing in the collect closure:

    .collect {
        def annotation = [name: it.name, sentence: it.sentenceIndex]
        it.variables.each { variable -> annotation[variable.key] = variable.value }
        return annotation
    }

Bonus: Strip Suffix

In all these cases we are listing the intent annotation names - but what if we really want the class name and just want to use the suffix to find them?

Then we can use groovy’s range with a negative end index (0..-X) syntax to get the name from the start until X characters before the end:

def suffix = ".INTENT"
_.inputAnnotations.names.findAll { it.endsWith(suffix) }.collect { it[0..-(suffix.size()+1)] }

[TDR_MY_NAME_IS_ANNA, FLIGHT_BOOKING, WEATHER_FORECAST]

(here we use the simple name example for simplicity - but the same functionality could be added in the collect if more information was required)

3 Likes