VoiceXML 2.1 Development Guide Home  |  Frameset Home

  tutorial SubDialogs  |  TOC  |  tutorial Nbest Lesson  

Tutorial: Shadow Variables

This tutorial is based on concepts you accomplished in previous tutorials. If you have not completed most of the VoiceXML tutorial section, we recommend you go through them first.

In this tutorial, we will:

Step 1: creating our initial VoiceXML file

We've seen it before; a simple form-field-grammar script, which is the basic building block of any VoiceXML dialog. But what happens after we down nine cans of Jolt and whip out an application? Usually, it involves figuring out what we did wrong when we breezed through the code-writing process, all hopped up, glarey-eyed, and jittery. Typos are the most easily solved errors, (and yet the hardest to track down), but when our grammars and variables start getting wonky, it pays to have a good working knowledge of the various javascript shadow variables that are inherently available within the VXML markup.

Let's take a look at our starting structure, minus any typos:


<?xml version="1.0" encoding="UTF-8"?>
<vxml version = "2.1" >
<meta name="maintainer" content="yourEmail@here.com"/>

  <form>
    <field name="F_1" slot="F_1">
      <prompt>
        what is your favorite soda pop?
        Is it sprite, pepsi, coca cola, or tab?
      </prompt>

      <grammar type="text/gsl">
<![CDATA[[
(coka cola)    { <F_1 "coke">  }
[pepsi]        { <F_1 "pepsi">  }
[sprite]        { <F_1 "sprite"> }
[tab]          { <F_1 "tab">    }
]]]>
      </grammar>
      <filled>
        <prompt> you said <value expr="F_1$.utterance"/>. </prompt>
      </filled>
    </field>
  </form>
</vxml>


Step 2: Learning what shadow variables can do for us

Seems simple enough, eh? Ask a question, return the user's utterance value. Let's look into some debug statements we can add into the mix to glean what goes on behind the scenes. There are essentially two different ways to get at the same result arrays when a grammar is matched:


    <value expr="fieldName$.objectName"/>
    <log expr="fieldName$.objectName"/>

    <value expr="lastresult$.objectName"/>
    <log expr="lastresult$.objectName"/>


Inserting the true fieldname, followed by '$.objectName' is the most commonly used syntax for accessing the value of a particular shadow variable. Using the 'lastresult' host object is simply an alternative to using the 'fieldName' syntax that will return, logically enough, the last matched result the interpreter encountered.


The more useful objects of 'lastresult'  that we can take advantage of are as follows:


Step 3. Adding the debug statements and shadow variables into the code

Notice that we usually place the <log> element within the <filled> portion of our script; this makes variable tracking during the debugging process as easy as pie. And as we all know, pie is yummy, and goes well with soda pop. For this example, we have included both of the shadow variable syntaxes for illustrative purposes, and included them in the resultant prompts so as to read back the values to the caller.


<?xml version="1.0" encoding="UTF-8"?>
<vxml version = "2.1">
<meta name="maintainer" content="yourEmail@here.com"/>

  <form>
    <field name="F_1" slot="F_1">
      <prompt>
        what is your favorite soda pop?
        Is it sprite, pepsi cola, coca cola, or tab?
      </prompt>

  <grammar type="text/gsl">
<![CDATA[[
(coka cola)    { <F_1 "coke">  }
[pepsi]        { <F_1 "pepsi">  }
[sprite]        { <F_1 "sprite"> }
[tab]          { <F_1 "tab">    }
]]]>
  </grammar>
      <filled>
        <log expr="'**********************************************'"/>
        <log expr="'CONFIDENCE = ' +lastresult$.confidence"/>
        <log expr="'UTTERANCE = ' + lastresult$.utterance"/>
        <log expr="'INPUTMODE = ' + lastresult$.inputmode"/>
        <log expr="'INTERPRETATION = ' + lastresult$.interpretation.F_1"/>
        <log expr="'**********************************************'"/>


        <prompt>
        the confidence value is was <value expr="F_1$.confidence"/>,
          and the utterance was <value expr="F_1$.utterance"/>.
          You entered the information in via <value expr="F_1$.inputmode"/>.
        </prompt>
      </filled>
    </field>
  </form>
</vxml>


Step 4. Using the <record> shadow variables

Since we have all mastered the fine art of recognition-related shadow variables, we now move on to the exploration of record-level shadow variables. The syntax for these is exactly the same as for field-level shadow variables, but when recording, we now have a bevy of new object variables at our disposal.



But hey, enough talk, let's get down to brass tacks and add these Cool Moe Dee snippets to our existing application structure:



<?xml version="1.0" encoding="UTF-8"?>
<vxml version = "2.1" >
<meta name="maintainer" content="yourEmail@here.com"/>

  <form>
    <field name="F_1" slot="F_1">
      <prompt>
        what is your favorite soda pop?
        Is it sprite, pepsi cola, coca cola, or tab?
      </prompt>

  <grammar type="text/gsl">
<![CDATA[[
(coka cola)    { <F_1 "coke">  }
[pepsi]        { <F_1 "pepsi">  }
[sprite]        { <F_1 "sprite"> }
[tab]          { <F_1 "tab">    }
]]]>
  </grammar>
      <filled>
        <log expr="'**********************************************'"/>
        <log expr="'CONFIDENCE = ' + lastresult$.confidence"/>
        <log expr="'UTTERANCE = ' + lastresult$.utterance"/>
        <log expr="'INPUTMODE = ' + lastresult$.inputmode"/>
        <log expr="'INTERPRETATION = ' + lastresult$.interpretation.F_1"/>
        <log expr="'**********************************************'"/>

        <prompt>
          the confidence value is was <value expr="F_1$.confidence"/>,
          and the utterance was <value expr="F_1$.utterance"/>.
          You entered the information in via <value expr="F_1$.inputmode"/>. 
        </prompt>
      </filled>
    </field>
   
    <record name="R_1" beep="true" maxtime="15s" finalsilence="3000ms">
      <prompt>
        tell us why you like <value expr="lastresult$.utterance"/> so much,
        and then press a DTMF key to end the recording.
      </prompt>

      <filled>
        <log expr="'**********************************************'"/>
        <log expr="'RECORD DURATION = ' + R_1$.duration"/>
        <log expr="'RECORD FILESIZE = ' + R_1$.size"/>
        <log expr="'RECORD TERMCHAR = ' + R_1$.termchar"/>
        <log expr="'**********************************************'"/>


        <prompt>
          you said that the reason that you liked
            <value expr="F_1$.utterance"/>
          was 
            <value expr="R_1"/>
         
          <break strength="medium"/>
         
          In addition, our re cord shadow variable for duration is
            <value expr="R_1$.duration"/>
          milliseconds,  the size of the re cording is
            <value expr="R_1$.size"/>
          bytes, and the DTMF key you pressed was
            <value expr="R_1$.termchar"/>.         
          Lastly, the boo leean value indicating if max time was hit resulted in
            <value expr="R_1$.maxtime"/>.
        </prompt>
      </filled>
    </record>   
  </form>
</vxml>


Download the Code!

  Motorola source code


What we covered:





  ANNOTATIONS: EXISTING POSTS
henryanelson
3/22/2006 11:03 AM (EST)
Where is the negative comment about TAB specified?
MattHenry
3/22/2006 2:46 PM (EST)

Hello Henry,

I'm relly sorry, but I don't have any idea at all what it is that you are referencing. I'd be glad to address this for you if you need help, but I would definitely need more clarity in order to do so.

~Matthew Henry


emeijer
8/24/2006 12:36 AM (EDT)
Hi,

Is there any way to access to shadow variables inside a <nomatch> block ?

I realize that if there is no match, things like utterance have no meaning, so probably I am on the wrong track and hence let me explain what I want to accomplish, perhaps you will point me in a different direction...

Taking the above example...let's assume the user tried to say "sprite", but doesn't remember the exact brand name and says "spirit". Also assume the vxml program doesn't match spirit to sprite and generates a <nomatch> event and keeps reprompting the user to say his favorite soda, etc.

What I want to do, is break the <nomatch> loop, (say after the second <nomatch> event) and help the user by suggesting what his favorite soda pop is... "did you perhaps say <sugestion>?"...

Obviously, I want to suggest the soda whose name is the closest to whatever soda name the user said..... for that I either need to get some sort of ranking on which of the grammar elements (pepsi, sprite, coka cola or tab) was the "closest"... even though the VXML engine decided that none of them passed the threshold and were a match.

Question: can you get an array with match scores for each of the grammar elements ? 

I also thought about doing a simple edit-distance match on the string  the user spoke and the soda's as defined in the grammar, but I would prefer the  ranking or score list instead.

The last resort I have is to suggest a random soda... in this example I would have a 25% chance of making the application look intelligent; I like to do better.



MattHenry
8/24/2006 11:07 AM (EDT)


Let's tackle these questions one by one:

[b]Is there any way to access to shadow variables inside a <nomatch> block ?[/b]

- This feature is currently not available on our platform, but we do have this in our queue to add this feature request. It is my understanding that the inclusion of this feature will take some significant engineering to enable, so I do not have a specific deployment date at this time.

[b]Question: can you get an array with match scores for each of the grammar elements ?[/b]

- I think what you'd really want to use is some nBest post processing, which will output an array of possible matches ranked by probabaility. Check the very next tutorial in our docset for details.


~Matthew henry

emeijer
9/28/2006 4:44 AM (EDT)
okay, but to use the nBest technique, I still need to have at least a match with one of the items in the grammar; only once there is a match, then I will have access to  an array with lastresult$ values and can  try to suggest to the user he wants a sprite.

Going back to the example, if the user meant to say sprite, but said spirit instead with wasn't matched, then  I could tweak the "confidencelevel" property; i.e. lower it enough such that spirit will match at least with one of them (hopefully with sprite).. but I guess if you lower the confidence level enough, you will get false matches on coke, pepsi and anything else ... I am not so sure if this an alternative for getting access to the lastresult$ values during nomatch events, is it ?
MattHenry
9/29/2006 12:38 AM (EDT)

Edwin,


You are correct in your understanding about the n-best array in how it relates to a Nomatch event: My last posting on the subject of match scores wasn't really in context with the topic of getting array values back in an OOGNI event, but was a generalistic response: Apologies if I didn't read into the reasoning behind your question accurately.

As this is the case, the abiality to access the array values in a nomatch event is going to be pending the deployment of this feature at the platform scope. I can say that this is in our engineering queue, but I also wanted to again caution you that this change to the browser is not a trivial one, and will take some time to code, and QA, and finally deploy.

Regards,

~Matthew Henry


awirtz
11/14/2006 8:47 PM (EST)
Edwin, might I suggest that for your scenario, the best solution might be to lower the confidence level to 0.1 so that the grammar (almost) always hits the "filled" block, then inside the "filled" block, use an "if" to compare lastresult$.confidence against your intended confidence cutoff, and based on the result of that logic, either accept the recognition as is, or attempt to confirm via yes/no the closest match. (if you also throw nBest into the mix, you can run down a list of probable matches from most to least likely, prompting yes/no on each if you wanted, but in my example, if the guess is wrong, I simply return to the original prompt.)

<?xml version="1.0" encoding="UTF-8"?>
<vxml version = "2.1">
<form>
  <field name="F_1" slot="F_1">
  <property name="confidencelevel" value="0.1"/>
  <prompt>
    What is your favorite soda pop?
    Is it sprite, pepsi cola, coca cola, or tab?
  </prompt>
  <grammar type="text/gsl">
    <![CDATA[[
    (coka cola)    { <F_1 "coke">  }
    [pepsi]        { <F_1 "pepsi">  }
    [sprite]      { <F_1 "sprite"> }
    [tab]          { <F_1 "tab">    }
    ]]]>
  </grammar>
  <filled>
    <if cond="F_1$.confidence > 0.45">
    <goto nextitem="B_1"/>
    </if>
  </filled>
  </field>
  <field name="F_2" slot="F_2">
  <property name="confidencelevel" value="0.45"/>
  <prompt>
    Did you say <value expr="F_1"/>?
  </prompt>
  <grammar type="text/gsl">
    <![CDATA[[
    [yes]    { <F_2 "yes">  }
    [no]    { <F_2 "no">  }
    ]]]>
  </grammar>
  <filled>
    <if cond="F_2 == 'yes'">
    <goto nextitem="B_1"/>
    <else/>
    <assign name="F_1" expr="undefined"/>
    <assign name="F_2" expr="undefined"/>
    <goto nextitem="F_1"/>   
    </if>
  </filled>
  </field>
  <block name="B_1">
  <prompt>
    Good choice!  I like <value expr="F_1"/> too.
  </prompt>
  <exit/>
  </block>
</form>
</vxml>


Note: the line that reads "<if cond="F_1$.confidence > 0.45">" should have a "& g t ;" (minus the spaces) in the cond attribute instead of the ">", but the notes system here won't let me type it that way :(
VoxeoTony
11/14/2006 11:20 PM (EST)
Hello awirtz,

Thank you for posting a very good example for the forum.  This is a good was for folks to see nBest in action, and to capture misses and gently get them back to the question.

I hope this is useful to t_3 with developing VoiceXML applications.


Regards,

Tony
stuartgielen
6/4/2007 3:44 AM (EDT)
Is there an equivalent to the 'termchar' shadow variable for the field element?

I have the following scenario:
-ask caller to enter 8 digit number followed by hash, or enter * if they stuffed up and want to re-enter the number (ie "12345678#" means "ok, go ahead with this number" and "12348*" means "oops, I made a mistake and want to try again".

Both * and # are defined as input ending characters, but need to know which one was entered. I know I can remove the * as an input character and allow it in the grammar, but don't want the caller to wait a few seconds for the input to time-out.

I am new to this site, so please let me know if there's a better spot to ask this question.

Thanks,

Stuart Gielen.
MattHenry
6/4/2007 1:51 PM (EDT)



Hello Stuart,

There isn't an equivalent for the "termchar" shadow variable for an input field, (aside from the record element), but we can easily work around this. Considering your test case where we want 8 digits followed by # or *, we would want to take the following steps:

1) Set the 'termchar' property to a null value, (using "@" should do the trick for voice center 5.5). If you are using Prophecy, I can probably figure a way to specify this, if you can confirm the platform that you are using.

2) Specify a *nine* digit grammar for the field that includes the * and # keys as valid input.

3) Use some client-side scripting to pull out the last character entered, and define it as a variable value.

4) Use conditional logic to determine which 'termchar' the user pressed:

<if cond="mytermChar == '#'">
  <!-- do something -->
<elseif cond="mytermChar == '*'">
  <!-- do something else-->
  ...


Hope this helps out,


~Matthew henry
stuartgielen
6/5/2007 3:49 AM (EDT)
Hi Matthew,

Thanks for your quick response.

The problem is though that the user can cancel the input with the * after less than 8 digits, eg "1234*". And to avoid the end-of-input time-out we need to specify the * key as a termchar.

Thanks,

Stuart.
jbassett
6/5/2007 4:03 AM (EDT)
Hello,

You will most likely want to use the <link> attribute. You can set a key press to a global grammar. So in theory you should be able to define dtmf-star at the application root, and use link next to point to the beginning of the section that asks for the customer to input the numbers. This would simulate customer making a mistake, pressing star, and then getting reprompted.

1 ) Define an application root document: details on this can be found at the two links below; the second link contains sample code that illustrates this exact concept:


http://www.w3.org/TR/voicexml20/#dml1.5.2
http://docs.voxeo.com/voicexml/2.0/vxml.htm

See samples:
<AppRoot.vxml>
<Vxml application-xml:base>

For your global grammar, you will want to define a <link> within the approot. Something along the lines of this:

<link next="transferPage.xml">
  <grammar>[dtmf-star]</grammar>
</link>

The next attribute of <link> allows us to specify a URI to go to. This URI is a document (perhaps with an anchor to specify the starting dialog), or a dialog in the current document (just a bare anchor).

You can find code samples for the usage of this element as well within our documentation:

http://docs.voxeo.com/voicexml/2.0/link.htm

Let us know if you require any additional assistance,

Thanks,
Jesse Bassett
stuartgielen
6/7/2007 8:32 PM (EDT)
Hi Jesse,

Thanks for that, learned something new again ;)

The link attribute works fine, but again not straight away.
After we press * it still waits for the interdigittimeout to pass before the link event is triggered. So it still doesn't give us the desired result.

I do have a solution for the long term (but doesn't help me now). We are using Genesys Voice Platform 7.2. I had a look at the release notes for 7.5 which is due later this year and that includes a platform-specific property called "com.genesys.returntermchar" which will do the trick for us.

Thanks for all your responses.
jassy
9/19/2007 6:06 AM (EDT)
Hi Voxeo Team,

I have a problem with my code.
My vxml page :

<?xml version="1.0"?>
<vxml version="2.0" xmlns = "http://www.w3.org/2001/vxml">
<form id = "main">
<field name="getChoice">
<prompt> enter an item of your choice </prompt>
<grammar src="main.grxml" type="application/srgs+xml"/>

<filled>
<prompt>  got it. you said <value expr="getChoice$.interpretation"/> and the shadow variables are <value expr="getChoice$.confidence"/> and <value expr="getChoice$.inputmode"/> and  <value expr="getChoice$.utterance"/> </prompt>
</filled>
</field>
</form>
</vxml>

and my grammar simply looks like this :

<?xml version="1.0"?>
<grammar version="1.0" xmlns="http://www.w3.org/2001/06/grammar" mode="voice" xml:lang="en-US"  root="sayThing">
  <rule id="sayThing">
    <one-of>
          <item> paper <tag> getChoice ="paper" </tag> </item>
  <item> keyboard <tag> getChoice ="keyboard" </tag> </item>
  <item> mouse <tag> getChoice ="mouse" </tag> </item>
    </one-of>
  </rule>
</grammar>

When i have the same grammar file as an inline grammar, it is workingn perfectly.  It is playing all the shadow variable values.  But when i write the grammar an an external one, i have a problem.

It is not playing the confidence level of the input.
For ex: When i say "paper" as speech input, It plays "Got it. you said paper and the shadow variables are '' and 'voice' and 'paper'.

I ported my application on Avaya IR.
Someone please help me out on this.

Thanks and Regards,
Jassy.

MattHenry
9/19/2007 2:39 PM (EDT)


Hello Jassy,


Ideally, it would be beneficial to see application debugger logs that would help illustrate the problem, but I *think* I see what you are trying to do here. If this is meant to be an SRGS grammar with SISR formatted returns, then I think you will want to insert a semicolon after your return values:

  <item> paper <tag> getChoice ="paper"; </tag> </item>
  <item> keyboard <tag> getChoice ="keyboard"; </tag> </item>
  <item> mouse <tag> getChoice ="mouse"; </tag> </item>

Can you give this a try, and let us know how this works out?

~Matthew Henry



jassy
9/26/2007 2:15 AM (EDT)
Hi Henry,

I tried your suggestion too.  But no change in the result.
Anyway i could solve the problem.
On Avaya IR, to get the confidence, the shadow variable is "slotconf" which is platform-dependant.
Thanks a lot for the timely suggestion.

Regards,
Jassy
ryao
1/17/2008 4:24 PM (EST)
Hi,
I've inserted a menu$.utterance field into my log and notice some strange behaviors. By the way my application is an outbound dialing app.  When i dial my own cell for instance and answer it, .utterance recognizes what i'm saying based on my grammars.  But what I'm trying to do is call our IVR systems.. that say " Thank you for calling Company XYZ, to do this press 1... etc."  But I always get a nomatch returned.  Even when i put the confidence level to 0.1 as advised earlier it still doesn't recognize.  Using Avaya IR, btw.

I'm trying to create a monitoring application that dials IVR's every 5-10 minutes to make sure they are working fine.

Any ideas ?
VoxeoDustin
1/17/2008 10:48 PM (EST)
Hey ryao,

Would it be possible for you to enter a support ticket with a sample of the code you're using and what your trying to do so our support team can better assist you?

Thanks,
Dustin

login

  tutorial SubDialogs  |  TOC  |  tutorial Nbest Lesson  

© 2003-2008 Voxeo Corporation  |  Voxeo IVR  |  VoiceXML & CCXML IVR Developer Site