Tags

Tags are special grammar tokens that can contain any information you wish to put in them. The vast majority of users will want to use tags to contain Semantic Interpretation for Speech Recognition (SISR), the standard method of placing semantic interpretation information inside of grammars.

Tags are placed inside of ABNF grammars using curly braces (the { } characters). Because SISR also allows for ECMAScript (JavaScript) code that treats the curly brace as a reserved character, tags can also be enclosed by a three character sequence of curly brace, exclamation point, curly brace (the {!{ and }!} sequence of characters). Both methods of denoting tags are equivalent, except the {!{ method allows you to use single curly braces within the tag.

SISR is a very powerful method of putting extra information inside of tags. For details about it, you can see our Introduction to Semantic Interpretation which contains an SISR tutorial.

In order to use SISR within an ABNF grammar, you include a tag-format declaration in your grammar's header, like so:

#ABNF 1.0 UTF-8;
language en-US;
mode voice;
tag-format <semantics/1.0>;

The tag format must be enclosed within angle brackets. See our list of tag formats for the acceptable formats you may declare.

If you are satisfied exclusively using SISR inside of tags, you may continue on to Applying Grammar Weights, the next chapter in the grammar tutorial.

Tags Without SISR

You may use tags without declaring a tag format, in which case tags are completely ignored when the Engine uses your grammar. Anytime the Engine sees a tag in a rule, it skips right over it. But when the Engine returns the results of a decode, it returns the tags it saw -- in the order it saw them -- along with the words and rules it recognized. This makes tags a good way to store post-processing information.

Note that it is easier to use SISR for this purpose. The following information is provided as a reference in case you want to design your own method of semantic interpretation.

Example

#ABNF 1.0;
language en-US;
mode voice;
root $yesorno;

$yes = yes [please] {!{ returnvalue: true }!}; // This is a tag
$no = no [way | thank you] { returnvalue: false }; // Another tag
$yesorno = $yes | $no;

To understand how you might use tags, we need to examine the form of an engine decode response.

Example

#ABNF 1.0;
language en-US;
mode voice;
root $navigate;

$direction = forward | back | backward | left | right;
$number = one | two | three | four | five;

$navigate = ( go | move | walk | step) $direction $number (steps | paces | units);

With the above grammar, if the engine recognizes "walk forward three paces," it will return a parse tree, or sentence diagram, that looks like this:

You can read more about the parse tree return type here.

In order to convert the parse tree return type into data useful to your application, your application needs to go through the tree and convert it into a result your application expects. For instance, your application might expect a result that looks like this:

While it is certainly possible to make the conversion, there are disadvantages to interpreting the parse tree directly to do so. One disadvantage is that your application becomes directly dependant on knowing the structure of your grammar. If the form of your grammar changes, your application code will have to change as well. Another disadvantage is that if your application uses multiple grammars (as most do), then you will most likely have to have a different set of parse tree processing code for each of your grammars.

Instead of manipulating the parse tree directly, you can put the conversion process in your grammar using tags. To do so, you adopt a consistent format for your tags, and a uniform way of processing your tags + parse tree. Then the shape of your grammar does not matter, as long as you process your tags and parse tree in the same way each time (note again that using SISR tags and getting results from the interpretation object solves this same problem).

For this example we will adopt a very simple method for post-processing: we will walk the tree, ignoring anything that is not a tag. We will treat the tags as string data, and concatenate the strings as we see them in the parse tree.

Example

#ABNF 1.0;
language en-US;
mode voice;
root $navigate;
tag-format <my_simple_tag_format>;

$direction = { direction: }( forward { 1, } |
back { 2, } | backward { 2, } | left { 3, } | right { 4, } );
$number = { units: } ( one { 1, } |
two { 2, } | three { 2, } | four { 4, } | five { 5, } );
$navigate = { instruction:[ }
( go | move | walk | step) $direction $number (steps | paces | units) { ] };

Now, with the above grammar, when the engine recognizes "walk forward three paces," the parse tree returned will look like:

And when we concatenate the tags we get the result type our application expects.

Admittedly, this is a very naive tag processing scheme, and as a result it requires a hefty number of tags to accomplish a simple task, but it does achieve the goal we want of processing our tree in a way that is independent of the form of the grammar. As a result, if the form of the grammar ever needs to change, the tags in the grammar can change, too, and the application code can stay the same.

The next chapter in the grammar tutorial is Applying Grammar Weights.

© 2012 LumenVox LLC. All rights reserved.