Creating VoiceXML Applications With Perl
by Kip Hampton
|
Pages: 1, 2
Creating Dynamic VoiceXML Applications
While the previous example hints at the potential of offering Web
content and services over the phone, the resulting "conversation"
between the caller and the VoiceXML application is too one-sided.
Fortunately VoiceXML offers several elements that are specially
designed for capturing user input. In addition, VoiceXML forms, like
the HTML forms that came before, can be used to capture data to pass
to the server via the standard HTTP GET and
POST methods.
For our final example we will create a dynamic VoiceXML document
based on POSTed data by creating a small application that
implements a limited (and somewhat dubious) "mystic oracle" that
appears to be sensitive to the caller's concerns. To keep things
simple, our oracle will be implemented in two parts; a plain VoiceXML
document containing a form to capture the caller's questions and a
dynamic, CGI-created document that formulates the responses to those
questions.
First let's create the form. We will begin with a simple greeting that will only be read the first time the user connects.
<?xml version="1.0"?>
<vxml>
<form id="greeting">
<block>
<audio>
Thank you for calling the mystic oracle!
</audio>
<goto next="#main_query"/>
</block>
</form>
Next we begin the main form. This form contains the sole
"query_type" field that will be used to capture the
caller's question. Pay special attention to the grammar
element. It allows VoiceXML developers to define just exactly what
input a given field will accept. In this case, for example, if the
caller's question contains any of the words "career", "job", "boss",
"coworker", or "department" the value of the "query_type" field will
be set to "career".
<form id="main_query">
<field name="query_type">
<grammar type="application/x-gsl" name="qtype">
<![CDATA[
[
[romance love sex boyfriend girlfriend] {<query_type "romance">}
[career job boss coworker department] {<query_type "career">}
[family husband wife mother father son daughter] {<query_type "family">}
]
]]>
</grammar>
The prompt element signals the VoiceXML gateway to
read a bit of text to the caller and wait for a response. In this
case, when the caller asks a question that contains one of the words
defined in the earlier grammar element, the application
thanks the caller and submits the data to the CGI portion of the
application using the POST method. The submit element's
namelist attribute allows us to specify which fields or
variables from the current document we would like to have submitted.
<prompt>
Clear your mind and concentrate on your question. <break/>
You may ask your question now.
</prompt>
<filled>
<audio>thank you.</audio>
<submit next="http://mysite.tld/cgi-bin/mystic_response.cgi"
method="POST"
namelist="query_type"/>
</filled>
Next we perform a bit of error-trapping to give the oracle a more
reasonable interface. The text contained by the nomatch
tag will be read if the user asks a question that does not contain any
of the words from our chosen grammar. The
reprompt element tells the VoiceXML browser to loop back
to and reread the previous prompt. If the caller fails
to ask a question at all, the noinput elements will be
read one at a time in the sequence defined by their individual
count attributes. If by the third reprompt
the caller has still not said anything, the application disconnects.
<nomatch>
The mystic oracle can only answer questions about romance, career,
or family matters. Please try again.
<reprompt/>
</nomatch>
<noinput count="1">
I can sense your apprehension.
<reprompt/>
</noinput>
<noinput count="2">
You must say something.
<reprompt/>
</noinput>
<noinput count="3">
Please call back when you are less stressed.
<disconnect/>
</noinput>
All that remains for this document is to close the "query_type"
field, its parent form, and the top-level
vxml elements.
</field>
</form>
</vxml>
Now let's create the CGI script that responds to the caller's question. This script will be passed a single POSTed parameter named "query_type" that will have the value romance, career, or family.
use strict;
use CGI qw(:standard);
my $q = CGI->new();
my $query_type = $q->param('query_type');
First we will generate a semi-random, characteristically vague answer to the caller's question.
my @intro_phrases = ('My sources say',
'All signs indicate that',
'Search your heart. You know');
my @responses = ('the answer is yes.',
'the answer is no.',
'it is too soon to tell.',
'the outlook is hazy. Please ask again later.');
my $response_text = $intro_phrases[int( rand ( scalar (@intro_phrases) ) )] .
' ' .
$responses[int( rand ( scalar (@responses) ) )];
Then we will create the VoiceXML output. Note how the inline Perl
variables are used both to include the randomly-generated answer to
the caller's question ($response_text) and to
create an illusory sense of personalized context by repeating the
general type of question that the caller asked
($query_type).
print qq*
<?xml version="1.0"?>
<vxml>
<form id="response">
<block>
<audio>
I sense your consternation.
Questions about $query_type can be very troublesome, indeed.
$response_text
</audio>
<goto next="#new_or_exit"/>
</block>
</form>
As a final feature, we will give the caller the opportunity to ask
our mystic oracle another question. If they say "no" to the following
prompt, the application will politely thank them and
disconnect; otherwise, they will be redirected back to
the main section of the previous document where they will be prompted
for a new query.
<form id="new_or_exit">
<field name="new_question">
<prompt>
Would you like to ask another question?
</prompt>
<grammar>
<![CDATA[
[
[yes] {<new_question "yes">}
[no] {<new_question "no">}
]
]]>
</grammar>
<filled>
<if cond="new_question=='no'">
<audio>Thank you for calling. Goodbye.</audio>
<disconnect/>
<else/>
<goto next="http://mysite.tld/vxml/mystic_prompt.xml#main_query"/>
</if>
</filled>
</field>
</form>
</vxml>
*;
A typical transcript of a call to the mystic oracle might look something like this:
Oracle: Thank you for calling the mystic oracle!
Clear your mind and concentrate on your question.
You may ask your question now.
Caller: Hmmmm. Should I take the new job I was just offered?
Oracle: Thank you.
I sense your consternation.
Questions about career can be very troublesome, indeed.
All signs indicate that the answer is yes.
Would you like to ask another question?
Caller: Yes, I would.
Oracle: Clear your mind and concentrate on your question.
...
Conclusions
Also in Perl and XML |
|
OSCON 2002 Perl and XML Review PDF Presentations Using AxPoint |
VoiceXML is much more than an alternative interface to the Web. It allows developers to extend their existing applications in new and useful ways, and it offers many unique opportunities for new development. As you may have guessed, though, that power and flexibility come with a hefty price tag: VoiceXML gateways (the hardware and software that connect the Web to the phone system, translate text to speech, interpret the VoiceXML markup, etc.) are not cheap. The good news is that many of prominent VoiceXML gateway providers offer free test and deployment environments to curious developers, so you can check out VoiceXML for yourself without breaking the bank.
Resources
- Download the sample code.
- The W3C's Voice Browser Activity Page
- Didier Martin's Hello, Voice World
- The VoiceXML Forum's FAQ
- VoiceXML Apps in Perl - potential error in example
2001-08-21 18:18:56 Brad Baker - VoiceXML Apps in Perl - potential error in example
2001-08-22 09:01:06 Kip Hampton