Asterisk权威指南/第十七章 交互式语音应答(IVR)

维基教科书,自由的教学读本

在这一章中,我们将讨论交互式语音应答(IVR)。如果你想了解自动接待,我们也为此写了一个章节(第15章)。IVR一词常被误用来指代自动接待,但它们两是完全不同的东西。

什么是IVR[编辑]

交互式语音应答系统的意义是获取呼叫者的输入,并基于这个输入执行动作(一般是在外部系统如一个数据库中查找数据),然后返回结果给呼叫者。IVR系统在过去是复杂、昂贵的,实施起来很麻烦。Asterisk改变了这一切。

Asterisk模糊了传统PBX和IVR系统的边界。Asterisk拨号计划的强大和灵活使得系统中几乎每一个分机都可以视为传统意义上的IVR。

IVR的内容[编辑]

IVR最基础的元素和自动接待很相似,但目的是不同的。我们需要最少一个提示告诉呼叫者IVR希望他输入的东西,一个从呼叫者处接受输入的技术,逻辑验证输入值的回复是否是有效输入,逻辑确认IVR下一步干嘛,最后,如果合适,还包括一个对于回应的存储机制。我们可能会把IVR想成一个决策树,尽管它不需要任何分支。例如,不管呼叫者做出什么选择,信息反馈可以向每个呼叫者呈现完全相同的提示集,并且所涉及的唯一路由逻辑是所给出的响应是否对于问题有效。

从呼叫者的角度来看,每个IVR需要从提示开始。这个初始提示将告诉呼叫者IVR是什么,并要求呼叫者提供第一个输入。 我们在第15章中讨论了自动接待的提示。之后,我们将会创建一个拨号方案,让你更好地管理多个语音提示。

第二个内容是IVR是一种用于从呼叫者接收输入的方法。回想一下,在第15章中我们讨论了用于接收新extension的Background()和WaitExten()应用程序。虽然你可以用Background()和WaitExten()创建IVR,但使用Read()应用程序通常更容易也更实用,该应用程序可以处理提示和捕获相应。Read()应用程序专门设计用于IVR系统。 其语法如下:

Read(variable[,filename[&filename2...]][,maxdigits][,option][,attempts][,timeout])

参数在表17-1中列出:

Argument Purpose
variable

变量

存储呼叫者的响应的变量。 最好的做法是给IVR中的每个变量赋予与该变量相关的提示类似的名称。 这将有助于以后如果出于商业原因或易用性你需要重新排列IVR的步骤。 命名你的变量var1,var2等,在短期内可能看起来很容易,但是在你的生命周期中,它会使修复错误更加困难。
prompt

提示

为呼叫者播放的文件(或文件列表,用&字符连接在一起),用于请求输入。文件名末尾省略格式扩展名。
maxdi gits

最大位数

允许输入的最大字符数。 在面临是/否问题和多项选择时,最佳做法是将此值限制为1。如果长度较长,呼叫方可以通过按#键来终止输入。
options

选项

s (skip)跳过

如果信道未回复立即退出

i (indication)指示

播放某种提示音(如拨号音)而不是播放提示

n (no answer)没有回答

从呼叫者方读取数字,即使线路尚未应答。

attempts尝试

播放提示的次数。如果呼叫者没有输入任何内容,则Read()应用程序自动重新提示用户。 默认是一次尝试。

timeout超时

呼叫者输入他的输入的秒数。Asterisk中的默认值为10秒,可以使用此选项对单个提示进行更改,也可以使用dialplan函数TIMEOUT(response)为整个会话分配值。

收到输入后,必须进行验证。 如果你不验证输入,你很有可能发现呼叫者抱怨不稳定的应用程序。处理你预期的输入是不够的; 你还需要处理你预期之外的输入。例如,呼叫者可能在IVR中会遇到困难并拨打0,在你的IVR中拨打0;你应该要很好地处理这个问题,让他们连接到可以帮助他们的人,或提供一个有用的替代方法。精心设计的IVR(就像任何程序一样)将尝试预测每一个可能的输入,并提供机制来适当处理该输入。

输入通过验证后,你可以将其提交给外部资源进行处理。可以通过数据库查询,URI提交,AGI程序或其他的多种方式来完成。这个外部应用程序会产生一个结果,你要将它返回给呼叫者。它可能会是一个详细的结果,例如“你的帐户余额是...”或简单的确认,例如“你的帐户已更新”。我们想不到现实世界中会存在呼叫者不需要返回的结果的情况。

有时IVR可能有多个步骤,因此结果可能包括来自呼叫者的请求更多信息,以便转到IVR应用的下一步。

设计非常复杂的具有数十甚至数百个可能路径的IVR系统也是可行的。我们在前面说过,我们还会再说一遍:人们不喜欢和你的手机系统通话,不管它是多么聪明。让你的IVR对呼叫者而言是简单的,他们更有可能从中获益。

一个绝赞的IVR

人们爱用的IVR的一个典例就是很多比萨送货服务使用的IVR:当你打电话订购时,IVR会查找你的呼叫ID,并说“如果你希望与上次完全一样的订单, 请按1。”

这就是它所做的所有工作,完美。

显然,这些公司可以设计出大量复杂的IVR,让你可以选择每一个细节(“选择放七粒谷物的面包皮,请按7”),但是有多少醉酒的饥饿客户能在早晨3点成功地应对导航?

最好的IVR是需要呼叫者输入最少的IVR。 按下1,你的披萨就在路上!

IVR设计注意事项[编辑]

当设计你自己的IVR时,需要牢记一些重要事项。我们把这些在你的IVR中要做和不要做的事情列在一起。

  • 保持简单
  • 有一个拨号选项可以连接到人工服务
  • 很好地处理错误

不要做

  • 认为IVR可以完全取代人类
  • 用你的IVR向人们展示你有多聪明
  • 尝试用IVR复制你的网站。
  • 如果你不能输入数字的话不要搭建IVR。没有人想要在电话拨号面板上拼写自己的名字
  • 强迫你的呼叫者听广告。记住,只要他们想,随时都可以挂电话。

用于搭建IVR的Asterisk模块[编辑]

可以在拨号计划中处理IVR的“前端”(与呼叫者交互的部分)。仅仅使用拨号计划来构建IVR系统(可能用astdb存储和检索数据)是可行的;然而,你通常需要与Asterisk外部的内容(IVR的“后端”)进行通信。

CURL[编辑]

Asterisk中的CURL()拨号计划功能允许你使用单行拨号计划代码涵盖整个Web应用程序。我们将在本章后面的示例IVR中使用它。虽然你会发现CURL()本身使用起来非常简单,但Web应用程序的创建需要Web开发经验。

func_odbc[编辑]

使用func_odbc,仅仅使用拨号计划代码和数据库查找功能,在Asterisk中开发一个极其复杂的应用程序也是可行的。 如果你不是一个强大的程序员,但是非常擅长Asterisk的拨号计划和数据库,那么你会喜欢func_odbc,就像我们一样。 具体请看第16章。

AGI[编辑]

Asterisk网关接口是将外部应用与Asterisk集成在一起的重要组成部分,我们给它单独分出一个章节。你可以在第21章找到更多信息。

AMI[编辑]

Asterisk Manager接口是一个套接字接口,你可以使用它来获取配置和状态信息,请求执行操作,并通知呼叫发生的事件。关于AMI我们也写了一整个章节。 你可以在第20章找到更多信息。

使用CURL实现的一个简单的IVR[编辑]

GNU / Linux程序cURL对于从URI检索数据很有用。在Asterisk中,CURL()是一个拨号计划功能。

接下来我们用CURL()实现一个非常简单的IVR例子。我们将从http://www.whatismyip.org请求我们的外部IP地址。

实际上,大多数IVR应用将会变得更加复杂。 包括CURL()的大多数使用也会变得复杂,因为URI可以返回一个巨大而可变的数据量,而绝大多数数据对于Asterisk来说是无法理解的。重点在于IVR不仅仅是拨号计划;它也非常关注由拨号计划触发的外部应用程序,它们正在进行IVR的真正工作。

在使用CURL()之前,必须确保它成功安装。

安装cURL模块

安装cURL很简单。 当你上次编译完Asterisk后它不在系统上,安装cURL完毕后你需要重新编译Asterisk,让它找到cURL依赖项并编译func_curl.so模块。

在 RHEL:

$ sudo yum -y install libcurl-devel

在Ubuntu:

$ sudo apt-get install libcurl4-openssl-dev

拨号计划

我们的示例IVR的拨号计划非常简单。CURL()函数将从http://www.whatismyip.org检索我们的IP地址,然后SayAlpha()将向呼叫者说出结果:

exten => *764,1,Verbose(2, Run CURL to get IP address from whatismyip.org)

same => n,Answer() same => n,Set(MyIPAddressIs=${CURL(http://www.whatismyip.org/)})

same => n,SayAlpha(${MyIPAddressIs})

same => n,Hangup()

这样的简单是不可思议的。在传统的IVR系统中,这种事情可能需要几天的时间才能完成。

一个记录提示的应用[编辑]

在第15章中,我们创建了一个简单的拨号计划来记录提示。这是相当有限的,因为它只记录了一个文件名,因此需要复制每一个提示文件才能记录新的提示。在这里,我们扩展了它以创建一个完整的记录提示的菜单:

[prompts]

exten => s,1,Answer

exten => s,n,Set(step1count=0) ; Initialize counters

; If we get no response after 3 times, we stop asking

same => n(beginning),GotoIf($[${step1count} > 2]?end)

same => n,Read(which,prompt-instructions,3)

same => n,Set(step1count=$[${step1count} + 1])

; All prompts must be 3 digits in length

same => n,GotoIf($[${LEN(${which})} != 3]?beginning)

same => n,Set(step1count=0) ; Successful response; reset counters

same => n,Set(step2count=0)

same => n(step2),Set(step2count=$[${step2count} + 1])

same => n,GotoIf($[${step2count} > 2]?beginning) ; No response after 3 tries

; If the file doesn't exist, then don't ask whether to play it

same => n,GotoIf($[${STAT(f,${which}.wav)} = 0]?recordonly)

same => n,Background(prompt-tolisten)

same => n(recordonly),Background(prompt-torecord)

same => n,WaitExten(10) ; Wait 10 seconds for a response

same => n,Goto(step2)

exten => 1,1,Set(step2count=0)

same => n,Background(${which})

same => n,Goto(s,step2)

exten => 2,1,Set(step2count=0)

same => n,Playback(prompt-waitforbeep)

same => n,Record(${CHANNEL(uniqueid)}.wav)

same => n(listen),Playback(${CHANNEL(uniqueid)})

same => n,Set(step3count=0)

same => n,Read(saveornot,prompt-1tolisten-2tosave-3todiscard,1)

same => n,GotoIf($["${saveornot}" = "1"]?listen)

same => n,GotoIf($["${saveornot}" = "2"]?saveit)

same => n,System(rm -f /var/lib/asterisk/sounds/${CHANNEL(uniqueid)}.wav)

same => n,Goto(s,beginning)

same => n(saveit),System(mv -f ${CHANNEL(uniqueid)}.wav ${which}.wav)

same => n,Playback(prompt-saved)

same => n,Goto(s,beginning)

在此系统中,提示符的名称不再是描述性的;相反,它是一个数字。这意味着你可以使用相同的机制记录更多种类的提示,但是取舍是你的提示将不再具有描述性名称。

语音识别和文字转语音[编辑]

虽然在大多数情况下,IVR系统向呼叫者提供预先记录的提示并通过拨号面板接受输入,但也可以:a)人为地生成提示,通常被称为文本到语音;b)通过语音识别引擎接受口头输入。

虽然能够与机器进行智能对话的概念是科学家们长期以来对我们的承诺,但实际的科学依然是复杂和错误的。尽管电脑具有惊人的功能,但电脑不适合欣赏人类言语微妙的细微差别。

话虽如此,应该指出的是,在过去的50年中,文字和言语表达方面都取得了惊人的进展。为一个非常具体的目的而精心设计的系统可以很好地工作。

不管市场营销人员怎么说,你的电脑仍然无法与你交谈,如果你正在考虑将你的电话系统与这些技术相结合的任何系统,你需要牢记这一点。

文字转语音[编辑]

文本到语音(也称为语音合成)要求系统能够用存储的数据人为地构建语音。虽然如果我们简单地给字母分配声音,并让计算机在读取字母时产生每个声音这个想法很吸引人,但英文语言并不完全是注音的。

表面上,关于电脑的想法是非常有吸引力的,实际上它的实用性有限。有关文本到语音与Asterisk的集成的更多信息,请参见第18章。

语音识别[编辑]

一旦我们使电脑能与我们交谈,我们自然就想要和他们进行交谈。任何尝试学习外语的人都可以认识到教授电脑来认识语言的复杂性;而且,语音识别要考虑到,在计算机可以理解这些单词之前,必须先将音频转换为数字格式。这个挑战比起设想的还要大。例如,作为人类,我们自然能够认识到与狗叫或汽车喇叭的声音不同的语言。对于电脑来说,这是一件非常复杂的事情。此外,对于基于电话的语音识别系统,接收到的音频总是具有非常低的保真度,因此计算机工作时将获得更少的信息来进行处理。

Asterisk没有内置语音识别,但是有许多第三方语音识别软件包与Asterisk集成。其中大部分内容超出了本书的范围,因为这些应用程序在Asterisk外部。

总结[编辑]

Asterisk作为IVR平台已经非常受欢迎。这本书在许多方面都是教你应用于IVR开发的技术。虽然主流媒体只注重Asterisk作为“免费PBX”,但实际情况是,Asterisk正在悄悄地掀起一场IVR行业风暴。在很多具有一定规模的组织中,Linux系统管理员都可能是使用Asterisk来解决以前无法解决或难以解决的电话问题的。这是一场隐秘的革命,但相对于它的无名却不甚重要。

如果你使用IVR业务,你需要了解Asterisk。