Lesson 4 -- Improving Prompts and Grammars

The focus of this lesson is on how to improve the caller's experience in our evolving travel agency application by using better prompts and grammars. It includes the following sections:

  • Improving grammars with the GARBAGE and NULL rules and the <tag> element

    • Standardizing the returned match with the <tag> element
  • Improving prompts with <break> and bargein

    • Adding pauses with the <break> element

    • Allowing callers to interrupt the prompt (bargein)

  • A new version of app-root.vxml with the changes in this lesson applied

  • What's next?

Improving grammars with the GARBAGE and NULL rules and the <tag> element

Prompts and grammars work together. Prompts influence what a caller can say and what your grammars must accept as input. Grammars should be improved in the context of their corresponding prompts. Conversely, you can design more effective prompts if your grammars accept a wider variety of phrases.

The special GARBAGE grammar rule

The prompt we have been using for the main_selection field is:

   <prompt>
      Welcome to Contoso Travel
      Say new reservation or press 1.
      Say change reservation or press 2.
     Say restaurant recommendation or press 3.
   </prompt>

Consider this item in the main_selection grammar:

<item>new reservation</item>

To match this item, a caller must say both words in the order they appear in the <item> element; that is, he or she must say "new reservation" exactly. Neither "new" nor "reservation" can be omitted, and no other words can be added. This can be limiting, as some callers may add words or sounds, such as "please" at the end or "umm" at the beginning. Non-exact phrases like "new reservation, please" or "I want to make a new reservation" won't make a match.

All we really need to hear in this item is the phrase "new reservation." We would like to allow other utterances before and after "new reservation" and still make a match. We can do this with the special GARBAGE and NULL grammar rules.

The GARBAGE rule will match any speech at all. So we modify <item>new reservation</item> like this:

   <item>
      <ruleref special="GARBAGE"/>
      new reservation
      <ruleref special="GARBAGE"/>
   </item>

Note

A <ruleref> element can appear anywhere a word or DTMF tone can appear. Here we are using it to invoke the special GARBAGE rule that will match any word or phrase.

Now the caller can say all sorts of things. As long as the phrase "new reservation" is in the utterance, a match will occur. All of these caller responses (and many more) will produce a match:

  • "New reservation."

  • "I want to make a new reservation."

  • "I want to make a new reservation please."

  • "New reservation please."

  • "New reservation, thank you."

  • "Umm, how about a new reservation."

Without the special GARBAGE rule, only the first response would be accepted.

Now, there is a potential problem with using the GARBAGE rule. Consider

   <item>
      <ruleref special="GARBAGE"/>
      new reservation
      <ruleref special="GARBAGE"/>
   </item>

What if nothing is said before "new reservation" or nothing is said after it? Will a match occur? This is platform dependent, so to create cross-platform code (it is always a good idea to do this in case you move your application to a new platform or your existing platform changes) we need to modify the <item> element immediately above. We do this with the special NULL rule.

The special NULL rule is the opposite of the GARBAGE rule. It matches silence. So, we can replace <ruleref special="GARBAGE"/> with this:

   <one-of>
      <item><ruleref special="GARBAGE"/></item>
      <item><ruleref special="NULL"/></item>
   </one-of>

This <one-of> element will match any speech or no speech at all.

Adding the GARBAGE and NULL rules to our application

Here is the grammar we have been using for the main form in the application we are developing:

   <grammar version="1.0" root="top">
     <rule id="top">
         <one-of>
            <item>new reservation</item>
            <item>change reservation</item>
            <item>restaurant recommendation</item>
         </one-of>
      </rule>
   </grammar>

Let's change this grammar as follows (changes in bold font):

   <grammar version="1.0" root="top">
      <rule id="top">
         <one-of>
            <item><ruleref special="GARBAGE"/></item>
            <item><ruleref special="NULL"/></item>
         </one-of>
         <one-of>
            <item>new reservation </item>
            <item>change reservation </item>
            <item>restaurant reservation</item>
         </one-of>
         <one-of>
            <item><ruleref special="GARBAGE"/></item>
            <item><ruleref special="NULL"/></item>
         </one-of>
      </rule>
   </grammar>

Now a grammar match will occur if the caller says (anything or nothing) + ("new reservation," "change reservation," or "restaurant") + (anything or nothing).

Standardizing the returned match with the <tag> element

There is a potential problem in using the GARBAGE ruleref in the grammar immediately above. If a caller says "I want a new reservation" the grammar may return this string:

"...new reservation"

On the other hand, if a caller just says "new reservation" then the returned string will not have the three dots (which signify garbage).

We need to make sure that the application returns the same thing whether or not there is garbage. We can accomplish this with the <tag> element. Without the <tag> element, a match returns the matched phrase, whatever it is. The <tag> element allows us to specify exactly what string is returned when a match is found.

To use the <tag> element, we must add an attribute to the <grammar> element:

tag-format="semantics/1.0"

Then, we modify the grammar as follows (new code in bold):

   <grammar version="1.0" root="top" tag-format="semantics/1.0">
      <rule id="top">
         <one-of>
            <item><ruleref special="GARBAGE"/></item>
            <item><ruleref special="NULL"/></item>
         </one-of>
         <one-of>
            <item>new reservation 
               <tag>out="new reservation";</tag></item>
            <item>change reservation 
               <tag>out="change reservation";</tag></item>
            <item>restaurant recommendation
               <tag>out="restaurant recommendation";</tag></item>
         </one-of>
         <one-of>
            <item><ruleref special="GARBAGE"/></item>
            <item><ruleref special="NULL"/></item>
         </one-of>
      </rule>
   </grammar>

The <tag>out="xxx";</tag> code causes the matched phrase (new reservation, change reservation, or restaurant recommendation) to be assigned to the field name variable, main_selection, without any prefixes or postfixes.

Now the application will return only new reservation, change reservation, or restaurant recommendation, whether or not these words are preceded or followed by garbage.

We do not have to change the DTMF grammar because the GARBAGE and NULL rules are only relevant to voice input.

Note

For more detailed discussion of GARBAGE, NULL and the <tag> element refer to the first four chapters of the Tellme Speech Service Grammar Developer's Guide (https://msdn.microsoft.com/en-us/library/ee800148.aspx).

Revising the new_reservation_type grammar

The prompt and grammar that we have been using for the new_reservation form are these:

   <form id ="new_reservation">
      <field name="new_reservation_type">
         <prompt>
            What type of reservation do you want to make? Say plane, hotel,
            or car. You can combine types by saying plane and hotel for example
         </prompt>
         <grammar version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>plane</item>
                  <item>hotel</item>
                  <item> car</item>
                  <item>plane and hotel</item>
                  <item>hotel and car</item>
                  <item>plane and car</item>
                  <item>plane and hotel and car</item>
               </one-of>
            </rule>
         </grammar>
      </field>
   </form>

The prompt is not very precise and it is likely that the caller will not respond with the correct words or with the words in the required order. We should try to make a grammar that permits a simpler prompt, such as:

   <prompt>
      What type of reservation do you want to make? Say plane, hotel, or car.
      You may choose more than one.
   </prompt>
   <grammar version="1.0" root="top">
      <rule id="top">
         <one-of>
      <!--single choice -->
            <item><ruleref special="GARBAGE"/>plane
                         <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/></item>
      <!--double choice -->
            <item><ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/></item>
      <!--triple choice -->
            <item><ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/></item>
            <item><ruleref special="GARBAGE"/>car
                  <ruleref special="GARBAGE"/>hotel
                  <ruleref special="GARBAGE"/>plane
                  <ruleref special="GARBAGE"/></item>
         </one-of>
      </rule>
   </grammar>

The grammar immediately above looks for:

   plane
   hotel
   car
   plane hotel
   plane car
   hotel plane
   car plane
   hotel car
   car hotel
   plane hotel car
   plane car hotel
   hotel plane car
   hotel car plane
   car plane hotel
   car hotel plane

This covers all possible combinations of a single reservation, two reservations, or three reservations in any arbitrary order.

Adding a subrule

The top rule in the grammar for the new_reservation form shown above includes a large number of <ruleref special="GARBAGE"/> elements. However, these really should be:

   <one-of>
      <item><ruleref special="GARBAGE"/></item>
      <item><ruleref special="NULL"/></item>
   </one-of>

so that we are sure it matches anything or nothing.

Replacing the GARBAGE ruleref with this <one-of> element would make the grammar very difficult to read. What we will do instead is to put the above <one-of> element in its own rule (with id="nonsense") and use a <ruleref> element to invoke it. The resulting grammar will look like this:

   <grammar version="1.0" root="top" tag-format="semantics/1.0">
   <rule id="top">
      .......
      .......
      .......
   </rule>
   <rule id="nonsense">
      <one-of>
         <item><ruleref special="GARBAGE"/></item>
         <item><ruleref special="NULL"/></item>
      </one-of>
   </rule>
</grammar>

l

Then, in the top rule, we replace <ruleref special="GARBAGE"/> everywhere with <ruleref uri="#nonsense"/>.

The resulting grammar will be much more flexible and will allow matches to a much wider variety of caller responses. The likelihood of failing to get a grammar match will be much reduced.

Using the <tag> element

We can choose to return anything that we want to from a grammar match if we use the <tag> element. In the new_reservation_type field, we can return one, two, or three reservation types. Since we handle plane, hotel, and car reservations in that order, let's use the <tag> element to return the following strings:

   plane
   hotel
   car
   plane and hotel
   plane and car
   hotel and car
   plane and hotel and car

Note

These strings were chosen so that we do not have to revise the new_reservation_type field's switch statement.

Adding the <tag> elements, the new_reservation_type field's grammar becomes (changes in bold font):

   <grammar version="1.0" root="top" tag-format="semantics/1.0">
      <rule id="top">
         <one-of>
         <!--single choice -->
            <item><ruleref uri="#nonsense"/>plane
                         <ruleref uri="#nonsense"/>
                         <tag>out="plane";</tag></item>
            <item><ruleref uri="#nonsense"/>hotel
                         <ruleref uri="#nonsense"/>
                         <tag>out="hotel";</tag></item>
            <item><ruleref uri="#nonsense"/>car
                         <ruleref uri="#nonsense"/>
                         <tag>out="car";</tag></item>
         <!--double choice -->
            <item><ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>hotel
                         <ruleref uri="#nonsense"/>
                         <tag>out="plane and hotel";</tag></item>
            <item><ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>car
                         <ruleref uri="#nonsense"/>
                         <tag>out="plane and car";</tag></item>
            <item><ruleref uri="#nonsense"/>hotel
                  <ruleref uri="#nonsense"/>plane
                         <ruleref uri="#nonsense"/>
                         <tag>out="plane and hotel";</tag></item>
            <item><ruleref uri="#nonsense"/>car
                  <ruleref uri="#nonsense"/>plane
                         <ruleref uri="#nonsense"/>
                         <tag>out="plane and car";</tag></item>
            <item><ruleref uri="#nonsense"/>hotel
                   <ruleref uri="#nonsense"/>car
                         <ruleref uri="#nonsense"/>
                         <tag>out="hotel and car";</tag></item>
            <item><ruleref uri="#nonsense"/>car
                   <ruleref uri="#nonsense"/>hotel
                         <ruleref uri="#nonsense"/>
                         <tag>out="hotel and car";</tag></item>
         <!--triple choice -->
            <item><ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>hotel
                  <ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
            <item><ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>car
                  <ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
            <item><ruleref uri="#nonsense"/>hotel
                  <ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
            <item><ruleref uri="#nonsense"/>hotel
                  <ruleref uri="#nonsense"/>car
                  <ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
            <item><ruleref uri="#nonsense"/>car
                  <ruleref uri="#nonsense"/>plane
                  <ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
            <item><ruleref uri="#nonsense"/>car
                  <ruleref uri="#nonsense"/>hotel
                  <ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>
                        <tag>out="plane and hotel and car";
                        </tag></item>
         </one-of>
      </rule>
      <rule id="nonsense">
         <one-of>
            <item><ruleref special="GARBAGE"/></item>
            <item><ruleref special="NULL"/></item>
         </one-of>
      </rule>
   </grammar>

Confirming the caller's choice

The grammar immediately above should handle a wide range of input from most callers. It is always possible, however, that a caller might say something rambling like "no plane, no car, just a hotel." This would, of course, yield an incorrect match: "plane and hotel and car."

To handle such a possibility, we could add a confirmation prompt of the form:

   <prompt>
   I heard you say plane and hotel and car. Is that correct?
   </prompt>

Instead of having to write our own confirmation grammar, we can use one that’s already been created for us: http://grammar.svc.tellme.com/yesno/mss/v1/confirm.grxml. This is a standard Tellme grammar that can be referenced by the public. This grammar is intended for just this sort of situation (answers to questions like "is that correct?"). It accepts a wide variety of responses (for example, yeah, yes, yup, sure, correct, wrong, nope and so forth) and returns yes or no. Using it will save us the time to write and debug our own grammar.

If the response is no the application can re-enter the main_selection field and try again.

We will postpone adding a confirmation prompt until Lessons 7 and 8 because it involves important concepts we haven't covered yet.

Adding DTMF to the new_reservation form

We could add a DTMF grammar that accepts 1 + 2, 1 +3, 2 +3, 1 + 2 + 3, and so forth, but it's probably not a good idea. Imagine this prompt:

   <prompt>
      What type of reservation do you want to make? Say plane or press 1, 
                            say hotel or press 2, say car or press 3.
      You may choose more than one.
   </prompt>

To use DTMF, the caller would have to remember which number went with which choice. That's straightforward for a single choice. For multiple choices, however, the caller has to memorize the whole list before choosing. Not everyone can do that easily, so multiple-choice DTMF can be a source of error.

Improving prompts with <break> and bargein

The <prompt> elements that contain the questions posed to callers can contain text or audio files. When the <prompt> element contains text, it is rendered by text-to-speech (TTS). In this lesson, as in all prior lessons, we continue to use TTS for prompts.

As an alternative to TTS, we can include a reference to an audio file in the <prompt> element. The application then plays the audio file rather than using TTS. Use of audio files will be covered in Lesson 9. Up until that lesson, we will continue to use TTS.

The improvements we made to our grammars have already improved our prompts. There are several more things we can use to make the prompts more user-friendly:

  • The <break> element

  • bargein attributes

Adding pauses with the <break> element

TTS has some variability in how natural it can sound. For instances that happen to require additional pauses between words in order to maximize naturalness, one can insert pauses with the <break> element (see https://msdn.microsoft.com/en-us/library/ff929031.aspx). Inserting <break size="medium"/> into a prompt introduces a 500 msec (1/2 second) pause in the TTS. size can also have the values small (200 msec) and large (1 sec).

With <break> elements inserted, the main_selection prompt is:

   <prompt>
      Welcome to Contoso Travel<break/>
      Say new reservation<break size="small"/>
                                     or press 1<break size="medium"/>
      Say reservation<break size="small"/>
                                     or press 2<break size="medium"/>
      Say restaurant recommendation<break size="small"/>
                                                            or press 3
   </prompt>

When you run code with this prompt you will see that it sounds more natural.

Note

medium is the default for size, so we can simply write <break/> to get a 500 msec pause.

With <break> elements inserted, the new_reservation_type prompt is:

   <prompt>
      What type of reservation do you want to make<break/>Say plane
      <break size="small"/>, hotel<break size="small"/>, or car<break/>
      You may choose more than one.
   </prompt>

Once again, when you run code with this prompt you will see that it sounds more natural.

Allowing callers to interrupt the prompt (bargein)

With every prompt, the question arises about letting the caller interrupt the prompt. Returning users who know the menus don't want to wait until a prompt is finished playing. To give them a good user experience, they should be allowed to interrupt (this is actually the default behavior on the Tellme platform and most others as well). On the other hand, the designer of an IVR application might want the caller to hear a message in in its entirety. Examples would include a welcome statement, an advertisement, or a special announcement that the owner of the application wants the caller to hear.

The bargein attributes of the <prompt> element allow or forbid callers to interrupt the prompt with speech or DTMF. Allowing bargein is the default behavior.

Attribute

Possible Value

Description

bargein

true

The caller can interrupt the prompt, and the caller's speech or DTMF input is processed (default).

false

Any caller speech or DTMF input is ignored until the prompt has finished.

bargeintype

speech

The prompt will be stopped as soon as speech or DTMF input is detected (default).

hotword

The prompt will not be stopped until a complete match of an active grammar is detected.

Consider, for example, writing the <prompt> element like this:

<prompt bargein="true" bargeintype="speech">.....</prompt>

With these values for the bargein attributes, a caller can interrupt the prompt and the prompt will stop playing as soon as the caller speaks. See https://msdn.microsoft.com/en-us/library/ff928996.aspx for more information on the bargein attributes.

The bargein properties

We have not yet discussed properties. We will cover properties in some detail beginning in Lesson 6. Here is a brief introduction for the purposes of this lesson.

Properties specify speech parameters for an entire application, document, or form, depending on where they are set. You set properties with a statement like this:

<property name="bargein" value="false"/>

All properties have default values that apply at the document or application level. That is, they are set by the platform. You only need to set a property if you do not want the default value to apply to your form, document, or application.

Tip

If the value of a property is important to your application, you should set it yourself rather than depending on a default. A given platform may change the default.

Among the VoiceXML properties are two bargein properties that have the same names and possible values as the bargein attributes:

  • The bargein property has a default of true on all platforms (as specified by the VoiceXML 2. specification).

  • The bargeintype property default is platform specific. For the Tellme platform, it is speech.

Note

You can determine the Tellme default value of any VoiceXML attribute or property by looking at the VoiceXML 2.x Element Catalog on MSDN. The default values are in bold text. See https://msdn.microsoft.com/en-us/library/ff934626.aspx.

Interplay between bargein attributes and properties

As properties, bargein and bargeintype can have dialog, document, or application scope. If they are not explicitly set, they have their default values (true, speech).

Important

The bargein attributes inherit their default values from the bargein properties of the same name. If the bargein properties are not explicitly set in the application, then the defaults for both the properties and the attributes are true and speech. Then the caller can barge in at any time during the prompt. If the bargein properties are explicitly set, then those settings become the defaults for the bargein attributes.

If, for example, the application scope bargein property is set to true, either explicitly or by default, then bargein is allowed for all prompts in the application.

When a bargein attribute is explicitly set for a prompt, that setting overrides the value of the corresponding bargein property.

We have not been setting bargein properties in app-root.vxml, so the default attributes (true and speech) apply and we do not need to include them explicitly. However, we will start using the bargein attributes in our application to emphasize that bargein is allowed.

If our travel agency application had a commercial announcement that it wanted the callers to hear in its entirety, we would set bargein="false" for that prompt.

Note

The bargein attribute and property settings apply to both voice and DTMF.

A new version of app-root.vxml with the changes in this lesson applied

If we add the prompts (with bargein attributes) and grammars in this lesson, we have a new version of app-root.vxml. All the code which has changed from the version of app-root.vxml at the end of Lesson 2 is in bold font.

<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns="http://www.w3.org/2001/vxml"
      version="2.1"
      xml:lang="en-US"
      xml:base="https://studio.tellme.com/vxml-tutorial/">
      
   <script>
      <![CDATA[
         var doNewPlaneRes = false;
         var doNewHotelRes = false;
         var doNewCarRes = false;
         var doChangePlaneRes = false;
         var doChangeHotelRes = false;
         var doChangeCarRes = false;
         var doRestaurantRec = false;
      ]]>
   </script>

<form id="main">
      <field name="main_selection">
         <prompt bargein="true" bargeintype="speech">
            Welcome to Contoso Travel<break/>
            Say new reservation<break size="small"/>
                                           or press 1<break/>
            Say change reservation<break size="small"/>
                                           or press 2<break/>
            Say restaurant recommendation<break size="small"/>
                                                   or press 3
         </prompt>
         <grammar version="1.0" root="top" tag-format="semantics/1.0">
            <rule id="top">
               <one-of>
                  <item><ruleref special="GARBAGE"/></item>
                  <item><ruleref special="NULL"/></item>
               </one-of>
               <one-of>
                  <item>new reservation 
                     <tag>out="new reservation";</tag></item>
                  <item>change reservation
                     <tag>out="change reservation";</tag></item>
                  <item>restaurant recommendation
                     <tag>out="restaurant recommendation";</tag></item>
               </one-of>
               <one-of>
                  <item><ruleref special="GARBAGE"/></item>
                  <item><ruleref special="NULL"/></item>
               </one-of>
            </rule>
         </grammar>
         <grammar mode="dtmf" version="1.0" root="top">
            <rule id="top">
               <one-of>
                  <item>1</item>
                  <item>2</item>
                  <item>3</item>
               </one-of>
            </rule>
         </grammar>

         <catch event="noinput nomatch">
            Sorry. Didn't get that. Please try again.
            <reprompt/>
         </catch>

         <filled>
            <script>
               <![CDATA[
                  var next_destination = "";
                  switch (main_selection){

                  case "new reservation" :
                    next_destination = "#new_reservation";
                    break;

                  case "1" :
                    next_destination = "#new_reservation";
                    break;
                    

                  case "change reservation" :
                    next_destination = "change-reservation.vxml";
                    break;
                    
                  case "2" :
                    next_destination = "change-reservation.vxml";
                    break;
                    

                  case "restaurant recommendation" :
                    next_destination = "restaurant.vxml";
                    break;
                    
                  case "3" :
                    next_destination = "restaurant.vxml";
                    break;
                    

                  default:
                    next_destination = error.vxm
                    break;
                 }
               ]]>
            </script>
            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>
   <form id ="new_reservation">
      <field name="new_reservation_type">
         <prompt bargein="true" bargeintype="speech">
            What type of reservation do you want to make<break/>Say
            plane<break size="small"/>, hotel
            <break size="small"/>, or car<break/>
            You may choose more than one.
         </prompt>
<grammar version="1.0" root="top" tag-format="semantics/1.0">
            <rule id="top">
               <one-of>
         <!--single choice -->
                  <item><ruleref uri="#nonsense"/>plane
                               <ruleref uri="#nonsense"/>
                               <tag>out="plane";</tag></item>
                  <item><ruleref uri="#nonsense"/>hotel
                               <ruleref uri="#nonsense"/>
                               <tag>out="hotel";</tag></item>
                  <item><ruleref uri="#nonsense"/>car
                               <ruleref uri="#nonsense"/>
                               <tag>out="car";</tag></item>

       <!--double choice -->
                  <item><ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>hotel
                               <ruleref uri="#nonsense"/>
                               <tag>out="plane and hotel";</tag></item>
                  <item><ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>car
                               <ruleref uri="#nonsense"/>
                               <tag>out="plane and car";</tag></item>
                  <item><ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>plane
                               <ruleref uri="#nonsense"/>
                               <tag>out="plane and hotel";</tag></item>
                  <item><ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>plane
                               <ruleref uri="#nonsense"/>
                               <tag>out="plane and car";</tag></item>
                  <item><ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>car
                               <ruleref uri="#nonsense"/>
                               <tag>out="hotel and car";</tag></item>
                  <item><ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>hotel
                               <ruleref uri="#nonsense"/>
                               <tag>out="hotel and car";</tag></item>

         <!--triple choice -->
                  <item><ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>car
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
                  <item><ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>hotel
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
                  <item><ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>car
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
                  <item><ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>plane
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
                  <item><ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>plane
                        <ruleref uri="#nonsense"/>hotel
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
                  <item><ruleref uri="#nonsense"/>car
                        <ruleref uri="#nonsense"/>hotel
                        <ruleref uri="#nonsense"/>plane
                              <ruleref uri="#nonsense"/>
                              <tag>out="plane and hotel and car";
                              </tag></item>
               </one-of>
            </rule>
            <rule id="nonsense">
               <one-of>
                  <item><ruleref special="GARBAGE"/></item>
                  <item><ruleref special="NULL"/></item>
               </one-of>
            </rule>
         </grammar>

         <catch event="noinput nomatch">
            Sorry. Didn't get that. Please try again.
            <reprompt/>
         </catch>

         <filled>
            <script>
              <![CDATA[
                  var next_destination = "";
                  switch (new_reservation_type){

                  case "plane" :
                    next_destination = "new-plane.vxml";
                    break;

                  case "hotel" :
                    next_destination = "new-hotel.vxml";
                    break;

                  case "car" :
                    next_destination = "new-car.vxml";
                    break;
                    
                  case "plane and hotel" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    break;

                  case "plane and car" :
                    next_destination = "new-plane.vxml";
                    doNewCarRes = true;
                    break;

                  case "hotel and car" :
                    next_destination = "new-hotel.vxml";
                    doNewCarRes = true;
                    break;
                    
                  case "plane and hotel and car" :
                    next_destination = "new-plane.vxml";
                    doNewHotelRes = true;
                    doNewCarRes = true;
                    break;

                  default:
                   next_destination = error.vxml
                   break;
                 }
               ]]>
            </script>

            <goto expr="next_destination"/>
         </filled>
      </field>
   </form>
</vxml>

You should paste this code into the Tellme Studio Scratchpad and run it.

What's next?

In this lesson we have shown how to improve grammars with the GARBAGE and NULL rules and the <tag> element, and how to make the TTS in prompts sound more natural with the <break> element.

In Lesson 5, we will explore three alternatives to the inline grammars that we have been using previously, as well as a method for testing them. The three alternatives are:

  • The <option> element.

  • Builtin grammars.

  • Tellme public grammars.