Special Rules
In addition to the rules you create, several reserved rules are outlined in section 2.2.3 of the SRGS Specification. These rules dictate special behavior for the Speech Engine.
While helpful, these rules are best used either temporarily or as a last resort, because they can negatively affect processing during decodes. In almost every case, the same result can be achieved through programming instead. The special rules are:
- GARBAGE
- VOID
- NULL
In ABNF, reference a special rule with $NAME, where NAME is the special rule name in all caps (e.g. $GARBAGE). In GrXML, special rules are referenced with <ruleref special="NAME"/>, where NAME is the rule name in all caps (e.g. <ruleref special="GARBAGE"/>). Note that the special attribute is used with <ruleref> here instead of the usual uri attribute.
GARBAGE
The GARBAGE rule functions like a wild card: it filters out and discards any words not matched by the other words within its rule.
Use it temporarily at best, as it can greatly increase decode time. It should not be used to create a hot-word or keyword-spotting grammar — that will not work.
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $yesorno; $yes = yes [please]; $no = no $GARBAGE; |
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="yesorno" mode="voice"> <rule id="yesorno"> <one-of> <item><ruleref uri="#yes"/></item> <item><ruleref uri="#no"/></item> </one-of> </rule> <rule id="yes"> yes <item repeat="0-1">please</item> </rule> <rule id="no"> no <ruleref special="GARBAGE"/> </rule> </grammar> |
The grammar above would let the user say "no," "no, thank you," or "no, you stupid machine." Only the matched no rule would be returned; "thank you," "you stupid machine," or anything else spoken after "no" would not be returned as part of the answer.
Note that engaging the out-of-vocabulary filter can slow recognition times, and can even cause additional misrecognitions if used too aggressively.
If possible, we recommend creating specific "filler entries" using grammar rules to match frequently occurring out-of-vocabulary words, instead of using the GARBAGE rule. For example, it is often better to use a rule like:
ABNF example:
| $no = no | no thank you | no you stupid machine; |
GrXML example:
| <rule id="no"> <one-of> <item>no</item> <item>no thank you</item> <item>no you stupid machine</item> </one-of> </rule> |
...instead of the GARBAGE rule, assuming your users frequently give responses like the ones above.
This is because, while you do not need the filler words for your interpretation, they add to the confidence of the match. "No" has the same interpretation as "no, thank you," but when those filler words are matched it increases the likelihood that the Engine has decoded the entire utterance correctly.
The GARBAGE rule is tempting because it seems to remove the need to account for any words around those in your grammar. However, it also introduces the possibility of false-positive matches — where a match is made incorrectly. If the GARBAGE rule matches anything around its grammar entry, it is also possible to match entries in the GARBAGE rule when you do not want to:
ABNF example — how NOT to use the GARBAGE rule:
| #ABNF 1.0; language en-US; mode voice; root $yesorno; $no = no $GARBAGE; $dontknow = [I] don't know | [I have] no idea; |
GrXML example — how NOT to use the GARBAGE rule:
| <rule id="no"> no <ruleref special="GARBAGE"/> </rule> <rule id="dontknow"> <one-of> <item> <item repeat="0-1">I</item> don't know </item> <item> <item repeat="0-1">I have</item> no idea </item> </one-of> </rule> |
Here, the parse "no idea" is intended to match the dontknow rule, and it would — but it will also match the no rule, and will probably return that as the first interpretation.
VOID
The VOID rule invalidates any matched rule that contains it — and therefore any answer that contains it. In other words, it throws away any input that matches the rule.
The VOID rule is most effectively used to prevent nonsensical input. Suppose a flight-booking application sometimes misrecognizes "San Diego" and "San Francisco," resulting in a nonsensical request such as San Diego to San Diego. You could use the VOID rule to prevent the destination from matching the departure:
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $utterance; $cities = San Diego | San Francisco | Portland | Seattle; $destination = $cities; $departure = $cities; $notallowed = (San Diego to San Diego | San Francisco to San Francisco) $VOID; $flights = $departure to $destination | $notallowed; $utterance = I want a flight from $flights; |
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="utterance" mode="voice"> <rule id="cities"> <one-of> <item>San Diego</item> <item>San Francisco</item> <item>Portland</item> <item>Seattle</item> </one-of> </rule> <rule id="destination"><ruleref uri="#cities"/></rule> <rule id="departure"><ruleref uri="#cities"/></rule> <rule id="notallowed"> <one-of> <item>San Diego to San Diego</item> <item>San Francisco to San Francisco</item> </one-of> <ruleref special="VOID"/> </rule> <rule id="flights"> <one-of> <item><ruleref uri="#departure"/> to <ruleref uri="#destination"/></item> <item><ruleref uri="#notallowed"/></item> </one-of> </rule> <rule id="utterance"> I want a flight from <ruleref uri="#flights"/> </rule> </grammar> |
Ideally, you would write a grammar that only contains valid destination/departure combinations in the first place — but explicitly enumerating all of them would be far more tedious than simply disallowing the specific unwanted combinations. Here, the VOID rule is a simple, effective way to eliminate likely misrecognitions without a huge undertaking.
The VOID rule is one of the most difficult rules to use correctly, and is misused more often than not. It is sometimes most easily understood by explaining how not to use it.
Ultimately, it discards the match. At a glance, it seems perfect for deterring people from giving an unwanted response — users often try to use $VOID to throw out values they do not want, like "operator" in a yes/no grammar:
ABNF example — how NOT to use the $VOID rule:
| #ABNF 1.0; language en-US; mode voice; root $yesorno; $yesorno = $yes | $no | operator $VOID; $yes = yes [please]; $no = no [thanks]; |
GrXML example — how NOT to use the $VOID rule:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="yesorno" mode="voice"> <rule id="yesorno"> <one-of> <item><ruleref uri="#yes"/></item> <item><ruleref uri="#no"/></item> <item>operator <ruleref special="VOID"/></item> </one-of> </rule> <rule id="yes"> yes <item repeat="0-1">please</item> </rule> <rule id="no"> no <item repeat="0-1">thanks</item> </rule> </grammar> |
In this example, if the caller says "operator," the VOID rule will force the recognition to be either "yes" or "no," and will end up with a low confidence. The result is basically the same as not having the operator word in the grammar at all — the application will either misrecognize or reprompt due to a low confidence score.
NULL
The NULL rule is automatically matched as soon as it is processed by the Engine, without the user having spoken anything. It is a programming tool, matched as the text of the grammar is parsed.
The NULL rule is illustrated below, with standard grammar operations rewritten to use it:
ABNF example:
| $yes = yes [please]; /* Identical rule expansion using the $NULL rule */ $yes = $yes (please | $NULL); |
GrXML example:
| <rule id="yes"> yes <item repeat="0-1">please</item> </rule> <!-- Identical rule expansion using the NULL rule --> <rule id="yes"> yes <one-of> <item>please</item> <item><ruleref special="NULL"/></item> </one-of> </rule> |
In the examples above, the expansion used to make "please" optional can be rewritten as the second rule. When the grammar is parsed, the ASR automatically knows it can match either "please" or NULL. Since it must match NULL automatically, it can return a valid parse without matching the word "please."
Since that example simply takes more keystrokes to accomplish the same thing, let's look at a more practical application. Below, you are building a numbers grammar that you want evenly weighted:
ABNF example:
| #ABNF 1.0; language en-US; mode voice; root $twenties; $OneToNine = one|two|three|four|five|six|seven|eight|nine; $twenties = twenty ($OneToNine | $NULL) |
When the speaker says any number in the twenties, they have the option to state a number between twenty and twenty-nine. This grammar lets them say "twenty" and then optionally use the $OneToNine rule to specify additional values. The $twenties rule specifies that the caller can either say something from within $OneToNine, or not.
However, this rule implies that the speaker is just as likely to say "twenty" as any other number within the twenties. Statistically, that may not be accurate — each number in the twenties should have a one-tenth chance of being said.
To counter this, add weights to the $twenties rule to bring the NULL option's weight down to 10% and raise the $OneToNine rule's weight to 90%:
| $twenties = twenty (/.9/$OneToNine | /.1/$NULL) |
Now the NULL rule is automatically matched, serving only to take up one-tenth of the weight of the $twenties rule. This is an important component, since you want all possible numbers in the twenties to have an equal likelihood of being matched.
In GrXML, this same grammar takes the form:
GrXML example:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="twenties" mode="voice"> <rule id="OneToNine"> <one-of> <item>one</item> <item>two</item> <item>three</item> <item>four</item> <item>five</item> <item>six</item> <item>seven</item> <item>eight</item> <item>nine</item> </one-of> </rule> <rule id="twenties"> twenty <one-of> <item weight=".9"><ruleref uri="#OneToNine"/></item> <item weight=".1"><ruleref special="NULL"/></item> </one-of> </rule> </grammar> |
As with the VOID rule, there are cases where you would not want to use the NULL rule. In the example below, the $word rule can be repeated an infinite number of times, as defined by the <0-> operator:
ABNF example — how NOT to use the $NULL rule:
| #ABNF 1.0; language en-US; mode voice; $utt = $NULL $word<0->[$NULL|a] ($NULL); $word = (a | b | $NULL); |
GrXML example — how NOT to use the $NULL rule:
| <?xml version="1.0" encoding="UTF-8" ?> <grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" root="utt" mode="voice"> <rule id="utt"> <ruleref special="NULL"/> <item repeat="0-"><ruleref uri="#word"/></item> <item repeat="0-1"> <one-of> <item><ruleref special="NULL"/></item> <item>a</item> </one-of> </item> <ruleref special="NULL"/> </rule> <rule id="word"> <one-of> <item>a</item> <item>b</item> <item><ruleref special="NULL"/></item> </one-of> </rule> </grammar> |
Other cases where the NULL rule is used are simply unnecessary and may slow down compilation or parsing of the grammar.
Related Articles
- Rule References — the previous step.
- Applying Grammar Weights
