Condition Syntax Reference
A language condition specifies patterns that need to be present in a user input for the condition to be fulfilled. Depending on where the condition is used, a match may result in a flow being triggered, a transition being selected, or a listener being applied.
There are two types of conditions: atomic conditions, which can be used on their own, and complex conditions, which are a combination of one or more conditions and an operator.
Atomic Conditions
The smallest building block of a condition is an atomic condition. The different types of atomic conditions are:
- Word Conditon
- Word Part Condition
- Language Object Condition
- Annotation Condition
- Script Condition
Word Condition
A word condition simply specifies a word that needs to be present in the user input.
Condition | Matched user input | Unmatched user input |
---|---|---|
love | love | loves |
I love tofu | He loves me |
Word Part Condition
A word part condition specifies a part of a word that needs to be present in the input. A wildcard (*) is added at the beginning and/or end of the word, and means that the word may contain any number of other characters at that point.
The wildcard may also be used by itself to represent a single word.
Condition | Matched user input | Unmatched user input |
---|---|---|
love* | lover | beloved |
loved | glove |
Condition | Matched user input | Unmatched user input |
---|---|---|
*love | glove | lover |
clove | clover | |
love | beloved |
Condition | Matched user input | Unmatched user input |
---|---|---|
*love* | beloved | luv |
clover | ||
love |
Condition | Matched user input | Unmatched user input |
---|---|---|
I + love + * | I love tofu | I love |
I love cats | It's you who I love | |
I love martial arts |
Language Object Condition
A language object condition specifies a language object that needs to match the user input. If we have a language object named 'FRUITS.LIST' with a condition like: (banana/apple/pear) the following applies:
Condition | Matched user input | Unmatched user input |
---|---|---|
%FRUITS.LIST | banana | cucumber |
May I have an apple? | May I have a tomato? |
Language objects are themselves containers of language conditions. They are described at more length here.
Annotation Condition
An annotation condition specifies a label that a word (or sequence of words) must have been annotated with. An annotation condition is thus not applied to the input words themselves, but to annotation labels. Teneo comes with several different annotators:
- a Part of Speech tagger that annotates each word in the input with its Part of Speech,
- a set of Named Entity Recognizers that annotate words (or word sequences) as persons, locations, or similar,
- a Language Detector that annotates each sentence with the language it is written in.
A full list of all annotations and entities can be found in the Annotations Reference.
Conditions are used on annotation labels the same way they are used on language objects; it's just the prefix that looks slightly different. An annotation label should be prefixed with %$.
Condition | Matched user input | Unmatched user input |
---|---|---|
%$LOCATION.NER | Berlin | app |
open Berlin on a map | open my favorite app |
Script Condition
You may use a Groovy script as a condition. It needs to be embraced with curly brackets ({ ... }). For a Script condition to be fulfilled, the result of the expression evaluation has to have a Boolean value of true. If the result type is not a Boolean, then it is converted to Boolean according to Groovy’s type conversion rules.
Condition | Matched user input | Unmatched user input |
---|---|---|
{ coffeeTypeInFocus == 'espresso' } | The variable 'coffeeTypeInFocus' has the value 'espresso'. The input words are irrelevant. | The variable 'coffeeTypeInFocus' does not have the value 'espresso'. The input words are irrelevant. |
Basic operators
You can combine conditions with operators to form more complex conditions. In this section we'll go through the most commonly used, basic operators.
Note that a complex condition may in turn be combined with another condition, to form another complex condition. You then use brackets to show how the condition should be read:
`( %I_LOVE.PHR / %I_LIKE.PHR ) + %ANIMALS.LIST`
OR ( / )
When conditions are combined with the OR-operator (/), at least one of them needs to match the input.
Condition | Matched user input | Unmatched user input |
---|---|---|
dog / cat / hamster / parakeet / goldfish | I have a dog | I don't like cats or dogs |
I used to have a cat | ||
I don't have a parakeet |
AND ( & )
Conditions that are combined with the AND-operator (&) must all match the input. The AND-operator does not require the words in the input to appear in a certain order.
Condition | Matched user input | Unmatched user input |
---|---|---|
I & love & you | I love you | everyone loves you |
you are the person whom I love |
FOLLOWED BY ( + )
Conditions that are combined with the FOLLOWED BY-operator (+) must all match the input, in the order stated. The operator is a good choice for word combinations whose sense would shift if the word order were rearranged.
Condition | Matched user input | Unmatched user input |
---|---|---|
John + loves + Anna | John loves Anna | Anna loves John |
John really loves his girlfriend Anna |
DIRECTLY FOLLOWED BY ( >> )
Conditions combined with the DIRECTLY FOLLOWED BY-operator (>>) must all match the input, in the order stated. There may not come any words between the matches.
Condition | Matched user input | Unmatched user input |
---|---|---|
I >> love >> you | I love you | I don't love you. |
I love you now and always! | I said he'll always love you |
NOT DIRECTLY FOLLOWED BY ( !>>)
When two conditions are combined with the NOT DIRECTLY FOLLOWED BY-operator (!>>), the left side condition must match the user input, and the right side condition must NOT match the words immediately following the first match.
The right side condition does not have to match anything in the input, it's merely restricting the left side condition.
In this example we're looking for inputs containing the word 'call' not directly followed by 'you'.
Condition | Matched user input | Unmatched user input |
---|---|---|
call !>> you | I want to call John | I want to call you John |
I want you to make a call |
NOT (!)
The NOT-operator (!) takes only one condition, and states that whatever is specified in that condition must not match the user input.
Condition | Matched user input | Unmatched user input |
---|---|---|
!cat | I have a dog | I don't have a cat |
I love cats | Are you a cat? |
Condition | Matched user input | Unmatched user input |
---|---|---|
(I+love+you) & !(%DO_NOT.VB.MUL) | I love you | I don't love you |
COMPOUND ( | )
The COMPOUND-operator (|) allows compound words to be written in a variety of ways: as one word, with a hypen or with a blank. The COMPOUND-operator can only be used to combine atomic word conditions. This means that a condition like %LANGUAGE_OBJECT|%LANGUAGE_OBJECT is syntactically wrong.
Condition | Matched user input | Unmatched user input |
---|---|---|
dog | house | We have a doghouse |
We have a dog-house | ||
We have a dog house |
Extendend AND-operators
Extended AND-operators are different variations of the AND-operator. Just as for the basic AND-operator (&), both the left side condition and the right side condition must match the user input.
In addition, they impose some restrictions on the words (or corresponding annotations) that these conditions have been applied to. For example, when using the SAME MATCH-operator (&=) the conditions must have been applied to the same part of the input, whereas, for the DIFFERENT MATCH-operator (&^), the conditions must have been applied to different parts of the input.
In the example below, apple is part of both the language objects FRUITS.LIST and COMPANY_NAMES.LIST:
Condition | Matched user input | Unmatched user input |
---|---|---|
%COMPANY_NAMES.LIST &= %FRUITS.LIST | apple | microsoft banana |
%COMPANY_NAMES.LIST &^ %FRUITS.LIST | microsoft banana | apple |
apple apple |
DIFFERENT MATCH ( &^ )
The DIFFERENT MATCH-operator (&) is conceptually very similar to the basic AND-operator. The only difference is that the left side condition and the right side condition must have been applied to different parts of the input (for the basic AND-operator that does not have to be the case).
In the example below, we want to make sure there are two cities mentioned in the input (if we would have used the basic AND-operator a single mention would have satisfied both conditions).
Condition | Matched user input | Unmatched user input |
---|---|---|
%CITIES.LIST &^ %CITIES.LIST | Berlin Paris | Berlin |
SAME MATCH ( &= )
When you combine two conditions with the SAME MATCH-operator (&=), both conditions need to match the input. In addition, these conditions must have been applied to the same words (or corresponding annotations) in the input.
This operator is particularly useful when you want to constrain both the word itself, and the annotation it's been annotated with. In this example we're looking for a synonym of the word buy (%BUY.VB.SYN) that is annotated as past tense (%$PAST.POS).
Condition | Matched user input | Unmatched user input |
---|---|---|
%BUY.VB.SYN &= %$PAST.POS | I bought a t-shirt | I'd like to buy a t-shirt |
I have purchased a sweater | I want to purchase a sweater |
Here we're looking for something that both matches a list of German cities, and a list of airline destinations (this particular airline does fly to Berlin, but not to Hannover).
Condition | Matched user input | Unmatched user input |
---|---|---|
%CITIES_GERMANY.LIST &= %AIRLINE_DESTINATIONS.LIST | A ticket to Berlin please | I want to go to Paris please. |
Take me to Hannover please. |
BIGGER MATCH ( &>)
When you combine two conditions with the BIGGER MATCH-operator (&>), both conditions need to match the input. In addition, the left side condition must have been applied to all the words (or annotations at the corresponding positions) of the right side condition, and possibly some more. In other words, the match of the right side condition must be fully contained in the match of the left side condition.
This operator is particularly useful when you want to limit the scope of a list to only cover items that contain a specific word. In this example we're looking for printers that are both listed among the supported ones and contain the string 'epson' in their names.
Condition | Matched user input | Unmatched user input |
---|---|---|
%SUPPORTED_PRINTERS.LIST &> epson | I need the documentation for Epson 202X | Where do I download a driver for HP 202XXL? |
Where do I download a driver for Epson SSLX? |
Here we're looking for car brands that contain the word 'hybrid'.
Condition | Matched user input | Unmatched user input |
---|---|---|
%CAR_BRANDS.LIST &> hybrid | Honda Accord Hybrid | Subaru Forrester |
Ford Fusion Hybrid |
SMALLER MATCH ( &< )
When you combine two conditions with the SMALLER MATCH-operator &<, both conditions need to match the input. In addition, the match of the left side condition must be fully contained in the match of the right side condition. The right side match may contain also other words/annotations.
The example below matches American cities that are mentioned as parts of movie titles.
Condition | Matched user input | Unmatched user input |
---|---|---|
%CITIES_USA.LIST &< %MOVIE_TITLES.LIST | The movie Fear and Loathing in Las Vegas | I like going around loathing in Las Vegas |
Have you ever seen Escape from New York? | The Lord of the Rings is a great film |
OVERLAP MATCH ( &~ )
When you combine two conditions using the OVERLAP MATCH-operator &~, the conditions on the left and right must share at least one used word. You could use this to require an optional condition part on the left side of the condition to be present. This can be useful if the optional condition is part of a referenced language object.
This example shows how you might use a list of US states to catch that users are referring to a state university.
Condition | Matched user input | Unmatched user input |
---|---|---|
(alaska / california / ohio)>>(state):O) &~ state | I attend Ohio State | I live in Ohio |
California State has a great football team | Hollywood is in the state of California |
Negated AND-operators
Negated AND-operators are useful when you want to specify something to be matched, and then add a constraint on that match.
Common to all negated AND-operators is that they consist of a left side condition that MUST match the input and a right side condition that impose some kind of restriction on that match — something that may NOT match all, a subset, or a superset of those words.
NOT SAME MATCH ( !&= )
When you combine two conditions with the NOT SAME MATCH-operator (!&=), the left side condition must match the input. The right side condition specifies something that must NOT match those exact same words (or their annotations).
You can thus use this operator when you're looking for something that SHOULD match on something particular, but SHOULD NOT match on something different.
In this example, we're looking for a European city that is not a German city (i.e. any non-German European city).
Condition | Matched user input | Unmatched user input |
---|---|---|
%CITIES_EUROPE.LIST !&= %CITIES_GERMANY.LIST | I want to go to Paris | I want to go to Berlin |
I want to go to Paris from Berlin |
Here the user input should contain the word 'play' not annotated as a noun:
Condition | Matched user input | Unmatched user input |
---|---|---|
play !&= %$NN.POS | I want to play some music | I am going to see a play in the theater |
I want to play in a play |
Finally, in this example, any word normalized to meta matches, except when it's written exactly as Metà (more on the Exact option (:E) here) :
Condition | Matched user input | Unmatched user input |
---|---|---|
meta !&= Metà:E | It is a meta question | We attended the Metà conference |
It is a META question |
NOT BIGGER MATCH ( !&> )
When you combine two conditions with the NOT BIGGER MATCH-operator (!&&g;) the left side condition must match the input. The right side condition specifies a constraint on that match — it specifies something that may NOT be part of that match.
You can thus use this operator when you want to restrict the coverage of a language object. In this example we want to match variations of how do I install, but we want to exclude variations that contain the word add.
Condition | Matched user input | Unmatched user input |
---|---|---|
%HOW_DO_I_INSTALL.PHR !&> %ADD.VB.LEX | How do I install the driver? | How can I add this gizmo? |
Can you help me installing the app? |
This example will match as long as what is matched by * isn’t also matched by COLORS.LIST.
Condition | Matched user input | Unmatched user input |
---|---|---|
(%I_NEED.PHR >> %NUMBERS.LIST >> * >> %MY_PRODUCTS.LIST) !&> %COLORS.LIST | I need 5 new brackets | I need five green brackets |
I really need 7 new shelves |
NOT SMALLER MATCH ( !&< )
When you combine two conditions with the NOT SMALLER MATCH-operator (!&<), the left side condition must match the input. The right side condition specifies a constraint on that match — it specifies a condition that must NOT generate a match that fully contains the first match.
You can thus use this operator when you want to constrain the context of a match. In this example we're looking for the phrase more than but we want to disqualify any match that is part of the longer phrase no more than.
Condition | Matched user input | Unmatched user input |
---|---|---|
(more>>than) !&< (no>>more>>than) | A word with more than ten letters | A word with no more than ten letters |
Here we're looking for matches of I like, but we want to disregard matches that also contain don't.
Condition | Matched user input | Unmatched user input |
---|---|---|
(I + like) !&< (I + %DO_NOT.MUL + like) | I really like all vegetables | I don't like vegetables |
In this example, we're looking for the word nice when not preceded by to, via, or from:
Condition | Matched user input | Unmatched user input |
---|---|---|
nice !&< (( to/via/from) >> nice) | Such a nice day! | I go via Nice |
So nice to see you! | I fly out from nice. |
NOT OVERLAP MATCH ( !&~)
When you combine two conditions with the NOT OVERLAP MATCH-operator (!&~), the left side condition must match the user input. The right side condition specifies a restriction on that match — it specifies something it may not overlap with.
You can thus use this operator when you want to constrain the context of a match. In this example, we're looking for the phrase can you close but we want it to be disqualified if it's overlapping with a match of why can.
Condition | Matched user input | Unmatched user input |
---|---|---|
(can + you + close ) !&~ (why + can ) | Can you close an account | Why can you close an account |
Here we're looking for phrases like are you angry but want to keep out inputs like are you making me angry :
Condition | Matched user input | Unmatched user input |
---|---|---|
( %ARE_YOU.PHR + %ANGRY.ADJ.SYN) !&~ (me >> %ANGRY.ADJ.SYN) | Are you angry now? | Why are you making me angry? |
Limit unused words
Normally, a language condition only specifies which words must be present in an input. There may be other words in the input not accounted for by the condition, and the input will still satisfy the condition.
With 'Limit unused words' you can add restrictions on how many words besides those specified in the condition may be present in the user input. The option is available with a Conditional Match Requirement, under the 'Condition' panel inside 'Advanced Options'.
In the example below, we are looking for inputs that don't contain any words other than how are you.
Condition | Unused word limit | Matched user input | Unmatched user input |
---|---|---|---|
how + are + you | 0 | How are you? | How are you removing an item? |
How are you doing? |
Here we allow one unused word to appear:
Condition | Unused word limit | Matched user input | Unmatched user input |
---|---|---|---|
how + are + you | 1 | How are you? | How are you removing an item? |
How are you doing? | How are you doing dear? |
MAYBE option (~)
The MAYBE-operator (~) allows you to specify words that may appear in the input, but don't have to. These words won't count as unused words. They may appear any number of times and still not count.
Condition | Unused word limit | Matched user input | Unmatched user input |
---|---|---|---|
(how+are+you) ~(doing/feeling/dear/%HI.PHR) | 0 | How are you? | How are you removing an item? |
Hi dear, how are you doing? | |||
Hi, hi, hi, how are you doing? |
In the example below we are looking for inputs where the user asks for the price of something we've just talked about, e.g. What's the cost? or How much is it?. We want to exclude inputs where the user is asking for the price of some new referent, e.g. How much is the espresso?. We will thus limit the number of unused words to 0 and use the MAYBE-operator to specify that other words may be part of the input, as long as they are not annotated as nouns.
Condition | Unused word limit | Matched user input | Unmatched user input |
---|---|---|---|
%WHAT_IS_THE_PRICE_OF.PHR ~ ( * !&= %$NN.POS ) | 0 | How much is it? | How much is an espresso? |
What is the cost then? | What is the cost of the ticket | ||
What is the cost? | The new iPhone, what is the cost of it? |
The MAYBE-operator will always be applied to the full input, and allow any number of the specified words to appear in the input. It can't be used to specify optional elements at specific positions; for that, you should use the Optional Match option.
In short, the MAYBE-operator should only be used in conjunction with Limit unused words. For all other use cases, use the Optional Match option instead.
Optional Match option (:O)
When attaching the Optional Match option ( :O) to an element of a condition, it lets the enclosed atomic or complex condition become an optional part of the surrounding condition, hence the element doesn't have to match the input for the condition to be fulfilled, but it may.
Please note that the Optional Match option is only applicable to bracketed conditions.
Condition | Matched user input | Unmatched user input |
---|---|---|
I >> (really):O >> like >> you | I like you | I sometimes like you |
I really like you | I really really like you | |
I >> (will>>always):O + like + you | I like you | I will like you |
I will always like you | I always like you |
In the example below we use the Optional Match option to set the variable 'milk' when appropriate:
Condition | Matched user input | Unmatched user input |
---|---|---|
%ESPRESSO.NN.LEX & (with>>milk):O^{ milk = 'yes' } | an espresso with milk please | 'yes' |
an espresso please | '' |
Position option
The Position Option (:<sentence_position>) can be applied to a word condition or a word part condition. For the constrained condition to be fulfilled, the word must appear in the user input at the specified position in the sentence. The first word in the sentence has position 1. A position relative to the sentence end may be specified by giving a negative number; the last word on the sentence has position -1. Note that position value 0 is invalid.
Condition | Matched user input | Unmatched user input |
---|---|---|
play:1 | play a song | I saw a play |
play the track please | you play it too loud | |
who >> are >> you:-1 | who are you | who are you talking to |
Exact option (:E)
Generally, condition matching is case-insensitive. But when you use the Exact Option (:E), the word must appear in the input exactly as written in the condition; thus no normalization, spelling tolerance, auto-correction, or simplification is applied.
Please note:
- The Exact Option may only be applied to words or word part conditions. This means that a condition like %LANGUAGE_OBJECT:E is syntactically wrong.
- The Exact Option is not applicable to bracketed conditions: a condition like (one/two):E has invalid syntax and should be written as (one:E/two:E)
Condition | Matched user input | Unmatched user input |
---|---|---|
horse:E | horse | Horse |
hoarse | ||
*house:E | boathouse | BOATHOUSE |
DogHouse | ||
Love*:E | Loved | loved |
beloved |
Longest Match option (:L)
The Longest Match option offers additional fine-tuning useful when working with used words or attached scripts. When testing your bot and conditions, Teneo tries to be as efficient as possible. If a match for an input is found, the condition is considered to be true, and processing continues with the next steps. It usually does not matter if a condition could have been true in many different ways. However, there are special cases where it is necessary to know which parts of a user input triggered the condition. If we care about the used words or have attached scripts to parts of our condition, we want Teneo to find the most precise or longest match for that input. The longest match becomes important whenever we can have overlapping entities, that is, a multiple word entity which contains a word or words that are entities themselves. If a shorter match is chosen, we lose the additional information.
When attaching the Longest Match option (:L) to an element of a condition, it forces the enclosed atomic or complex condition to be true for the match using the most words possible.
Please note that the Longest Match option only is applicable to bracketed conditions.
Condition | Matched user input | Unmatched user input |
---|---|---|
(york / (new>>york) ):L | I want to book a flight to York. | York |
Can you recommend hotels in New York? | New York | |
( (hbo>>2) / (hbo>>comedy) / (hbo>>family) / (hbo>>latino) / (hbo>>signature) / (hbo>>zone) / hbo):L | I watch hbo | hbo |
How can I subscribe to HBO comedy? | HBO comedy |
In this example we use Longest Match to assure the correct value is set to the variable 'country':
Condition | Matched user input | Unmatched user input |
---|---|---|
((porto>>novo)^{country="Benin"} / ((porto>>alegre)/(porto>>velho))^{country="Brazil"} / (porto/(porto>>de>>mós))^{country="Portugal"}):L | Where is Porto Novo located? | 'Benin' |
Which country has a city called porto? | 'Portugal' |
Predicate scripts
Predicate scripts allow you to add additional value-dependent constraints to a condition element based on NLU variables or annotations associated with the condition. Like propagation scripts, predicate scripts can be attached to bracketed condition parts, language objects, entities, and input annotations. If the predicate script is evaluated as false, the match is disregarded. The predicate script has access to NLU variables, input annotation variables, and used words of the associated object. It does not have access to flow or session variables and it cannot propagate values.
Condition | Matched user input | Unmatched user input |
---|---|---|
(*):{_USED_WORDS.toLowerCase() != "hello"} | Hi | Hello |
Welcome | hello | |
%ANIMALS.LIST:{lob.sAnimalType == "Pet"} | Cat | Tiger |
Dog | Wasp | |
%$NUMBER:{lob.numericValue > 100} | 131 | 99 |
1300 | 0.4 |
Shortcuts
While working with conditions. There are some shortcuts inside Teneo that helps the developer to write its own conditions. They are as follows:
- Ctrl + space - Auto complete the Language Object name, as seen here.
- Alt + double click - Open Flow or Language Object in edit mode.
- Alt + restart - Full engine restart, which is helpful when testing your newly created condition in Try Out.
Engine Access methods
Some other conditions that can be used as an additional is the engine access methods. These are as follows:
Condition | Description |
---|---|
_.getUserInputText() | Get full user input (string). |
_getUserInputWords() | Get user input (list). |
_.getUsedWords(_.ORIGINAL) | Get raw triggering words (list). |
_.getUsedWords(_.SIMPLIFIED) | Get processed triggering words (list). |
_.getUsedWords(_.FINAL) | Get final triggering words (list). |
_.getNotUsedRawWords() | Get words not triggering (list). |
_.getLangObjVariable(‘x’) | value of Language Object variable 'x'. |
_.setSessVarLifespan(‘x’, 3) | set life span of variable 'x'. |
_.getThisFlow() | Get the flow that was currently processed. |
==Insert comments here== | Comments made by the developer. |